引自:https://www.cnblogs.com/mightycode/p/6394810.html 作者:爱鱼
http://www.cnblogs.com/techyan1990/p/7291771.html 作者:TechYan
https://www.cnblogs.com/Black-Small/p/3258463.html 作者:Black Small
Canny边缘检测算子是一种多级检测算法。1986年由John F. Canny提出,同时提出了边缘检测的三大准则:
- 1.低错误率的边缘检测:检测算法应该精确地找到图像中的尽可能多的边缘,尽可能的减少漏检和误检。
- 2.最优定位:检测的边缘点应该精确地定位于边缘的中心。
- 3.图像中的任意边缘应该只被标记一次,同时图像噪声不应产生伪边缘。
为了满足这些要求,Canny使用了变分法。Canny检测器中的最优函数使用四个指数项的和来描述,它可以由高斯函数的一阶导数来近似。
在目前常用的边缘检测方法中,Canny边缘检测算法是具有严格定义的,可以提供良好可靠检测的方法之一。由于它具有满足边缘检测的三个标准和实现过程简单的优势,成为边缘检测最流行的算法之一。
Canny边缘检测算法的处理流程
- 图像灰度化:只有灰度图才能进行边缘检测
- 使用高斯滤波器,以平滑图像,滤除噪声。
- 计算图像中每个像素点的梯度强度和方向。
- 应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。
- 应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
- 通过抑制孤立的弱边缘最终完成边缘检测。
1.图像灰度化:
Canny算法通常处理的图像为灰度图,因此如果摄像机获取的是彩色图像,那首先就得进行灰度化。对一幅彩色图进行灰度化,就是根据图像各个通道的采样值进行加权平均。以RGB格式的彩图为例,通常灰度化采用的方法主要有:
方法1:Gray=(R+G+B)/3;
方法2:Gray=0.299R+0.587G+0.114B;
注意1:至于其他格式的彩色图像,可以根据相应的转换关系转为RGB然后再进行灰度化;
注意2:在编程时要注意图像格式中RGB的顺序通常为BGR。
2.高斯滤波
为了尽可能减少噪声对边缘检测结果的影响,所以必须滤除噪声以防止由噪声引起的错误检测。为了平滑图像,使用高斯滤波器与图像进行卷积,该步骤将平滑图像,以减少边缘检测器上明显的噪声影响。
其实在各个算法库如Matlab、OpenCV等,在实现的时候,就是采用一个矩阵模板进行加权运算,拿图像的八连通区域来说,中间点的像素值就等于八连通区的像素值的均值,这样达到平滑的效果,该模板我们常成为高斯核。
根据上述分析可知,高斯核是整个求解的关键。很显然,它是通过二维高斯函数计算得来的。这里给出离散高斯核矩阵的计算公式,
Lena原图
Lena高斯模糊
3.计算图像中每个像素点的梯度强度和方向
图像的边缘可以指向不同方向,因此经典Canny算法用了四个梯度算子来分别计算水平,垂直和对角线方向的梯度。但是通常都不用四个梯度算子来分别计算四个方向。常用的边缘差分算子(如Rober,Prewitt,Sobel)计算水平和垂直方向的差分Gx和Gy。这样就可以如下计算梯度模和方向:梯度角度θ范围从弧度-π到π,然后把它近似到四个方向,分别代表水平,垂直和两个对角线方向(0°,45°,90°,135°)。可以以±iπ/8(i=1,3,5,7)分割,落在每个区域的梯度角给一个特定值,代表四个方向之一。
Sobel算子 无阈值
4.非极大值(Non-Maximum Suppression)抑制
非极大值抑制是一种边缘稀疏技术,非极大值抑制的作用在于“瘦”边。对图像进行梯度计算后,仅仅基于梯度值提取的边缘仍然很模糊。对于标准3,对边缘有且应当只有一个准确的响应。而非极大值抑制则可以帮助将局部最大值之外的所有梯度值抑制为0,对梯度图像中每个像素进行非极大值抑制的算法是:
- 将当前像素的梯度强度与沿正负梯度方向上的两个像素进行比较。
- 如果当前像素的梯度强度与另外两个像素相比最大,则该像素点保留为边缘点,否则该像素点将被抑制。
通常为了更加精确的计算,在跨越梯度方向的两个相邻像素之间使用线性插值来得到要比较的像素梯度,现举例如下:
如图3-2所示,将梯度分为8个方向,分别为E、NE、N、NW、W、SW、S、SE,其中0代表045度,1代表4590度,2代表-90~ -45度,3代表-45~ 0度。像素点P的梯度方向为theta,则像素点P1和P2的梯度线性插值为: 因此非极大值抑制的伪代码描写如下: 需要注意的是,如何标志方向并不重要,重要的是梯度方向的计算要和梯度算子的选取保持一致。非极大值抑制
5.双阈值检测
在施加非极大值抑制之后,剩余的像素可以更准确地表示图像中的实际边缘。然而,仍然存在由于噪声和颜色变化引起的一些边缘像素。为了解决这些杂散响应,必须用弱梯度值过滤边缘像素,并保留具有高梯度值的边缘像素,可以通过选择高低阈值来实现。如果边缘像素的梯度值高于高阈值,则将其标记为强边缘像素;如果边缘像素的梯度值小于高阈值并且大于低阈值,则将其标记为弱边缘像素;如果边缘像素的梯度值小于低阈值,则会被抑制。阈值的选择取决于给定输入图像的内容。6.抑制孤立的弱边缘
强边缘点可以认为是真的边缘。弱边缘点则可能是真的边缘,也可能是噪声或颜色变化引起的。为得到精确的结果,后者引起的弱边缘点应该去掉。通常认为真实边缘引起的弱边缘点和强边缘点是连通的,而又噪声引起的弱边缘点则不会。所谓的滞后边界跟踪算法检查一个弱边缘点的8连通领域像素,只要有强边缘点存在,那么这个弱边缘点被认为是真是边缘保留下来。
这个算法搜索所有连通的弱边缘,如果一条连通的弱边缘的任何一个点和强边缘点连通,则保留这条弱边缘,否则抑制这条弱边缘。搜索时可以用广度优先或者深度优先算法,我在这里实现了应该是最容易的深度优先算法。一次连通一条边缘的深度优先算法如下:
- 1.准备一个栈s,一个队列q,设联通指示变量connected为假。从图像的第一个点开始,进入2。
- 2.如果这个点是弱边界点并且没有被标记,把它标记,并把它作为第一个元素放入栈s中,同时把它放入记录连通曲线的队列q,进入3。如果这个点不是弱边界或者已经被标记过,到图像的下一个点,重复2。
- 3.从栈s中取出一个元素,查找它的8像素领域。如果一个领域像素是弱边界并且没有被标记过,把这个领域像素标记,并加入栈s中,同时加入队列q。同时查找领域对应的强边界图,如果有一个像素是强边界,表示这条弱边界曲线和强边界联通,设置connected为真。重复3直到栈中没有元素了。如果connected为假,则依次从队列q中取出每个元素,清空标记。如果connected为真,保留标记。
- 4.清空队列q,设置connected为假,移动到图像的下一个点,到2。
7.结果
下面是对Lena图计算Canny边缘检测的梯度模图和二值化图,高斯半径2,高阀值100,低阀值50。
Canny检测梯度模图 Canny检测梯度二值图 作为对比,下面是用一阶差分和Sobel算子对原图计算的结果,阀值100。由于一阶差分的梯度值相对较小,我对一阶差分的梯度值放大了一定倍数,使得它和Sobel的梯度值保持同样的水平。 一阶差分梯度模图 一阶差分梯度二值图 Sobel梯度模图 Sobel梯度二值图
很明显,Canny边缘检测的效果是很显著的。相比普通的梯度算法大大抑制了噪声引起的伪边缘,而且是边缘细化,易于后续处理。对于对比度较低的图像,通过调节参数,Canny算法也能有很好的效果。
原图 Canny梯度模,高斯半径2,低阀值30,高阀值100 Canny梯度二值化图,高斯半径2,低阀值30,高阀值100
原图 Canny梯度模,高斯半径1,低阀值40,高阀值80 Canny梯度二值化图,高斯半径1,低阀值40,高阀值80
网友评论