Canny边缘检测
具体流程如下:
使用高斯滤波器,用以平滑图像,滤除噪声 (噪声对边缘像素点会有影响)
计算图像中的每个像素点的梯度强度和方向
应用非极大值抑制(Non-Maximum Supression),来消除边缘检测带来的杂散响应
极大值抑制:取不是最大的Class框,是极大值就被抑制而不见啦
非极大值抑制:取最大的Class框,不是极大值就被抑制而不见啦
应用双阈值(Double-Threshold)检测来确定真实和潜在的边缘
通过抑制孤立的筛选边缘最终完成边缘检测
一、 高斯滤波器
下面还是进行了归一化处理(平均)
H = [ 0.0924 0.1192 0.0924 0.1192 0.1538 0.1192 0.0924 0.1192 0.0924 ] H=\left[\begin{array}{lll}
0.0924 & 0.1192 & 0.0924 \\
0.1192 & 0.1538 & 0.1192 \\
0.0924 & 0.1192 & 0.0924
\end{array}\right] H = ⎣ ⎡ 0.0924 0.1192 0.0924 0.1192 0.1538 0.1192 0.0924 0.1192 0.0924 ⎦ ⎤
下面是阵列乘法的计算过程:
e = H ∗ A = [ h 11 h 12 h 13 h 21 h 22 h 23 h 31 h 32 h 33 ] ∗ [ a b c d e f g h i ] = sum ( [ a × h 11 b × h 12 c × h 13 d × h 21 e × h 22 f × h 23 g × h 31 h × h 32 i × h 33 ] ) e=H * A=\left[\begin{array}{lll}
\mathrm{h}_{11} & \mathrm{~h}_{12} & \mathrm{~h}_{13} \\
\mathrm{~h}_{21} & \mathrm{~h}_{22} & \mathrm{~h}_{23} \\
\mathrm{~h}_{31} & \mathrm{~h}_{32} & \mathrm{~h}_{33}
\end{array}\right] *\left[\begin{array}{ccc}
a & b & c \\
d & e & f \\
g & h & i
\end{array}\right]=\operatorname{sum}\left(\left[\begin{array}{lll}
\mathrm{a} \times \mathrm{h}_{11} & \mathrm{~b} \times \mathrm{h}_{12} & \mathrm{c} \times \mathrm{h}_{13} \\
\mathrm{~d} \times \mathrm{h}_{21} & \mathrm{e} \times \mathrm{h}_{22} & \mathrm{f} \times \mathrm{h}_{23} \\
\mathrm{~g} \times \mathrm{h}_{31} & \mathrm{~h} \times \mathrm{h}_{32} & \mathrm{i} \times \mathrm{h}_{33}
\end{array}\right]\right) e = H ∗ A = ⎣ ⎡ h 11 h 21 h 31 h 12 h 22 h 32 h 13 h 23 h 33 ⎦ ⎤ ∗ ⎣ ⎡ a d g b e h c f i ⎦ ⎤ = sum ⎝ ⎛ ⎣ ⎡ a × h 11 d × h 21 g × h 31 b × h 12 e × h 22 h × h 32 c × h 13 f × h 23 i × h 33 ⎦ ⎤ ⎠ ⎞ ,最终的这个 sum 值就是中心点值。
二、梯度和方向
G = G x 2 + G y 2 θ = arctan ( G y / G x ) 这里的 θ 取值范围为 [ − p i / 2 , p i / 2 ] 。 \begin{array}{l}
G=\sqrt{G_{x}^{2}+G_{y}^{2}} \\
\theta=\arctan \left(G_{y} / G_{x}\right)
\end{array}这里的\theta取值范围为[-pi / 2, pi / 2]。 G = G x 2 + G y 2 θ = arctan ( G y / G x ) 这里的 θ 取值范围为 [ − p i /2 , p i /2 ] 。
下面是利用Sobel算子得出的横纵两个方向的梯度值:
S x = [ − 1 0 1 − 2 0 2 − 1 0 1 ] S y = [ 1 2 1 0 0 0 − 1 − 2 − 1 ] \quad S_{x}=\left[\begin{array}{rrr}
-1 & 0 & 1 \\
-2 & 0 & 2 \\
-1 & 0 & 1
\end{array}\right] \quad S_{y}=\left[\begin{array}{ccc}
1 & 2 & 1 \\
0 & 0 & 0 \\
-1 & -2 & -1
\end{array}\right] S x = ⎣ ⎡ − 1 − 2 − 1 0 0 0 1 2 1 ⎦ ⎤ S y = ⎣ ⎡ 1 0 − 1 2 0 − 2 1 0 − 1 ⎦ ⎤
G x = S x ∗ A = [ − 1 0 1 − 2 0 2 − 1 0 1 ] ∗ [ a b c d e f g h i ] = sum ( [ − a 0 c − 2 d 0 2 f − g 0 i ] ) G_{x}=S_{x} * A=\left[\begin{array}{ccc}
-1 & 0 & 1 \\
-2 & 0 & 2 \\
-1 & 0 & 1
\end{array}\right] *\left[\begin{array}{ccc}
a & b & c \\
d & e & f \\
g & h & i
\end{array}\right]=\operatorname{sum}\left(\left[\begin{array}{ccc}
-a & 0 & c \\
-2 d & 0 & 2 f \\
-g & 0 & i
\end{array}\right]\right) G x = S x ∗ A = ⎣ ⎡ − 1 − 2 − 1 0 0 0 1 2 1 ⎦ ⎤ ∗ ⎣ ⎡ a d g b e h c f i ⎦ ⎤ = sum ⎝ ⎛ ⎣ ⎡ − a − 2 d − g 0 0 0 c 2 f i ⎦ ⎤ ⎠ ⎞
G y = S y ∗ A = [ 1 2 1 0 0 0 − 1 − 2 − 1 ] ∗ [ a b c d e f g h i ] = sum ( [ a 2 b c 0 0 0 − g − 2 h − i ] ) G_{y}=S_{y} * A=\left[\begin{array}{ccc}
1 & 2 & 1 \\
0 & 0 & 0 \\
-1 & -2 & -1
\end{array}\right] *\left[\begin{array}{ccc}
a & b & c \\
d & e & f \\
g & h & i
\end{array}\right]=\operatorname{sum}\left(\left[\begin{array}{ccc}
a & 2 b & c \\
0 & 0 & 0 \\
-g & -2 h & -i
\end{array}\right]\right) G y = S y ∗ A = ⎣ ⎡ 1 0 − 1 2 0 − 2 1 0 − 1 ⎦ ⎤ ∗ ⎣ ⎡ a d g b e h c f i ⎦ ⎤ = sum ⎝ ⎛ ⎣ ⎡ a 0 − g 2 b 0 − 2 h c 0 − i ⎦ ⎤ ⎠ ⎞
三、非极大值抑制
1. 方法一
利用已知点的梯度来计算未知点的梯度
得出点 c 的梯度后,若比 dump1 和 dump2 都大则保留(不是极大值就被抑制)
2. 方法二
四、双阈值检测
import cv2
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
def cv_show (name, img ):
cv2.imshow(name,img)
cv2.waitKey(0 )
cv2.destroyAllWindows()
五、上下限设置效果对比
img = cv2.imread('tgcf.png' , cv2.IMREAD_GRAYSCALE)
cv_show("gray" , img)
v1 = cv2.Canny(img, 80 , 150 )
v2 = cv2.Canny(img, 20 , 50 )
res = np.hstack([v1, v2])
cv_show('Compare' , res)
p = cv2.imread('Park.jpg' ,cv2.IMREAD_GRAYSCALE)
cv_show('Park' , p)
v1 = cv2.Canny(p, 100 , 200 )
v2 = cv2.Canny(p, 25 , 50 )
res = np.hstack([p, v1, v2])
cv_show('Compare' , res)