赞
踩
Canny边缘检测算法由计算机科学家John F. Canny于1986年提出. 它不仅提供算法,而且带来了一组边缘检测理论,分阶段说明了如何实现边缘检测. Canny检测算法包括以下阶段:
灰度
高斯模糊
计算图像梯度幅度
非最大抑制
双重阈值选择
灰度
Graying实际上是降维操作,可以减少计算量. 如果该算法不执行与颜色相关的识别,它也可以直接执行后续阶段而不会发灰.
高斯模糊
噪声将包含在实际图片中. 但是有时,图片中的噪点会导致图片中的边缘信息消失. 解决方案是使用高斯平滑来减少噪声,这是一种高斯模糊运算. 该操作是与高斯分布有关的滤波操作. 以下是二维高斯函数,其中(x,y)是坐标,而σ是标准偏差:
在执行高斯滤波之前,您需要获取一个高斯滤波器(内核). 如何获得高斯滤波器?实际上,将高斯函数离散化,并将滤波器中相应的水平和垂直坐标索引代入高斯函数以获得相应的值. 不同的过滤器具有不同的值. 以下是(2k + 1)x(2k + 1)过滤器的公式:
常用的高斯滤波器,大小为5x5基于canny边缘检测的人脸识别技术,σ= 1.4. 这是5x5高斯滤波器的实现代码:
图像梯度幅度
边缘是图像强度快速变化的地方. 您可以通过计算图像梯度幅度,即计算图像强度的一阶导数来识别这些位置. 由于图片是离散的,因此可以通过有限的导数来近似图片的梯度:
图像的梯度值:
梯度方向是:
实现代码如下:
非最大抑制(NMS)
理想情况下,所得边缘应非常细. 因此,需要执行非最大抑制以使边缘变薄. 原理很简单: 对梯度矩阵的所有点进行迭代,并使边缘方向上具有最大值的像素保持不变.
梯度方向和边缘方向相互垂直
让我们谈谈NMS的细节. NMS分别在4个方向(0、90、45和135)上执行. 有两个没有角度的场. 因此,共有八个字段: 上,下,左,右,左,上,下基于canny边缘检测的人脸识别技术,右如下图所示,C周围的八个点是其周围的八个区域.
这样做的好处是简单,但是这种简化方法无法达到最佳效果,因为自然图像中边缘梯度的方向不一定沿着这四个方向. 因此,非常有必要进行插值,以找到与像素所在的梯度方向的两侧最匹配的像素值.
NMS是要找到局部最大值,因此您需要将当前像素的梯度与其他方向进行比较. 如下图所示,g1,g2,g3和g4是C的八个区域中的四个点,蓝线是C的梯度方向. 如果C是局部最大值,则C点处的梯度幅度必须大于梯度方向线与g1g2,g4g3的交点处的梯度幅度,即大于点dTemp1和dTemp2处的梯度幅度. 由于dTemp1和dTemp2并不是整个像素而是子像素,因此上述方法无法发挥最佳效果. 亚像素表示两个物理像素之间存在像素.
那么,如何找到亚像素梯度幅度?您可以使用线性插值方法来计算g1和g2之间的dTemp1权重,以获取其梯度幅度. 计算公式如下:
以下两个图显示了y方向上的梯度值相对较大(即,梯度方向接近y轴)的情况. 因此,g2和g4在C之上和之下,并且权重= | gy | / | gx |. 左图显示x和y方向上的渐变符号相同的情况,右图显示x和y方向上的渐变符号相反的情况.
对于左图,点C是当前位置d [i,j],则g2在C的前一行,g4在C的下一行,因此位置坐标为: g2 = d [i-1,j]; g4 = d [i + 1,j].
根据左边的位置关系,我们可以得到: g1 = d [i-1,j-1]; g3 = d [i + 1,j + 1].
同样,根据右侧的位置关系,您可以获得: g1 = d [i-1,j + 1]; g3 = d [i + 1,j-1].
以下两个图显示了x方向上的梯度值相对较大(即,梯度方向接近x轴)的情况. 因此,g2和g4在C的左右位置,权重= |. gy | / | gx |左图显示x和y方向上的渐变符号相同的情况,右图显示x和y方向上的渐变符号相反的情况.
从上面,您可以获得以下信息: g2 = d [i,j-1]; g4 = d [i,j + 1];
左: g1 = d [i + 1,j-1]; g3 = d [i-1,j + 1];
右: g1 = d [i-1,j-1]; g3 = d [i + 1,j + 1].
以下两张图片可能有助于您理解:
然后,根据上述信息,代码实现如下:
双重阈值选择
此阶段确定哪些边缘是真实的,哪些不是. 为此,需要设置两个阈值minVal和maxVal. 梯度大于maxVal的任何边缘都必须是真实边缘,而minVal以下的边缘必须是非边缘,因此将被丢弃. 这两个阈值之间的边缘根据其连接性分为边缘或非边缘,如果将它们连接到“可靠边缘”像素,则将它们视为边缘的一部分. 否则,它将被丢弃.
代码如下:
边缘检测结果
经过上述5个过程,您可以获得以下结果:
与OpenCV,skimage算法进行比较:
我个人认为OpenCV结果是最好的,其次是skimage结果. 您自己的算法的一些结果相当粗糙. 如果有时间,可以尝试使用不同的标准偏差σ,或者尝试使用不同大小的高斯滤波器,等等. 也许可以改善结果. 或者,您可以了解skimage代码的实现方式.
完整的代码可以在以下位置找到: caoqi95 / CV_Learning /边缘检测
参考
[1]. 图像处理基础(四): 高斯滤波器的详细说明
[2]. Python中Canny Edge检测的分步指南—计算机视觉
[3]. Canny运算符的Python实现
[4]. OpenCV-Canny边缘检测
P.S: 该代码主要引用文章[3],更正了一些错误并将其写为类.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-149893-1.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。