边缘检测评判标准:
所有边缘都极易受到噪声的干扰,为了防止因噪声引起的错误检测,应对图像进行平滑处理滤除噪声,常用的低通滤波器为高斯滤波器,见 c v : : G a u s s i a n B l u r ( ) cv::GaussianBlur() cv::GaussianBlur()算子。
梯度是图像灰度值变化剧烈的地方,它可以通过梯度检测算子Roberts、Prewitt、Sobel等得到。Canny中用的梯度检测算子为Sobel算子,它由两个模板组成:
G
x
=
[
−
1
0
1
−
2
0
2
−
1
0
1
]
G_x=
G
y
=
[
1
2
1
0
0
0
−
1
−
2
1
]
G_y=
把这两个模板分别与图像进行卷积,得到水平方向的梯度
G
x
G_x
Gx和垂直方向的梯度
G
y
G_y
Gy,最终的梯度幅值
G
G
G由欧几里距离(L2范数)求得:
G
=
G
x
2
+
G
y
2
G=\sqrt{G_x^2+G_y^2}
G=Gx2+Gy2
由于平方和平方根开销较大,为了简化计算,梯度值也可由曼哈顿距离(L1范数)求得:
G
=
∣
G
x
∣
+
∣
G
y
∣
G=|G_x|+|G_y|
G=∣Gx∣+∣Gy∣
梯度辐角
θ
\theta
θ为:
θ
=
a
r
c
t
a
n
(
∣
G
y
∣
∣
G
x
∣
)
\theta=arctan(\frac {|G_y|}{|G_x|})
θ=arctan(∣Gx∣∣Gy∣)
这一步骤的目的是使边缘细化。非极大值抑制可以抑制那些局部不是梯度幅值最大的边缘,而保留下来的具有局部最大值的像素点正是灰度值变化最剧烈的地方。这里的局部最大值由 3 ∗ 3 3*3 3∗3的邻域内梯度方向上比较梯度值得到。
由于上一步得到的边缘仍有一小部分由于噪声或者颜色变化影响而不是真正的边缘,虽然他们的梯度幅值也满足局部最大值,但是与其他边缘相比,它们的梯度幅值较小。因此,Canny算法采用双阈值的方法,设置高、低两个阈值,通过判断:
强边缘需要被保留下来,弱边缘需要采用边缘跟踪的方法来判断是否为真正的边缘,在弱边缘的 3 ∗ 3 3*3 3∗3的邻域内,如果有强边缘,则说明该若边缘属于这个强边缘,则需要被保留,否则被剔除。
void cv::Canny(InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false)
Parameters
image 8-bit输入图像;
edges 输出边缘图像,8-bit单通道图像;
threshold1 低阈值;
threshold2 高阈值;
apertureSize Sobel算子滤波器核尺寸,默认3;
L2gradient 表示计算梯度幅值时是否使用L2范数,默认false,即采用L1范数;