ngd1210 commited on
Commit
7a74dd9
·
1 Parent(s): 1eba945

Added dot effect filter with customizable parameters

Browse files

- Introduces dot effect filter
- Supports dot size and spacing customization
- Includes invert option for dark mode
- Dynamic dot sizing based on brightness
- Removes unused filters for simplicity

Files changed (2) hide show
  1. .gitignore +1 -0
  2. filters.py +54 -60
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ .aider*
filters.py CHANGED
@@ -2,73 +2,67 @@ import cv2
2
  import numpy as np
3
  from registry import registry
4
 
 
5
  @registry.register("Original")
6
  def original(image):
7
  return image
8
 
9
- @registry.register("Grayscale")
10
- def grayscale(image):
11
- return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
- @registry.register("Gaussian Blur", defaults={'kernel_size': 15}, min_vals={'kernel_size': 3}, max_vals={'kernel_size': 31}, step_vals={'kernel_size': 2})
14
- def gaussian_blur(image, kernel_size: int = 15):
15
- return cv2.GaussianBlur(image, (kernel_size, kernel_size), 0)
 
 
 
 
 
 
16
 
17
- @registry.register("Pencil Sketch")
18
- def pencil_sketch(image):
19
- gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
20
- inverted = cv2.bitwise_not(gray)
21
- blurred = cv2.GaussianBlur(inverted, (21, 21), 0)
22
- inverted_blurred = cv2.bitwise_not(blurred)
23
- return cv2.divide(gray, inverted_blurred, scale=256.0)
24
 
25
- @registry.register("Sepia")
26
- def sepia(image):
27
- kernel = np.array([
28
- [0.393, 0.769, 0.189],
29
- [0.349, 0.686, 0.168],
30
- [0.272, 0.534, 0.131]
31
- ])
32
- return cv2.transform(image, kernel)
33
 
34
- @registry.register("Edge Enhance", defaults={'intensity': 1.5}, min_vals={'intensity': 0.5}, max_vals={'intensity': 5.0}, step_vals={'intensity': 0.1})
35
- def edge_enhance(image, intensity: float = 1.5):
36
- kernel = np.array([
37
- [-1 * intensity, -1 * intensity, -1 * intensity],
38
- [-1 * intensity, 9 * intensity, -1 * intensity],
39
- [-1 * intensity, -1 * intensity, -1 * intensity]
40
- ])
41
- return cv2.filter2D(image, -1, kernel)
42
 
43
- @registry.register("Canny Edge", defaults={'lower_threshold': 100, 'upper_threshold': 200, 'convert_to_gray': True}, min_vals={'lower_threshold': 0, 'upper_threshold': 255}, max_vals={'lower_threshold': 255, 'upper_threshold': 255}, step_vals={'lower_threshold': 1, 'upper_threshold': 1})
44
- def canny_edge(image, lower_threshold: int=100, upper_threshold: int=200, convert_to_gray: bool=True):
45
- if convert_to_gray and len(image.shape) == 3:
46
- gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
47
- else:
48
- gray = image
49
- edges = cv2.Canny(gray, lower_threshold, upper_threshold)
50
- return edges
51
 
52
- @registry.register("Sobel Edge", defaults={'dx': 1, 'dy': 0, 'kernel_size': 3, 'convert_to_gray': True}, min_vals={'dx': 1, 'dy': 1, 'kernel_size': 3}, max_vals={'dx': 2, 'dy': 2, 'kernel_size': 7}, step_vals={'dx': 1, 'dy': 1, 'kernel_size': 2})
53
- def sobel_edge(image, dx: int=1, dy: int=0, kernel_size: int=3, convert_to_gray: bool=True):
54
- """
55
- Applies the Sobel edge detector to detect horizontal or vertical edges.
56
-
57
- Args:
58
- img (numpy.ndarray): Input image (BGR or grayscale)
59
- dx (int): Order of derivative in x-direction (0 = no x-edge detection)
60
- dy (int): Order of derivative in y-direction (0 = no y-edge detection)
61
- kernel_size (int): Size of Sobel kernel (1, 3, 5, or 7)
62
- convert_to_gray (bool): Convert to grayscale first
63
-
64
- Returns:
65
- numpy.ndarray: Edge magnitude image
66
- """
67
- if convert_to_gray and len(image.shape) == 3:
68
- gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
69
- else:
70
- gray = image
71
- sobel = cv2.Sobel(gray, cv2.CV_64F, dx, dy, ksize=kernel_size)
72
- abs_sobel = cv2.convertScaleAbs(sobel)
73
-
74
- return abs_sobel
 
2
  import numpy as np
3
  from registry import registry
4
 
5
+
6
  @registry.register("Original")
7
  def original(image):
8
  return image
9
 
10
+ @registry.register("Dot Effect", defaults={
11
+ "dot_size": 10,
12
+ "dot_spacing": 2,
13
+ "invert": False,
14
+ }, min_vals={
15
+ "dot_size": 1,
16
+ "dot_spacing": 1,
17
+ }, max_vals={
18
+ "dot_size": 20,
19
+ "dot_spacing": 10,
20
+ }, step_vals={
21
+ "dot_size": 1,
22
+ "dot_spacing": 1,
23
+ })
24
+ def dot_effect(image, dot_size: int = 10, dot_spacing: int = 2, invert: bool = False):
25
+ # Convert to grayscale if image is color
26
+ if len(image.shape) == 3:
27
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
28
+ else:
29
+ gray = image
30
 
31
+ # Apply adaptive thresholding to improve contrast
32
+ gray = cv2.adaptiveThreshold(
33
+ gray,
34
+ 255,
35
+ cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
36
+ cv2.THRESH_BINARY,
37
+ 25, # Block size
38
+ 5 # Constant subtracted from mean
39
+ )
40
 
41
+ height, width = gray.shape
42
+ canvas = np.zeros_like(gray) if not invert else np.full_like(gray, 255)
 
 
 
 
 
43
 
44
+ y_dots = range(0, height, dot_size + dot_spacing)
45
+ x_dots = range(0, width, dot_size + dot_spacing)
 
 
 
 
 
 
46
 
47
+ dot_color = 255 if not invert else 0
48
+ for y in y_dots:
49
+ for x in x_dots:
50
+ region = gray[y:min(y+dot_size, height), x:min(x+dot_size, width)]
51
+ if region.size > 0:
52
+ brightness = np.mean(region)
 
 
53
 
54
+ # Dynamic dot sizing based on brightness
55
+ relative_brightness = brightness / 255.0
56
+ if invert:
57
+ relative_brightness = 1 - relative_brightness
 
 
 
 
58
 
59
+ # Draw circle with size proportional to brightness
60
+ radius = int((dot_size/2) * relative_brightness)
61
+ if radius > 0:
62
+ cv2.circle(canvas,
63
+ (x + dot_size//2, y + dot_size//2),
64
+ radius,
65
+ (dot_color),
66
+ -1)
67
+
68
+ return canvas