1
+ from scipy import ndimage
2
+ from scipy .ndimage .filters import convolve
3
+
4
+ from scipy import misc
5
+ import numpy as np
6
+
7
+
8
+ class cannyEdgeDetector :
9
+ def __init__ (self , imgs , sigma = 1 , kernel_size = 5 , weak_pixel = 75 , strong_pixel = 255 , lowthreshold = 0.05 ,
10
+ highthreshold = 0.15 ):
11
+ self .imgs = imgs
12
+ self .imgs_final = []
13
+ self .img_smoothed = None
14
+ self .gradientMat = None
15
+ self .thetaMat = None
16
+ self .nonMaxImg = None
17
+ self .thresholdImg = None
18
+ self .weak_pixel = weak_pixel
19
+ self .strong_pixel = strong_pixel
20
+ self .sigma = sigma
21
+ self .kernel_size = kernel_size
22
+ self .lowThreshold = lowthreshold
23
+ self .highThreshold = highthreshold
24
+ return
25
+
26
+ def gaussian_kernel (self , size , sigma = 1 ):
27
+ size = int (size ) // 2
28
+ x , y = np .mgrid [- size :size + 1 , - size :size + 1 ]
29
+ normal = 1 / (2.0 * np .pi * sigma ** 2 )
30
+ g = np .exp (- ((x ** 2 + y ** 2 ) / (2.0 * sigma ** 2 ))) * normal
31
+ return g
32
+
33
+ def sobel_filters (self , img ):
34
+ Kx = np .array ([[- 1 , 0 , 1 ], [- 2 , 0 , 2 ], [- 1 , 0 , 1 ]], np .float32 )
35
+ Ky = np .array ([[1 , 2 , 1 ], [0 , 0 , 0 ], [- 1 , - 2 , - 1 ]], np .float32 )
36
+
37
+ Ix = ndimage .filters .convolve (img , Kx )
38
+ Iy = ndimage .filters .convolve (img , Ky )
39
+
40
+ G = np .hypot (Ix , Iy )
41
+ G = G / G .max () * 255
42
+ theta = np .arctan2 (Iy , Ix )
43
+ return (G , theta )
44
+
45
+ def non_max_suppression (self , img , D ):
46
+ M , N = img .shape
47
+ Z = np .zeros ((M , N ), dtype = np .int32 )
48
+ angle = D * 180. / np .pi
49
+ angle [angle < 0 ] += 180
50
+
51
+ for i in range (1 , M - 1 ):
52
+ for j in range (1 , N - 1 ):
53
+ try :
54
+ q = 255
55
+ r = 255
56
+
57
+ # angle 0
58
+ if (0 <= angle [i , j ] < 22.5 ) or (157.5 <= angle [i , j ] <= 180 ):
59
+ q = img [i , j + 1 ]
60
+ r = img [i , j - 1 ]
61
+ # angle 45
62
+ elif (22.5 <= angle [i , j ] < 67.5 ):
63
+ q = img [i + 1 , j - 1 ]
64
+ r = img [i - 1 , j + 1 ]
65
+ # angle 90
66
+ elif (67.5 <= angle [i , j ] < 112.5 ):
67
+ q = img [i + 1 , j ]
68
+ r = img [i - 1 , j ]
69
+ # angle 135
70
+ elif (112.5 <= angle [i , j ] < 157.5 ):
71
+ q = img [i - 1 , j - 1 ]
72
+ r = img [i + 1 , j + 1 ]
73
+
74
+ if (img [i , j ] >= q ) and (img [i , j ] >= r ):
75
+ Z [i , j ] = img [i , j ]
76
+ else :
77
+ Z [i , j ] = 0
78
+
79
+
80
+ except IndexError as e :
81
+ pass
82
+
83
+ return Z
84
+
85
+ def threshold (self , img ):
86
+
87
+ highThreshold = img .max () * self .highThreshold ;
88
+ lowThreshold = highThreshold * self .lowThreshold ;
89
+
90
+ M , N = img .shape
91
+ res = np .zeros ((M , N ), dtype = np .int32 )
92
+
93
+ weak = np .int32 (self .weak_pixel )
94
+ strong = np .int32 (self .strong_pixel )
95
+
96
+ strong_i , strong_j = np .where (img >= highThreshold )
97
+ zeros_i , zeros_j = np .where (img < lowThreshold )
98
+
99
+ weak_i , weak_j = np .where ((img <= highThreshold ) & (img >= lowThreshold ))
100
+
101
+ res [strong_i , strong_j ] = strong
102
+ res [weak_i , weak_j ] = weak
103
+
104
+ return (res )
105
+
106
+ def hysteresis (self , img ):
107
+
108
+ M , N = img .shape
109
+ weak = self .weak_pixel
110
+ strong = self .strong_pixel
111
+
112
+ for i in range (1 , M - 1 ):
113
+ for j in range (1 , N - 1 ):
114
+ if (img [i , j ] == weak ):
115
+ try :
116
+ if ((img [i + 1 , j - 1 ] == strong ) or (img [i + 1 , j ] == strong ) or (img [i + 1 , j + 1 ] == strong )
117
+ or (img [i , j - 1 ] == strong ) or (img [i , j + 1 ] == strong )
118
+ or (img [i - 1 , j - 1 ] == strong ) or (img [i - 1 , j ] == strong ) or (
119
+ img [i - 1 , j + 1 ] == strong )):
120
+ img [i , j ] = strong
121
+ else :
122
+ img [i , j ] = 0
123
+ except IndexError as e :
124
+ pass
125
+
126
+ return img
127
+
128
+ def detect (self ):
129
+ imgs_final = []
130
+ for i , img in enumerate (self .imgs ):
131
+ self .img_smoothed = convolve (img , self .gaussian_kernel (self .kernel_size , self .sigma ))
132
+ self .gradientMat , self .thetaMat = self .sobel_filters (self .img_smoothed )
133
+ self .nonMaxImg = self .non_max_suppression (self .gradientMat , self .thetaMat )
134
+ self .thresholdImg = self .threshold (self .nonMaxImg )
135
+ img_final = self .hysteresis (self .thresholdImg )
136
+ self .imgs_final .append (img_final )
137
+
138
+ return self .imgs_final
0 commit comments