Skip to content

Commit 971a0a9

Browse files
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
1 parent bcd2425 commit 971a0a9

1 file changed

Lines changed: 47 additions & 25 deletions

File tree

computer_vision/cannyedge.py

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Canny Edge Detector - It is used to identify edges in images.
2+
Canny Edge Detector - It is used to identify edges in images.
33
Implementation of the Canny Edge Detection algorithm using NumPy.
44
55
https://en.wikipedia.org/wiki/Canny_edge_detector
@@ -16,8 +16,8 @@ def grayscale(image: np.ndarray) -> np.ndarray:
1616
To convert RGB -> grayscale using luminance weights.
1717
"""
1818
return np.dot(image[..., :3], [0.299, 0.587, 0.114]).astype(np.uint8)
19-
#gray = 0.299R+0.587G+0.114B
20-
#np.uint8 = converts values to 8-bit integers(0-255)
19+
# gray = 0.299R+0.587G+0.114B
20+
# np.uint8 = converts values to 8-bit integers(0-255)
2121

2222

2323
def gaussian_kernel(kernel_size: int = 5, sigma: float = 1.4) -> np.ndarray:
@@ -28,15 +28,13 @@ def gaussian_kernel(kernel_size: int = 5, sigma: float = 1.4) -> np.ndarray:
2828
"""
2929
if kernel_size % 2 == 0:
3030
raise ValueError("kernel's size must be odd")
31-
#as we need a center
31+
# as we need a center
3232

3333
center = kernel_size // 2
3434

3535
x, y = np.mgrid[-center : center + 1, -center : center + 1]
36-
#assigns weights, center gets largest while farther pixels get smaller values.
37-
kernel = (1 / (2 * pi * sigma**2)) * np.exp(
38-
-((x**2 + y**2) / (2 * sigma**2))
39-
)
36+
# assigns weights, center gets largest while farther pixels get smaller values.
37+
kernel = (1 / (2 * pi * sigma**2)) * np.exp(-((x**2 + y**2) / (2 * sigma**2)))
4038

4139
return kernel / kernel.sum()
4240

@@ -54,19 +52,25 @@ def convolve(image: np.ndarray, kernel: np.ndarray) -> np.ndarray:
5452
padding = kernel_size // 2
5553

5654
padded_image = np.pad(image, padding, mode="constant")
57-
#convolution near borders needs neighbors
55+
# convolution near borders needs neighbors
5856
output = np.zeros_like(image, dtype=np.float64)
5957

6058
for row in range(image_height):
6159
for column in range(image_width):
62-
region = padded_image[row : row + kernel_size,column : column + kernel_size]
60+
region = padded_image[
61+
row : row + kernel_size, column : column + kernel_size
62+
]
6363

6464
output[row, column] = np.sum(region * kernel)
65-
#multiply and add
65+
# multiply and add
6666
return output
6767

6868

69-
def gaussian_blur(image: np.ndarray,kernel_size: int = 5,sigma: float = 1.4,) -> np.ndarray:
69+
def gaussian_blur(
70+
image: np.ndarray,
71+
kernel_size: int = 5,
72+
sigma: float = 1.4,
73+
) -> np.ndarray:
7074
"""
7175
Blurring image using Gaussian filter.
7276
@@ -107,16 +111,19 @@ def sobel_gradients(image: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
107111
gradient_x = convolve(image, sobel_x)
108112
gradient_y = convolve(image, sobel_y)
109113

110-
gradient_magnitude = np.hypot(gradient_x, gradient_y)#edge strength
114+
gradient_magnitude = np.hypot(gradient_x, gradient_y) # edge strength
111115

112116
gradient_magnitude = (gradient_magnitude / gradient_magnitude.max()) * 255
113-
#normalize values to 0-255
117+
# normalize values to 0-255
114118
gradient_direction = np.arctan2(gradient_y, gradient_x)
115-
#computes edge direction angle, just tan^-1(Gy/Gx)
119+
# computes edge direction angle, just tan^-1(Gy/Gx)
116120
return gradient_magnitude, gradient_direction
117121

118122

119-
def non_maximum_suppression(magnitude: np.ndarray,direction: np.ndarray,) -> np.ndarray:
123+
def non_maximum_suppression(
124+
magnitude: np.ndarray,
125+
direction: np.ndarray,
126+
) -> np.ndarray:
120127
"""
121128
Suppress non-maximum gradient values.
122129
@@ -139,7 +146,7 @@ def non_maximum_suppression(magnitude: np.ndarray,direction: np.ndarray,) -> np.
139146

140147
current_angle = angle[row, column]
141148

142-
if (0 <= current_angle < 22.5 or 157.5 <= current_angle <= 180):
149+
if 0 <= current_angle < 22.5 or 157.5 <= current_angle <= 180:
143150
neighbor_1 = magnitude[row, column + 1]
144151
neighbor_2 = magnitude[row, column - 1]
145152

@@ -155,13 +162,20 @@ def non_maximum_suppression(magnitude: np.ndarray,direction: np.ndarray,) -> np.
155162
neighbor_1 = magnitude[row - 1, column - 1]
156163
neighbor_2 = magnitude[row + 1, column + 1]
157164

158-
if (magnitude[row, column] >= neighbor_1 and magnitude[row, column] >= neighbor_2):
165+
if (
166+
magnitude[row, column] >= neighbor_1
167+
and magnitude[row, column] >= neighbor_2
168+
):
159169
suppressed[row, column] = magnitude[row, column]
160170

161171
return suppressed
162172

163173

164-
def double_threshold(image: np.ndarray,low_threshold_ratio: float = 0.05,high_threshold_ratio: float = 0.15,) -> tuple[np.ndarray, int, int]:
174+
def double_threshold(
175+
image: np.ndarray,
176+
low_threshold_ratio: float = 0.05,
177+
high_threshold_ratio: float = 0.15,
178+
) -> tuple[np.ndarray, int, int]:
165179
"""
166180
Apply double thresholding.
167181
To separate strong edges from weak edges.
@@ -196,7 +210,11 @@ def double_threshold(image: np.ndarray,low_threshold_ratio: float = 0.05,high_th
196210
return result, weak, strong
197211

198212

199-
def hysteresis(image: np.ndarray,weak: int,strong: int = 255,) -> np.ndarray:
213+
def hysteresis(
214+
image: np.ndarray,
215+
weak: int,
216+
strong: int = 255,
217+
) -> np.ndarray:
200218
"""
201219
Track edges using hysteresis.
202220
@@ -230,7 +248,13 @@ class CannyEdgeDetector:
230248
Canny Edge Detector implementation.
231249
"""
232250

233-
def __init__(self,kernel_size: int = 5,sigma: float = 1.4,low_threshold_ratio: float = 0.05,high_threshold_ratio: float = 0.15,) -> None:
251+
def __init__(
252+
self,
253+
kernel_size: int = 5,
254+
sigma: float = 1.4,
255+
low_threshold_ratio: float = 0.05,
256+
high_threshold_ratio: float = 0.15,
257+
) -> None:
234258
self.kernel_size = kernel_size
235259
self.sigma = sigma
236260
self.low_threshold_ratio = low_threshold_ratio
@@ -259,9 +283,7 @@ def detect(self, image_path: str) -> np.ndarray:
259283
self.sigma,
260284
)
261285

262-
gradient_magnitude, gradient_direction = sobel_gradients(
263-
blurred_image
264-
)
286+
gradient_magnitude, gradient_direction = sobel_gradients(blurred_image)
265287

266288
suppressed_image = non_maximum_suppression(
267289
gradient_magnitude,
@@ -288,4 +310,4 @@ def detect(self, image_path: str) -> np.ndarray:
288310

289311
detected_edges = detector.detect("Screenshot 2026-05-11 065624.png")
290312

291-
cv2.imwrite("canny_edges.jpg", detected_edges)
313+
cv2.imwrite("canny_edges.jpg", detected_edges)

0 commit comments

Comments
 (0)