原理
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
浙公网安备 33010602011771号