-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcanny_edge.py
120 lines (110 loc) · 4.01 KB
/
canny_edge.py
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
import numpy as np
from scipy import signal
from scipy.ndimage import filters
import matplotlib.pyplot as plt
from matplotlib import colors
def myCanny(image, tl, th):
'''Canny edge detection algorithm
inputs : Grayscale image , tl : low threshold, th : high threshold
output : Edge image or Canny image
Basic steps of canny are :
1. Image smoothing using gaussian kernel for de-noising
2. Getting gradient magnitude image
3. None maxima suppression:
Suppression of week edges at the same direction to have a thin edge
4. Double thresholding :
Suppress globally weak edges that bellow tl, and keep that above th
5. Edge tracking:
track remaining pixels with values in between tl and th. Suppress them
if they haven't a strong edge in its neighbors.
'''
# 1. Image smoothing
sigma = 1.4
im1 = filters.gaussian_filter(image, (sigma, sigma))
# 2. Getting gradient magnitude image
sobelx = np.array([[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]])
sobely = sobelx.T
Gx = signal.convolve2d(im1, sobelx, "same")
Gy = signal.convolve2d(im1, sobely, "same")
G = np.sqrt(Gx**2 + Gy**2)
# 3. None maxima suppression
# Getting gradient direction at first
theta = np.arctan2(Gy, Gx)
theta = 180 + (180/np.pi)*theta
x0, y0 = np.where(((theta < 22.5)+(theta > 157.5)*(theta < 202.5)
+ (theta > 337.5)) == True)
x45, y45 = np.where(((theta > 22.5)*(theta < 67.5)
+ (theta > 202.5)*(theta < 247.5)) == True)
x90, y90 = np.where(((theta > 67.5)*(theta < 112.5)
+ (theta > 247.5)*(theta < 292.5)) == True)
x135, y135 = np.where(((theta > 112.5)*(theta < 157.5)
+ (theta > 292.5)*(theta < 337.5)) == True)
# Apply none-max suppression
theta[x0, y0] = 0
theta[x45, y45] = 1
theta[x90, y90] = 2
theta[x135, y135] = 3
dirs = theta
edgeCoords = np.array(G.nonzero()).T
for c in edgeCoords:
gradDir = dirs[c[0], c[1]]
try:
if gradDir == 0:
idx = [[c[0], c[1]+1],
[c[0], c[1]-1],
[c[0], c[1]+2],
[c[0], c[1]-2]]
elif gradDir == 1:
idx = [[c[0]+1, c[1]+1],
[c[0]-1, c[1]-1],
[c[0]+2, c[1]+2],
[c[0]-2, c[1]-2]]
elif gradDir == 2:
idx = [[c[0]+1, c[1]],
[c[0]-1, c[1]],
[c[0]+2, c[1]],
[c[0]-2, c[1]]]
elif gradDir == 3:
idx = [[c[0]+1, c[1]-1],
[c[0]-1, c[1]+1],
[c[0]+2, c[1]-2],
[c[0]-2, c[1]+2]]
for i in idx:
if G[i[0], i[1]] > G[c[0], c[1]]:
G[c[0], c[1]] = 0
except:
pass
# 4. Double Thresholding
remainingEdges = np.array(G.nonzero()).T
for e in remainingEdges:
if G[e[0], e[1]] < tl:
G[e[0], e[1]] = 0
elif G[e[0], e[1]] > th:
G[e[0], e[1]] = 255
# 5. Edge tracking by hysteresis
remEdges = np.array(G.nonzero()).T
for re in remEdges:
if G[re[0], re[1]] != 255:
try:
neighbors = G[re[0]-1:re[0]+2, re[1]-1:re[1]+2].flatten()
if np.max(neighbors) == 255:
G[re[0], re[1]] = 255
else:
G[re[0], re[1]] = 0
except:
G[re[0], re[1]] = 0
continue
return G
if __name__ == '__main__':
# Load Image
image = plt.imread("images/Lines.jpg")
# Extract value channel (intensity)
hsvImage = colors.rgb_to_hsv(image)
valIm = hsvImage[..., 2]
cannyIm = myCanny(valIm, 75, 150)
# Show Canny image
plt.set_cmap("gray")
plt.imshow(cannyIm)
plt.show()