转自:http://blog.csdn.net/likezhaobin/article/details/6892176算法
图象的边缘是指图象局部区域亮度变化显著的部分,该区域的灰度剖面通常能够看做是一个阶跃,既从一个灰度值在很小的缓冲区域内急剧变化到另外一个灰度相差较大的灰度值。图象的边缘部分集中了图象的大部分信息,图象边缘的肯定与提取对于整个图象场景的识别与理解是很是重要的,同时也是图象分割所依赖的重要特征,边缘检测主要是图象的灰度变化的度量、检测和定位,自从1959提出边缘检测以来,通过五十多年的发展,已有许多中不一样的边缘检测方法。根据做者的理解和实践,本文对边缘检测的原理进行了描述,在此基础上着重对Canny检测算法的实现进行详述。编程
本文所述内容均由编程验证而来,在实现过程当中,有任何错误或者不足之处你们共同讨论(本文不讲述枯燥的理论证实和数学推导,仅仅从算法的实现以及改进上进行原理性和工程化的描述)。数据结构
在以前的博文中,做者从一维函数的跃变检测开始,按部就班的对二维图像边缘检测的基本原理进行了通俗化的描述。结论是:实现图像的边缘检测,就是要用离散化梯度逼近函数根据二维灰度矩阵梯度向量来寻找图像灰度矩阵的灰度跃变位置,而后在图像中将这些位置的点连起来就构成了所谓的图像边缘(图像边缘在这里是一个统称,包括了二维图像上的边缘、角点、纹理等基元图)。函数
在实际状况中理想的灰度阶跃及其线条边缘图像是不多见到的,同时大多数的传感器件具备低频滤波特性,这样会使得阶跃边缘变为斜坡性边缘,看起来其中的强度变化不是瞬间的,而是跨越了必定的距离。这就使得在边缘检测中首先要进行的工做是滤波。性能
1)滤波:边缘检测的算法主要是基于图像强度的一阶和二阶导数,但导数一般对噪声很敏感,所以必须采用滤波器来改善与噪声有关的边缘检测器的性能。常见的滤波方法主要有高斯滤波,即采用离散化的高斯函数产生一组归一化的高斯核(具体见“高斯滤波原理及其编程离散化实现方法”一文),而后基于高斯核函数对图像灰度矩阵的每一点进行加权求和(具体程序实现见下文)。测试
2)加强:加强边缘的基础是肯定图像各点邻域强度的变化值。加强算法能够将图像灰度点邻域强度值有显著变化的点凸显出来。在具体编程实现时,可经过计算梯度幅值来肯定。.net
3)检测:通过加强的图像,每每邻域中有不少点的梯度值比较大,而在特定的应用中,这些点并非咱们要找的边缘点,因此应该采用某种方法来对这些点进行取舍。实际工程中,经常使用的方法是经过阈值化方法来检测。blog
JohnCanny于1986年提出Canny算子,它与Marr(LoG)边缘检测方法相似,也属因而先平滑后求导数的方法。本节对根据上述的边缘检测过程对Canny检测算法的原理进行介绍。get
Canny算法一般处理的图像为灰度图,所以若是摄像机获取的是彩色图像,那首先就得进行灰度化。对一幅彩色图进行灰度化,就是根据图像各个通道的采样值进行加权平均。以RGB格式的彩图为例,一般灰度化采用的方法主要有:数学
方法1:Gray=(R+G+B)/3;
方法2:Gray=0.299R+0.587G+0.114B;(这种参数考虑到了人眼的生理特色)
注意1:至于其余格式的彩色图像,能够根据相应的转换关系转为RGB而后再进行灰度化;
注意2:在编程时要注意图像格式中RGB的顺序一般为BGR。
图像高斯滤波的实现能够用两个一维高斯核分别两次加权实现,也能够经过一个二维高斯核一次卷积实现。
1)高斯核实现
上式为离散化的一维高斯函数,肯定参数就能够获得一维核向量。
上式为离散化的二维高斯函数,肯定参数就能够获得二维核向量。
注意1:关于参数Sigma的取值详见上篇博文。
注意2:在求的高斯核后,要对整个核进行归一化处理。
2)图像高斯滤波
对图像进行高斯滤波,听起来很玄乎,其实就是根据待滤波的像素点及其邻域点的灰度值按照必定的参数规则进行加权平均。这样能够有效滤去理想图像中叠加的高频噪声。
一般滤波和边缘检测是矛盾的概念,抑制了噪声会使得图像边缘模糊,这回增长边缘定位的不肯定性;而若是要提升边缘检测的灵敏度,同时对噪声也提升了灵敏度。实际工程经验代表,高斯函数肯定的核能够在抗噪声干扰和边缘检测精肯定位之间提供较好的折衷方案。这就是所谓的高斯图像滤波,具体实现代码见下文。
关于图像灰度值得梯度可以使用一阶有限差分来进行近似,这样就能够得图像在x和y方向上偏导数的两个矩阵。经常使用的梯度算子有以下几种:
1)Roberts算子
上式为其x和y方向偏导数计算模板,可用数学公式表达其每一个点的梯度幅值为:
2)Sobel算子
上式三个矩阵分别为该算子的x向卷积模板、y向卷积模板以及待处理点的邻域点标记矩阵,据此可用数学公式表达其每一个点的梯度幅值为:
3)Prewitt算子
和Sobel算子原理同样,在此仅给出其卷积模板。
4)Canny算法所采用的方法
在本文实现的Canny算法中所采用的卷积算子比较简单,表达以下:
其x向、y向的一阶偏导数矩阵,梯度幅值以及梯度方向的数学表达式为:
求出这几个矩阵后,就能够进行下一步的检测过程。
图1 非极大值抑制原理
根据图1 可知,要进行非极大值抑制,就首先要肯定像素点C的灰度值在其8值邻域内是否为最大。图1中蓝色的线条方向为C点的梯度方向,这样就能够肯定其局部的最大值确定分布在这条线上,也即出了C点外,梯度方向的交点dTmp1和dTmp2这两个点的值也可能会是局部最大值。所以,判断C点灰度与这两个点灰度大小便可判断C点是否为其邻域内的局部最大灰度点。若是通过判断,C点灰度值小于这两个点中的任一个,那就说明C点不是局部极大值,那么则能够排除C点为边缘。这就是非极大值抑制的工做原理。
做者认为,在理解的过程当中须要注意如下两点:
1)中非最大抑制是回答这样一个问题:“当前的梯度值在梯度方向上是一个局部最大值吗?” 因此,要把当前位置的梯度值与梯度方向上两侧的梯度值进行比较;
2)梯度方向垂直于边缘方向。
但实际上,咱们只能获得C点邻域的8个点的值,而dTmp1和dTmp2并不在其中,要获得这两个值就须要对该两个点两端的已知灰度进行线性插值,也即根据图1中的g1和g2对dTmp1进行插值,根据g3和g4对dTmp2进行插值,这要用到其梯度方向,这是上文Canny算法中要求解梯度方向矩阵Thita的缘由。
完成非极大值抑制后,会获得一个二值图像,非边缘的点灰度值均为0,可能为边缘的局部灰度极大值点可设置其灰度为128。根据下文的具体测试图像能够看出,这样一个检测结果仍是包含了不少由噪声及其余缘由形成的假边缘。所以还须要进一步的处理。