OpenCV 4.10.0
开源计算机视觉
|
在本章中,我们将会学习
Canny 边缘检测是一种流行的边缘检测算法。该算法由约翰·F·坎尼于
降噪
由于边缘检测容易受到图像中噪声的影响,第一步是使用 5x5 高斯滤波器去除图像中的噪声。我们在之前的章节中已经了解到这一点。
找出图像的强度梯度
平滑后的图像将分别使用 Sobel 核在水平和垂直方向进行滤波,以获得水平方向 ( \(G_x\)) 和垂直方向 ( \(G_y\)) 的一阶导数。通过这两个图像,我们可找到每个像素的边缘梯度和方向,如下所示
\[ 边缘\_梯度 \; (G) = \sqrt{G_x^2 + G_y^2} \\ 角度 \; (\theta) = \tan^{-1} \bigg(\frac{G_y}{G_x}\bigg) \]
梯度方向始终垂直于边缘。将其四舍五入为 4 个角度中的一个,代表垂直、水平和两个对角线方向。
非极大值抑制
在获取梯度幅度和方向后,对图像进行全面扫描以去除可能不构成边缘的任何不需要的像素。为此,在每个像素处,检查该像素在梯度方向的邻域中是否局部极大值。请查看下图
点 A 位于边缘上(垂直方向)。梯度方向与边缘垂直。点 B 和 C 位于梯度方向上。因此,需要使用点 B 和 C 检查点 A 是否形成局部极大值。如果是,则考虑用于下一阶段,否则将其抑制(设为零)。
简而言之,你获取的结果是带有“细边缘”的二值图像。
滞后阈值
此阶段决定哪些是真正的边缘,哪些不是。为此,我们需要两个阈值 minVal 和 maxVal。强度梯度大于 maxVal 的任何边缘肯定是边缘,而低于 minVal 的边缘肯定会是非边缘,因此将其舍弃。介于这两个阈值之间的那些根据其连通性归类为边缘或非边缘。如果它们连接到“确定边缘”像素,则认为它们是边缘的一部分。否则,它们也将被舍弃。请参见下图
边的 A 高于 maxVal,因此认为是“好边”。尽管边 C 低于 maxVal,但它连接到了边 A,所以也认为它是有用边,我们可以获得完整曲线。而边 B,尽管它高于 minVal 且与边 C 位于相同区域中,但它未连接到任何“好边”,因此它被丢弃。因此,我们必须根据具体的 minVal 和 maxVal 来获得正确的结果,这一点非常重要。
此阶段还删除了小像素噪声,假设边是较长的线。
因此,我们最终获得图中的粗边。
OpenCV 将上述所有内容置于单个函数 cv.Canny() 中。我们将了解如何使用它。第一个参数是我们的输入图像。第二个和第三个参数分别是我们的 minVal 和 maxVal。第四个参数是 aperture_size。这是 Sobel 内核的尺寸,用于查找图像梯度。默认值为 3。最后一个参数是 L2gradient,它指定用于查找梯度大小的方程。如果为 True,则它使用上面提到的更准确的方程,否则它使用以下函数:\(Edge\_Gradient \; (G) = |G_x| + |G_y|\)。默认值为 False。
在下方查看结果