转载请说明出处:http://blog.csdn.net/zhubaohua_bupt/article/details/73826080
Canny边缘检测算子是John
F. Canny于 1986 年开发出来的一个多级边缘检测算法。
Canny 的目标是找到一个最优的边缘检测算法,最优边缘检测的含义是:
好的检测- 算法能够尽可能多地标识出图像中的实际边缘。
好的定位- 标识出的边缘要尽可能与实际图像中的实际边缘尽可能接近。
最小响应- 图像中的边缘只能标识一次,并且可能存在的图像噪声不应标识为边缘
——摘自百度百科
最近做了个项目,需要canny边缘检测,但是,在平台上不支持opencv,所以就研究了一下canny边缘检测的原理,并用c++实现算法。
1 原理部分
Canny边缘检测整个流程共分为4步,分别是
*滤波、
*梯度及方向角计算(增强)、
*边缘非极大值抑制、
*双阈值连接,
下面以一个图像边缘检测的流程探讨一下每个部分。原图为
1.1 滤波
1.1.1为什么要滤波?
滤波的目的是为了平滑一些纹理较弱的非边缘区域,从而更准确的检测边缘。
1.1.2 高斯滤波
常见的滤波算法有均滤波、中值滤波、高斯滤波、双边滤波等等。我们知道,均值滤波可以模糊图像;
中值滤波可以去除椒盐噪声; 双边滤波可以保留边缘,平滑非边缘区域。canny边缘检测使用的高斯滤波,
和均值、双边滤波一样,高斯滤波也是通过对图像模板卷积实现的, 只不过模板的内容不一样。下面探究一下高斯滤波:
高斯滤波的模板(高斯核)是利用高斯函数形成的。
高斯核形成中有一个比较重要的参数,即方差,方差控制着高斯滤波对图像的平滑程度。方差越大,滤波后的图像越平滑。
极限情况下,方差无限大,高斯滤波退化成均值滤波。滤波就说到这里,关于高斯滤波更详细的特性可以自行百度。
1.1.3 高斯核为3,7时的效果
1.2 梯度及方向角计算
canny利用sobel算子来计算经过滤波后,图像的梯度和方向角。
高斯核大小分别为3,7时,sobel效果
1.3 非极大值抑制
在图像边缘区域,其附近梯度值往往都很大,为了满足最小响应标准,canny采用了非极大值抑制,
来去除真实边缘附近的其他梯度较大的区域。
非极大值抑制的思想是,沿着梯度方向,如果当前待检测像素的梯度不是最大值,那么,此像素就不是边缘。
为了简化计算,由于一个像素周围有八个像素,本文把一个像素的梯度方向离散为八个方向,如下图
把像素可能的360梯度方向分为8个扇区,每个扇区对应一个像素位置。这样就可以不利用插值,计算像素沿梯度方向前后的两个像素值。
这样,对于一个像素,其前后像素的计算就对应4种情况,比如像素p的梯度方向角为12.1度,
那么该像素沿着梯度方向前后的两个像素分别为(i-1,j+1),(i+1,j-1)。
高斯核分别为3,7时 ,经过非极大值抑制后的边缘
![](//img-blog.csdn.net/20170628180132859?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemh1YmFvaHVhX2J1cHQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](//img-blog.csdn.net/20170628180200413?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemh1YmFvaHVhX2J1cHQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
1.4 双阈值连接
经过以上3个步骤,我们已经可以得到一个经过非极大值抑制的边缘图像,如果没有什么特殊要求,这个边缘图像就可以利用了。
之所以要有双阈值连接这一步,是因为在获取图像边缘时,我们希望得到一些梯度比较大边缘,即得到一些特征较鲜明的边缘。
这样就必须设定一个阈值highThreshold来卡一下梯度值,只有图像梯度值大于highThreshold时才认为这些边缘特征鲜明。但是,
如下图, 只设定一个阈值会出现这样的问题,就是检测到的边缘不连续,
![](//img-blog.csdn.net/20170628143019545?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemh1YmFvaHVhX2J1cHQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
为了得到特征明显且连续的边缘,因此,canny采用了双阈值连接法。
即再设定一个低阈值,lowThreshold,用lowThreshold卡一下梯度图像,记录所用大于此阈值的像素位置,用来连接经过highThreshold阈值后
不连续的边缘。连接后图像如下,lowThreshold和highThreshold
一低 一高,为什么叫双阈值,相信一下就明白了吧。
![](//img-blog.csdn.net/20170628143341561?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemh1YmFvaHVhX2J1cHQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
双阈值连接效果,高斯核分别为3,7
![](//img-blog.csdn.net/20170628180434157?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemh1YmFvaHVhX2J1cHQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](//img-blog.csdn.net/20170628180405493?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemh1YmFvaHVhX2J1cHQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
实现部分见下篇博客
参考:
1 http://blog.csdn.net/yanmy2012/article/details/8110316
2 http://blog.csdn.net/xiajun07061225/article/details/6926108
3 http://www.cnblogs.com/qiqibaby/p/5289977.html
4 http://blog.csdn.net/dcrmg/article/details/52344902