【文档翻译】OpenCV-Canny Edge Detection
原文 https://docs.opencv.org/3.1.0/da/d22/tutorial_py_canny.html
1. Goal
本章节我们将学到:
- Canny 边缘检测的概念;
- OpenCV 函数 cv2.Canny() 的使用;
2. Theory
Canny 边缘检测是一个相当流行的边缘检测算法,它由 John F. Canny 提出。该算法是一个多步骤的算法,接下来我们将介绍其中的每一个步骤。
2.1 Noise Reduction
由于边缘检测对图像中的噪点非常敏感,所以第一步就是过滤到图像中的噪声。这一步通过一个 5x5 的高斯滤波完成,即对图像进行模糊处理。
2.2 Finding Intensity Gradient of the Image
模糊处理后的图像用一个 Sobel 算子对其在垂直和水平方向计算一阶偏导 $G_x$ 和 $G_y$。通过 $G_x$ 和 $G_y$ 就可以得到图像中每一个像素的梯度及其方向,梯度及其方向计算如下:
梯度方向永远垂直于边,它可以是四个角点之一,分别代表垂直、水平和两条对角线方向。
2.3 Non-maximum Suppression
当得到梯度大小及其方向后,将对整幅图像进行扫描以排除掉那些不会是构成边的像素。为了达到这个目的,在每一个像素都将检查该像素在其梯度方向上是否是局部最大值。
794
点 A 位于垂直方向的边上,其梯度方向垂直于边。点 B 和 C 在点 A 的梯度方向上。如果在点 A、B、C 中,A 为最大值(局部最大值),那么进行下一步。如果不是,则该点被排除(置为0)。
2.4 Hysteresis Thresholding
这一步判断在上一步得出的边界中,哪些是真正的边,哪些不是。为了达到这个目的,需要两个阈值 minVal 和 maxVal。任何梯度值大于 maxVal 的边界都将被当做真正的边,梯度值小于 minVal 的边界都将被忽略。处于 minVal 和 maxVal 之间的边界将根据他是否与真正的边连同来判断。如果其与真正的边相连,那么它将被当做真正的边,如果没有真正的边与之相连,那么它也将被忽略。如下图所示:
1179
边 A 中像素梯度大于 maxVal 的部分是真正的边,边 C 是边 A 中小于 maxVal 的部分,但它与边 A 相连,所以它也当做是真正的边。这样就得到的完整的曲线边界。但是边 B 与边 C 一样位于 minVal 和 maxVal 之间,但是由于它没有真正的边与其相连,所以边 B 将被忽略。因此采用恰当的 minVal 和 maxVal 值对于获取正确的结果十分重要。
由于这一步中假设边是长边,所以该步骤中也能过滤掉一些小的像素噪声。
3. Canny Edge Detection in OpenCV
OpenCV 将上述的所有步骤都封装到了一个函数中,cv2.Canny()。接下来将描述如何使用该函数。
1 | Python: |
第一个参数 image 是输入的图像,第二个和第三个参数是 minVal 和 maxVal 的值。第四个参数是输出的灰度图像,其与输入图像大小一致,第五个参数是 Sobel 算子的大小,默认是 3。最后一个参数默认为 false,即使用 $norm = |dI/dx| + |dI/dy|$ 来近似计算梯度大小。如果为 true 则使用 $norm = \sqrt{(dI/dx)^2 + (dI/dy)^2}$ 来更加精确的计算梯度大小。
1 | import cv2 |
结果如下:
3560