原理

1.降噪

由于边缘检测很容易受到噪音影响,所以第一步是使用5x5的高斯滤波器去除噪音。

2.计算图像梯度

对平滑后的图像使用Sobel算子计算水平方向和竖直方向的一阶导数(图像梯度)(Gx和Gy)。根据得到的这两幅梯度图找到边界的梯度和方向。公式如下:

 梯度的方向一般总是与边界垂直。梯度方向被归为四类:垂直、水平和两条对角线。

3.非极大值抑制

在获得梯度的方向和大小后,应该对整幅图做一个扫描,除去那些非边界上的点。对每一个像素进行检查,看这个店的梯度是不是周围具有相同梯度方向的点中最大的。

 点A在边缘(垂直方向)上。渐变方向垂直于边缘。点B和C在梯度方向上。因此,将A点、B点和C点进行检查,看是否形成局部最大值。如果是这样,则考虑将其用于下一阶段,否则将其抑制(置为0)。简而言之,你得到的结果是带有“细边”的二进制图像。

4.滞后阈值

现在要去顶那些边界才是真正的边界,需要设置两个阈值:minVal和maxVal。当图像的灰色强度高于maxVal时被认为是真的边界,那些低于minVal的边界会被抛弃。如果介于两者之间的话,就要看这个点是否与某个被确定为真正边界点相连,如果是,就认为它也是边界点,如果不是就抛弃。

 边缘A在maxVal之上,因此被视为“确定边缘”。尽管边C低于maxVal,但它连接到边A,因此也被视为有效边,得到了完整的曲线。但是边缘B尽管在minVal之上并且与边缘C处于同一区域,但是它没有连接到任何“确保边缘”,因此被丢弃。因此,非常重要的一点是必须相应地选择minVal和maxVal以获得正确的结果。

OpenCV中的Canny边界检测

cv.Canny()第一个参数是输入图像,第二和第三个参数分别是minVal和maxVal。第三个参数设置用来计算图像梯度的Sobel卷积核的大小,默认值为3。最后一个参数是L2gradient,它可以用来设定求梯度大小的方程。如果设为True,就使用上面提到过的方程,否则使用下面方程替代。默认值为False。

 

import cv2 as cv
from matplotlib import pyplot as plt

img=cv.imread('./images/lena.jpeg',0)
edges=cv.Canny(img,100,200)
plt.subplot(121)
plt.imshow(img,'gray')
plt.title('original')
plt.xticks([])
plt.yticks([])
plt.subplot(122)
plt.imshow(edges,'gray')
plt.title('edges')
plt.xticks([])
plt.yticks([])
plt.show()

结果:

 

 posted on 2024-05-03 16:27  会飞的金鱼  阅读(43)  评论(0)    收藏  举报