【Emgu CV教程】11.2、Canny边缘检测
文章目录
- 一、背景知识
- 二、Canny()函数
- 三、演示
- 1.原始素材
- 2.程序代码
- 3.threshold1=30,threshold2=90的效果
- 3.threshold1=100,threshold2=200的效果
- 四、最后总结
一、背景知识
Canny 边缘检测算法 是 John F. Canny 于 1986年开发出来的一个多级边缘检测算法,也被很多人认为是边缘检测的 最优算法, 最优边缘检测的三个主要评价标准是:
- 低错误率: 标识出尽可能多的实际边缘,同时尽可能的减少噪声产生的误报。
- 高定位性: 标识出的边缘要与图像中的实际边缘尽可能接近。
- 最小响应: 图像中的边缘只能标识一次。
在传统的边缘检测算法中,Canny边缘检测可以更好的满足以上三个标准,其步骤包括:
- 使用高斯滤波器,以平滑图像,滤除噪声。
- 使用Sobel函数滤波,计算图像中每个像素点的梯度强度和方向。
- 应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。
- 应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
- 通过抑制孤立的弱边缘最终完成边缘检测。
上述五个步骤,除了第一、二、三、五步都好理解,而第四步种的“双阈值”,在有些教程中也叫“滞后阈值”,其实就是设定两个数,阈值上界maxVal和阈值下界minVal。网上有一篇大佬的文章对双阈值描述的相对简洁明了,以下是我直接拷贝过来的:
在经过第一、二、三步以后,图像中还会有很多噪声。Canny算法中应用了一种叫双阈值的技术。即设定一个阈值上界maxVal和阈值下界minVal,图像中的像素点如果大于阈值上界则认为必然是边界(称为强边界,strong edge),小于阈值下界则认为必然不是边界,两者之间的则认为是候选项(称为弱边界,weak edge),需进行进一步处理——如果与确定为边缘的像素点邻接,则判定为边缘;否则为非边缘。
应用双阈值的方法来决定可能的(潜在的)边界。
- 如果某一像素位置的幅值超过 高 阈值maxVal, 该像素被保留为边缘像素。
- 如果某一像素位置的幅值小于 低 阈值minVal, 该像素被排除。
- 如果某一像素位置的幅值在两个阈值之间,该像素仅仅在连接到一个高于 高 阈值的像素时被保留。
要想充分理解Canny函数实现过程中,最好的办法是去学习opencv的源码,但对于图像处理相关人员,只需要会用这个函数就可以,看不懂也没什么。
二、Canny()函数
Emgu CV中,Canny()函数定义如下:
public static void Canny(IInputArray image, // 输入图像IOutputArray edges, // 输出图像double threshold1, // 滞后阈值低值double threshold2, // 滞后阈值高值int apertureSize = 3, // 用于计算图片提取的 Sobel kernel 尺寸,默认为 3bool l2Gradient = false //指定计算梯度的等式。该参数默认为 False,当参数为 True 时,其精度更高。
)
注意:
- 一般来说,threshold2的大小是threshold1的2~3倍。
- threshold1、threshold2越小,越能够捕获更多的边缘信息,坏处是很多噪声造成的边缘会被保留。
- threshold1、threshold2越大,越能够获得主要的边缘信息,坏处是强边缘也有可能被去掉。
三、演示
1.原始素材
原始素材srcMat如下图:
2.程序代码
Mat tempMat = srcMat.Clone();
Mat dstMat = new Mat();
int threshold1;
int threshold2;threshold1=???
threshold2=???// Canny运算
CvInvoke.Canny(tempMat, dstMat, threshold1, threshold2);
CvInvoke.Imshow("Canny, " + dstMat.Size.ToString(), dstMat);
apertureSize和l2Gradient 都采用默认的值,可以不用写。
3.threshold1=30,threshold2=90的效果
运行结果如下:
输出的图像中大桥的边缘提取的效果很好,但是桥墩和路面部分存在很多弱边缘。
3.threshold1=100,threshold2=200的效果
随着threshold1和threshold2的值增大,输出的图像中去掉了更多的弱边缘,但是注意左下角的白色面包车,它的真实边缘也被去掉了很多。
四、最后总结
一幅图像想要利用Canny函数使用边缘检测,threshold1、threshold2、apertureSize、l2Gradient这四个参数需要尝试多次才能得出一个比较好的效果。
而且,图像不同,这四个参数值也可能不同,不存在一组通用的参数可以精确提取任何图像的边缘信息。
原创不易,请勿抄袭。共同进步,相互学习。