【OpenCV学习笔记20】- Canny 边缘检测

发布时间:2024年01月23日

这是对于 OpenCV 官方文档中 图像处理 的学习笔记。学习笔记中会记录官方给出的例子,也会给出自己根据官方的例子完成的更改代码,同样彩蛋的实现也会结合多个知识点一起实现一些小功能,来帮助我们对学会的知识点进行结合应用。
如果有喜欢我笔记的请麻烦帮我关注、点赞、评论。谢谢诸位。

学习笔记:
学习笔记目录里面会收录我关于OpenCV系列学习笔记博文,大家如果有什么不懂的可以通过阅读我的学习笔记进行学习。
【OpenCV学习笔记】- 学习笔记目录

内容

  • Canny 边缘检测的概念
  • OpenCV 的功能: cv2.Canny()

理论

Canny 边缘检测是一种流行的边缘检测算法。它是由 John F. Canny 在 1986 年提出。

  1. 这是一个多阶段算法,我们将介绍算法的每一个步骤。
  2. 降噪
    由于边缘检测易受图像中的噪声影响,因此第一步是使用 5x5 高斯滤波器去除图像中的噪声。我们在前面的章节中已经介绍到了这一点。
  3. 寻找图像的强度梯度
    然后在水平和垂直方向上用 Sobel 内核对平滑后的图像进行滤波,以获得水平方向(G_x)和垂直方向(G_y)的一阶导数。从这两个图像中,我们可以找到每个像素的边缘梯度和方向,如下所示:
    在这里插入图片描述
    渐变方向始终垂直于边缘。它被四舍五入到表示垂直,水平和两个对角线方向的四个角度中的一个。
  4. 非最大抑制
    在获得梯度幅度和方向之后,完成图像的全扫描以去除可能不构成边缘的任何不需要的像素。为此,在每个像素处,检查像素是否是其在梯度方向上的邻域中的局部最大值。检查下图:
    在这里插入图片描述
    A 点位于边缘(垂直方向)。渐变方向与边缘垂直。 B 点和 C 点处于梯度方向。因此,用点 B 和 C 检查点 A,看它是否形成局部最大值。如果是这样,则考虑下一阶段,否则,它被抑制(归零)。
    简而言之,您得到的结果是具有“细边”的二进制图像。
  5. 滞后阈值
    这个阶段决定哪些边缘都是边缘,哪些边缘不是边缘。为此,我们需要两个阈值,minVal 和 maxVal。强度梯度大于 maxVal 的任何边缘肯定是边缘,而 minVal 以下的边缘肯定是非边缘,因此被丢弃。位于这两个阈值之间的人是基于其连通性的分类边缘或非边缘。如果它们连接到“可靠边缘”像素,则它们被视为边缘的一部分。否则,他们也被丢弃。见下图:
    在这里插入图片描述
    边缘 A 高于 maxVal,因此被视为“确定边缘”。虽然边 C 低于 maxVal,但它连接到边 A,因此也被视为有效边,我们得到完整的曲线。但是边缘 B 虽然高于 minVal 并且与边缘 C 的区域相同,但它没有连接到任何“可靠边缘”,因此被丢弃。因此,我们必须相应地选择 minVal 和 maxVal 才能获得正确的结果。
    在假设边是长线的情况下,该阶段也消除了小像素噪声。

所以我们最终得到的是图像中的强边缘。

OpenCV 中的 Canny 边缘检测

OpenCV将以上所有内容放在单个函数cv.Canny()中。我们将看到如何使用它。第一个参数是我们的输入图像。第二个和第三个参数分别是我们的minVal和maxVal。第三个参数是perture_size。它是用于查找图像渐变的Sobel内核的大小。默认情况下为3。最后一个参数是L2gradient,它指定用于查找梯度幅度的方程式。如果为True,则使用上面提到的更精确的公式,否则使用以下函数:
在这里插入图片描述
默认情况下,它为False。

示例代码:

# Canny 边缘检测
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('../image/3.7.1.png', 0)
edges = cv2.Canny(img, 100, 200)
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(edges, cmap='gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.show()

效果图:
在这里插入图片描述

调整

调整 minVal 和 maxVal之后,我们再看看,会比较直观的感觉到参数对边缘检测的影响:

示例代码:

# Canny 边缘检测
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('../image/3.7.1.png', 0)
edges = cv2.Canny(img, 10, 150)
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(edges, cmap='gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.show()

效果图:
在这里插入图片描述

文章来源:https://blog.csdn.net/q664243624/article/details/135777654
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。