Canny 边缘检测是当今最流行的边缘检测方法之一,因为它非常强大和灵活。该算法本身遵循从图像中提取边缘的三个阶段过程。
边缘检测是一种图像处理技术,用于识别对象的边界(边缘)或图像内的区域。边缘是与图像相关的最重要的特征之一。我们通过图像的边缘了解图像的底层结构。因此,计算机视觉处理管道在应用中广泛使用边缘检测技术。
用于边缘检测的图片
import cv2
img = cv2.imread('test.jpg')
cv2.imshow('Original', img)
cv2.waitKey(0)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_blur = cv2.GaussianBlur(img_gray, (3,3), 0)
第一步是读入图像,使用imread()函数来读取我们需要进行检测的图片,并进行图片的灰度颜色空间转换,因为我们不需要颜色信息来检测边缘,这里转换到灰度空间方便图片的边缘检测,读取图像后,我们还使用GaussianBlur()函数对其进行模糊处理。
GaussianBlur()为了减少图像中的噪声。在边缘检测中,必须计算像素强度的数值导数,这通常会导致“噪声”边缘。换句话说,图像中相邻像素(尤其是靠近边缘)的强度可能会波动很大,从而产生不代表我们正在寻找的主要边缘结构的边缘。 模糊可以平滑边缘附近的强度变化,从而更容易识别图像中的主要边缘结构。
用于边缘检测的图
Sobel 边缘检测
Sobel 边缘检测是最广泛使用的边缘检测算法之一。Sobel 算子检测以像素强度突然变化为标志的边缘,如下图所示。
作为 t 函数的像素强度
当我们绘制强度函数的一阶导数时,强度的上升更加明显。
作为 t 函数的像素强度的一阶导数
上图表明可以在梯度高于特定阈值的区域中检测到边缘。此外,导数的突然变化也会揭示像素强度的变化。考虑到这一点,我们可以使用 3×3 内核来近似导数。我们使用一个内核来检测 X 方向上像素强度的突然变化,以及 Y 方向上的另一个。
这些是用于 Sobel 边缘检测的内核:
X 方向内核
Y 方向内核
当这些内核与原始图像卷积时,便会得到一个“Sobel 边缘图像”
# X轴方向的Sobel 边缘检测
sobelx = cv2.Sobel(src=img_blur, ddepth=cv2.CV_64F, dx=1, dy=0, ksize=5)
# Y轴方向的Sobel 边缘检测
sobely = cv2.Sobel(src=img_blur, ddepth=cv2.CV_64F, dx=0, dy=1, ksize=5)
# XY轴方向的Sobel 边缘检测
sobelxy = cv2.Sobel(src=img_blur, ddepth=cv2.CV_64F, dx=1, dy=1, ksize=5)
#显示图片
cv2.imshow('Sobel X', sobelx)
cv2.waitKey(0)
cv2.imshow('Sobel Y', sobely)
cv2.waitKey(0)
cv2.imshow('Sobel X Y using Sobel() function', sobelxy)
cv2.waitKey(0)
这里我们使用Sobel(src, ddepth, dx, dy)函数进行图片的边缘检测
参数src代表需要进行边缘检测的图片
参数ddepth指定输出图像的精度,而dx和dy指定每个方向的导数顺序。
例如:
如果dx=1和dy=0,我们计算 x 方向上的一阶导数 Sobel 图像。
如果同时dx=1和dy=1,我们计算两个方向的一阶导数 Sobel 图像
运行以上图片,我们可以得到图片的边缘检测图片
结果如下图所示。 x 方向的 Sobel 图像主要识别垂直边缘(即那些在 x 方向、水平方向梯度最大的边缘)。在 y 方向上标识水平边缘(即那些在 y 方向上的梯度最大的垂直边缘)
x 方向的 Sobel 图像
y 方向的 Sobel 图像
x y方向的 Sobel 图像
Canny 边缘检测
Canny 边缘检测是当今最流行的边缘检测方法之一,因为它非常强大和灵活。该算法本身遵循从图像中提取边缘的三个阶段过程。添加图像模糊,这是减少噪声的必要预处理步骤。其中主要包括:
降噪:原始图像像素通常会导致噪声边缘,因此在计算边缘之前减少噪声很重要 在 Canny 边缘检测中,高斯模糊过滤器用于从本质上去除或最小化可能导致不良边缘的不必要细节。
计算图像的强度梯度:图像平滑(模糊)后,将使用 Sobel 核心进行水平和垂直过滤。然后使用这些过滤操作的结果来计算每个像素的强度梯度
抑制假边:在降低噪声和计算强度梯度后,这一步的算法使用一种称为边缘非最大抑制的技术来过滤掉不需要的像素(实际上可能并不构成边缘)。为此,在正负梯度方向上将每个像素与其相邻的像素进行比较。如果当前像素的梯度幅度大于其相邻像素,则保持不变。否则,当前像素的大小设置为零。
滞后阈值:在 Canny 边缘检测的最后一步中,梯度幅度与两个阈值进行比较
- 如果梯度幅值高于较大的阈值,则这些像素与边缘相关联,并包含在最终的边缘图中。
- 如果梯度幅值低于较小的阈值,则像素被抑制,并从最终边缘图中排除。
- 所有其他像素,其梯度幅度落在这两个阈值之间,被标记为“弱”边缘(即它们成为包含在最终边缘图中的候选者)。
- 如果“弱”像素与边缘相关联,那么它们也包含在最终的边缘图中。
edges = cv2.Canny(image=img_blur, threshold1=100, threshold2=200)
cv2.imshow('Canny Edge Detection', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
这里opencv已经把以上几个步骤集成到了cv2.Canny一个函数里面
edge = cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient ]]]
参数解释
- image:源图像
- threshold1:阈值1
- threshold2:阈值2
- apertureSize:可选参数,Sobel算子的大小
其中,较大的阈值2用于检测图像中明显的边缘,但一般情况下检测的效果不会那么完美,边缘检测出来是断断续续的。所以这时候用较小的第一个阈值用于将这些间断的边缘连接起来。函数返回的是二值图,包含检测出的边缘
cv2.Canny边缘检测
Canny边缘检测与Sobel边缘检测算法相比,Canny边缘检测凸显出来的图片边缘更加真实
内容出处:,
声明:本网站所收集的部分公开资料来源于互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时修改或删除。文章链接:http://www.yixao.com/tech/25104.html