7. Canny边缘检测

本文介绍了Canny边缘检测算法的原理,包括降噪、寻找梯度、非最大抑制和滞后阈值四个步骤。在OpenCV中,Canny边缘检测通过cv.Canny()函数实现,允许自定义参数以优化边缘检测效果。
摘要由CSDN通过智能技术生成

1. 原理

边缘检测是一种流行的边缘检测算法。它是由 John F. Canny 开发的.

  1. 这是一个多阶段算法,我们将经历多个阶段。
  2. 降噪:由于边缘检测容易受到图像中噪声的影响,第一步是使用 5x5 高斯滤波器去除图像中的噪声。我们已经在前面的章节中看到了这一点。
  3. 寻找图像的强度梯度:平滑的图像然后在水平和垂直方向使用 Sobel 核进行滤波,以获得水平方向 (Gx) 和垂直方向 (Gy) 的一阶导数。从这两张图像中,我们可以找到每个像素的边缘梯度和方向,如下所示:
    E d g e G r a d i e n t ( G ) = G x 2 + G y 2 Edge_Gradient(G)=\sqrt{G^2_x+G^2_y} EdgeGradient(G)=Gx2+Gy2
    A n g l e ( θ ) = t a n − 1 ( G y G x ) Angle(θ)=tan^{-1}(\frac{Gy}{Gx}) Angle(θ)=tan1(GxGy)
  4. 非最大抑制:在获得梯度大小和方向后,对图像进行全扫描以去除可能不构成边缘的任何不需要的像素。为此,在每个像素处,检查像素是否在梯度方向的邻域中是局部最大值。检查下面的图像:
    在这里插入图片描述
    点 A 在边缘上(在垂直方向)。渐变方向垂直于边缘。 B点和C点在梯度方向。所以点 A 与点 B 和 C 一起检查,看它是否形成局部最大值。如果是,则考虑进入下一阶段,否则,将其抑制(置零)。
    简而言之,得到的结果是具有“细边缘”的二值图像。
  5. 滞后阈值 :这个阶段决定哪些边是真正的边,哪些不是。为此,我们需要两个阈值 minVal 和 maxVal。任何强度梯度大于 maxVal 的边缘肯定是边缘,而那些低于 minVal 的肯定是非边缘,因此被丢弃。位于这两个阈值之间的那些根据它们的连通性被分类为边缘或非边缘。如果它们连接到“确定边缘”像素,则它们被认为是边缘的一部分。否则,它们也会被丢弃。见下图:
    在这里插入图片描述
    边 A 高于 maxVal,因此被视为“确定边”。尽管边 C 低于 maxVal,但它连接到边 A,因此它也被视为有效边,我们得到了完整的曲线。但是边 B,虽然它高于 minVal 并且与边 C 处于同一区域,但它没有连接到任何“确定边”,因此将其丢弃。因此,我们必须相应地选择 minVal 和 maxVal 以获得正确的结果,这一点非常重要。
    在假设边缘是长线的情况下,此阶段还去除了小像素噪声。
    所以我们最终得到的是图像中的强边缘

2. OpenCV 中的 Canny 边缘检测

python中用法:

edges	=	cv.Canny(	image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]]	)
edges	=	cv.Canny(	dx, dy, threshold1, threshold2[, edges[, L2gradient]]	)

这是一个重载的成员函数,为了方便而提供。它与上述函数的不同之处仅在于它接受的参数。
使用具有自定义图像梯度的 Canny 算法查找图像中的边缘。

OpenCV 将上述所有内容放在单个函数 cv.Canny() 中。我们将看到如何使用它。第一个参数是我们的输入图像。第二个和第三个参数分别是我们的 minVal 和 maxVal。第三个参数是aperture_size。它是用于查找图像梯度的 Sobel 核的大小。默认情况下它是 3。最后一个参数是 L2gradient,它指定了寻找梯度幅度的方程。如果为 True,则使用上述公式更准确,否则使用此函数: E d g e _ G r a d i e n t ( G ) = ∣ G x ∣ + ∣ G y ∣ Edge\_Gradient(G)=|G_x|+|G_y| Edge_Gradient(G)=Gx+Gy。默认情况下,它是 False。

参数描述
dx输入图像的 16 位 x 导数(CV_16SC1 或 CV_16SC3)。
dst输入图像的 16 位 y 导数(与 dx 类型相同)
edges输出边缘图;单通道 8 位图像,与图像大小相同
threshold1滞后过程的第一个阈值。
threshold2滞后过程的第二个阈值。
L2gradient一个标志,指示是否应该使用更准确的 L 2 n o r m = ( d I / d x ) 2 + ( d I / d y ) 2 L2 norm=\sqrt{(dI/dx)^2+(dI/dy)^2} L2norm=(dI/dx)2+(dI/dy)2 来计算图像梯度幅度( L2gradient=true ),或者是否默认 ( L2gradient=false )。
img = cv.imread("../../file/photos/messi5.jpg", 0)
edges = cv.Canny(img, 100, 200)
cv.imwrite("edges.jpg", edges)
plt.subplot(121), plt.imshow(img, 'gray'), plt.title("Oringal")
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(edges, 'gray'), plt.title("edges")
plt.xticks([]), plt.yticks([])

plt.show()

结果如下:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值