![]() |
OpenCV 4.12.0
开源计算机视觉
|
Canny 边缘检测是一种流行的边缘检测算法。它由 John F. Canny 于 1986 年开发。它是一个多阶段的算法,我们将逐个阶段进行讲解。
噪声降低
由于边缘检测容易受到图像中噪声的影响,因此第一步是使用 5x5 高斯滤波器去除图像中的噪声。我们已经在之前的章节中看到了这一点。
查找图像的强度梯度
然后使用 Sobel 核在水平和垂直方向上对平滑后的图像进行滤波,以获得水平方向 ( \(G_x\)) 和垂直方向 ( \(G_y\)) 的一阶导数。从这两个图像中,我们可以找到每个像素的边缘梯度和方向,如下所示
\[ Edge\_Gradient \; (G) = \sqrt{G_x^2 + G_y^2} \\ Angle \; (\theta) = \tan^{-1} \bigg(\frac{G_y}{G_x}\bigg) \]
梯度方向始终垂直于边缘。它被四舍五入到四个角度之一,分别代表垂直、水平和两个对角线方向。
非极大值抑制
在获得梯度幅度和方向后,将对图像进行完整扫描,以移除任何可能不构成边缘的无关像素。为此,在每个像素处,检查像素是否是其邻域中梯度方向上的局部最大值。查看下面的图像
点 A 在边缘上(垂直方向)。梯度方向垂直于边缘。点 B 和 C 在梯度方向上。因此,检查点 A 与点 B 和 C,以查看它是否形成局部最大值。如果是,则将其考虑用于下一阶段,否则,将其抑制(置零)。
简而言之,您获得的结果是具有“细边缘”的二值图像。
迟滞阈值处理
此阶段决定哪些边缘是真正的边缘,哪些不是。为此,我们需要两个阈值 minVal 和 maxVal。强度梯度大于 maxVal 的任何边缘肯定都是边缘,而低于 minVal 的边缘肯定不是边缘,因此会被丢弃。那些介于这两个阈值之间的边缘根据它们的连通性被分类为边缘或非边缘。如果它们连接到“确定边缘”像素,则它们被认为是边缘的一部分。否则,它们也会被丢弃。见下图
边缘 A 高于 maxVal,因此被认为是“确定边缘”。虽然边缘 C 低于 maxVal,但它连接到边缘 A,因此也被认为是有效边缘,我们得到了完整的曲线。但是边缘 B,尽管它高于 minVal 并且与边缘 C 处于同一区域,但它没有连接到任何“确定边缘”,因此被丢弃。因此,我们必须相应地选择 minVal 和 maxVal 才能获得正确的结果,这一点非常重要。
此阶段还会消除小像素噪声,因为假设边缘是长线。
因此,我们最终得到的是图像中的强边缘。
我们使用函数:cv.Canny(图像, 边缘, 阈值1, 阈值2, apertureSize = 3, L2gradient = false)
| image | 8 位输入图像。 |
| edges | 输出边缘图;单通道 8 位图像,它与图像具有相同的大小。 |
| threshold1 | 用于滞后过程的第一个阈值。 |
| threshold2 | 用于滞后过程的第二个阈值。 |
| apertureSize | Sobel 算子的孔径大小。 |
| L2gradient | 指定用于查找梯度幅度的公式。如果为 True,则使用上面提到的更精确的公式,否则使用此函数:\(Edge\_Gradient \; (G) = |G_x| + |G_y|\)。 |