opencv canny边缘检测代码
Canny算子是John Canny在1986年发表的论文中首次提出的边缘检测算子,该算子检测性能比较好,应用广泛。
Canny算子进行边缘检测的原理和步骤如下:
⑴消除噪声。边缘检测的算法主要是基于图像强度的一阶和二阶微分操作,但导数通常对噪声很敏感,边缘检测算法常常需要根据图像源的数据进行预处理操作,因此采用滤波器来改善与噪声有关的边缘检测性能,比如在进行边缘检测前,可以对原始数据先作高斯滤波处理。opencv canny边缘检测代码其实不仅对噪声,如果不做滤波平滑处理,原图片中不是边缘但是灰度变化频率较高的部分也容易被认为是边缘,这样导致了边缘检测性能的下降。
⑵计算梯度的幅度与方向。OpenCV中的Canny函数是使用Sobel卷积核来计算梯度的幅度与方向的。计算出的幅度与方向作为后面提取图像边缘的原始数据。
⑶非极大抑制。非极大抑制的目的是剔除第⑵部中计算出来的结果中的大部分非边缘点。其原理是通过像素的八邻域来判断要不要将这个像素置为边缘点,如果不置为边缘点,那么就置为背景色。判断的方法如下:
①判断范围是像素的八邻域,所以是局部最优判断法;
②判断的标准是如果某个像素在其八邻域内,既是最大,梯度也最大,那么可判断该点为像素边缘点,否则就不是。如何判断呢?
首先,梯度的判断是很好判断的,用边缘检测微分算子得到的结果直接比较就可以了,但是最大的判断可不是只比较其旁边的八个点哦,还要比较另外两个点,详情如下:

如果已经判断出上图中的C点比其旁边的8个点的像素都大,那么接下来判断上图中dTmp1和dTmp2的是否也小于C点的,那么dTmp1和dTmp2的怎么求呢?上图中蓝色的线条方向为C点的梯度方向,这样就可以确定其局部的最大肯定分布在这条线上,也即除了C点外,梯度方向的交点dTmp1和dTmp2这两个点的也可能会是局部最大。因此,判断C点灰度与这两个点灰度大小即可判断C点是否为其邻域内的局部最大灰度点。如果经过判断,C点灰度小于这两个点中的任一个,那就说明C点不是局部极大,那么则可以排除C点为边缘。
⑷用滞后阈算法求解图像边缘。上一步对边缘检测算子的结果进行了非极大抑制,接下来我们用二化的方法来求解图像边缘。单阈处理边缘效果不好,所以Cannny算法中采用滞后阈法求解。滞后阈法需要设置一个高阈和一个低阈,解后按如下法则进行:
第一,如果某一像素位置的梯度幅超过高阈,则像素被保留为边缘像素;
第二,如果某一像素位置的梯度幅小于低阈,则像素被排除;
第三,如果某一像素位置的幅在两个阈之间,该像素仅仅在连接到一个高于高阈的像素时被保留。
在以上的法则中,推荐的高阈与低阈比在2:1到3:1之间!
通过消除噪声、计算梯度幅度与方向、非极大抑制及用滞后阈算法求解图像边缘四个步骤就可实现Canny边缘检测。
Canny函数原型如下:
void Canny( InputArray image, OutputArray edges,double threshold1, double threshold2,int apertureSize=3, bool L2gradient=false );
Image为输入图像,单通道8bit;
edges为输出图像,与输入图像同类型同尺寸;
threshold1为滞后阈算法的低阈;
threshold2为为滞后阈算法的高阈;
apertureSize为Sobel算子的窗口(卷积核)阶数;
L2gradient表示是否使用L2范数来计算图像梯度幅。
以下是使用函数Canny实现图像边缘检测的代码:
代码中用到的图像的下载链接为:
//OpenCV版本2.4.9 //交流QQ2487872782 2016-8-4注:很报歉,此代码目前不能公开发表在博客上,已经删除,希望大家能理解!
运行结果如下图所示:

从图中我们可以看出Canny边缘检测算子的效果确实不错嘛!
附各边缘检测算子及方法效果对比,链接:
-------------------------------------------
欢迎大家加入图像识别技术交流群:271891601,另外,特别欢迎成都从事图像识别工作的朋友交流,我的QQ号2487872782
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-34140-1.html
烊烊