File size: 3,977 Bytes
4cc2869
 
 
 
3d5d69a
4cc2869
 
 
 
3d5d69a
7a74dd9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fd32459
856f31e
 
8e75d7b
 
 
 
 
856f31e
8e75d7b
 
fd32459
7a74dd9
 
 
 
 
4cc2869
7a74dd9
 
 
 
 
 
 
 
 
4cc2869
7a74dd9
 
4cc2869
7a74dd9
 
4cc2869
7a74dd9
 
 
 
 
 
38b98e3
41bdd67
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3d5d69a
41bdd67
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3d5d69a
 
41bdd67
 
3d5d69a
 
41bdd67
ad0c787
 
3d5d69a
be24af1
 
ad0c787
3d5d69a
ad0c787
 
 
 
 
3d5d69a
ad0c787
3d5d69a
 
 
 
 
 
 
 
 
 
be24af1
ad0c787
3d5d69a
 
ad0c787
3d5d69a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import cv2
import numpy as np
from registry import registry


@registry.register("Original")
def original(image):
    return image


@registry.register("Dot Effect", defaults={
    "dot_size": 10,
    "dot_spacing": 2,
    "invert": False,
}, min_vals={
    "dot_size": 1,
    "dot_spacing": 1,
}, max_vals={
    "dot_size": 20,
    "dot_spacing": 10,
}, step_vals={
    "dot_size": 1,
    "dot_spacing": 1,
})
def dot_effect(image, dot_size: int = 10, dot_spacing: int = 2, invert: bool = False):
    """
    ## Convert your image into a dotted pattern.

    **Args:**
    * `image` (numpy.ndarray): Input image (BGR or grayscale)
    * `dot_size` (int): Size of each dot
    * `dot_spacing` (int): Spacing between dots
    * `invert` (bool): Invert the dots

    **Returns:**
    * `numpy.ndarray`: Dotted image
    """
    # Convert to grayscale if image is color
    if len(image.shape) == 3:
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    else:
        gray = image

    # Apply adaptive thresholding to improve contrast
    gray = cv2.adaptiveThreshold(
        gray,
        255,
        cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
        cv2.THRESH_BINARY,
        25,  # Block size
        5    # Constant subtracted from mean
    )

    height, width = gray.shape
    canvas = np.zeros_like(gray) if not invert else np.full_like(gray, 255)

    y_dots = range(0, height, dot_size + dot_spacing)
    x_dots = range(0, width, dot_size + dot_spacing)

    dot_color = 255 if not invert else 0
    for y in y_dots:
        for x in x_dots:
            region = gray[y:min(y+dot_size, height), x:min(x+dot_size, width)]
            if region.size > 0:
                brightness = np.mean(region)

            # Dynamic dot sizing based on brightness
            relative_brightness = brightness / 255.0
            if invert:
                relative_brightness = 1 - relative_brightness

            # Draw circle with size proportional to brightness
            radius = int((dot_size/2) * relative_brightness)
            if radius > 0:
                cv2.circle(canvas,
                           (x + dot_size//2, y + dot_size//2),
                           radius,
                           (dot_color),
                           -1)

    return canvas


@registry.register("Pixelize", defaults={
    "pixel_size": 10,
}, min_vals={
    "pixel_size": 1,
}, max_vals={
    "pixel_size": 50,
}, step_vals={
    "pixel_size": 1,
})
def pixelize(image, pixel_size: int = 10):
    """
    ## Apply a pixelization effect to the image.

    **Args:**
    * `image` (numpy.ndarray): Input image (BGR or grayscale)
    * `pixel_size` (int): Size of each pixel block

    **Returns:**
    * `numpy.ndarray`: Pixelized image
    """
    height, width = image.shape[:2]

    # Resize the image to a smaller size
    small_height = height // pixel_size
    small_width = width // pixel_size
    small_image = cv2.resize(
        image, (small_width, small_height), interpolation=cv2.INTER_LINEAR)

    # Resize back to the original size with nearest neighbor interpolation
    pixelized_image = cv2.resize(
        small_image, (width, height), interpolation=cv2.INTER_NEAREST)

    return pixelized_image


@registry.register("Sketch Effect")
def sketch_effect(image):
    """
    ## Apply a sketch effect to the image.

    **Args:**
    * `image` (numpy.ndarray): Input image (BGR or grayscale)

    **Returns:**
    * `numpy.ndarray`: Sketch effect applied image
    """
    # Convert the image to grayscale
    if len(image.shape) == 3:
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    else:
        gray = image

    # Invert the grayscale image
    inverted_gray = cv2.bitwise_not(gray)

    # Apply Gaussian blur to the inverted image
    blurred = cv2.GaussianBlur(inverted_gray, (21, 21), 0)  # Fixed kernel size

    # Blend the grayscale image with the blurred inverted image
    sketch = cv2.divide(gray, 255 - blurred, scale=256)

    return sketch