Canny边缘检测
边缘检测评判标准:
- 低错误率:在图像中精确地检测出尽可能多的边缘,并尽量减少漏检和误检;
- 高定位精度:检测出的边缘点应该精确地定位于边缘的中心;
- 边缘唯一性:图像中的每条边缘只被标记一次,同时避免由于噪声干扰产生虚假边缘;
Canny边缘检测的四个步骤
1、平滑处理
所有边缘都极易受到噪声的干扰,为了防止因噪声引起的错误检测,应对图像进行平滑处理滤除噪声,常用的低通滤波器为高斯滤波器,见 c v : : G a u s s i a n B l u r ( ) cv::GaussianBlur() cv::GaussianBlur()算子。
2、梯度检测
梯度是图像灰度值变化剧烈的地方,它可以通过梯度检测算子Roberts、Prewitt、Sobel等得到。Canny中用的梯度检测算子为Sobel算子,它由两个模板组成:
G
x
=
[
−
1
0
1
−
2
0
2
−
1
0
1
]
G_x=\begin{bmatrix} -1 & 0&1\\ -2 & 0&2 \\-1&0&1\\ \end{bmatrix}
Gx=
−1−2−1000121
G
y
=
[
1
2
1
0
0
0
−
1
−
2
1
]
G_y=\begin{bmatrix} 1 & 2&1\\ 0 & 0&0 \\-1 &-2&1\\ \end{bmatrix}
Gy=
10−120−2101
把这两个模板分别与图像进行卷积,得到水平方向的梯度
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、NMS非极大值抑制
这一步骤的目的是使边缘细化。非极大值抑制可以抑制那些局部不是梯度幅值最大的边缘,而保留下来的具有局部最大值的像素点正是灰度值变化最剧烈的地方。这里的局部最大值由 3 ∗ 3 3*3 3∗3的邻域内梯度方向上比较梯度值得到。
- 当梯度方向为 θ = 0 ° \theta=0° θ=0°时,在 3 ∗ 3 3*3 3∗3的邻域内,当前像素与左右两个像素的梯度值进行比较,如果当前像素的幅值为最大时,则保留,否则剔除;
- 当梯度方向为 θ = 90 ° \theta=90° θ=90°时,在 3 ∗ 3 3*3 3∗3的邻域内,当前像素与上下两个像素的梯度值进行比较,如果当前像素的幅值为最大时,则保留,否则剔除;
- 当梯度方向为 θ = 135 ° \theta=135° θ=135°时,在 3 ∗ 3 3*3 3∗3的邻域内,当前像素与左上角与右下角两个像素的梯度值进行比较,如果当前像素的幅值为最大时,则保留,否则剔除;
- 当梯度方向为 θ = 45 ° \theta=45° θ=45°时,在 3 ∗ 3 3*3 3∗3的邻域内,当前像素与左下角和右上角两个像素的梯度值进行比较,如果当前像素的幅值为最大时,则保留,否则剔除;
4、滞后阈值处理
由于上一步得到的边缘仍有一小部分由于噪声或者颜色变化影响而不是真正的边缘,虽然他们的梯度幅值也满足局部最大值,但是与其他边缘相比,它们的梯度幅值较小。因此,Canny算法采用双阈值的方法,设置高、低两个阈值,通过判断:
- 当梯度幅值大于高阈值时,则该边缘为强边缘;
- 当梯度幅值小于低阈值时,则该边缘需要被剔除;
- 当梯度幅值介于高低阈值之间时,则该边缘为弱边缘;
强边缘需要被保留下来,弱边缘需要采用边缘跟踪的方法来判断是否为真正的边缘,在弱边缘的 3 ∗ 3 3*3 3∗3的邻域内,如果有强边缘,则说明该若边缘属于这个强边缘,则需要被保留,否则被剔除。
OpenCV算子
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范数;
参考
- 书籍:图像局部特征检测和描述
- https://docs.opencv.org/4.8.0/