请参阅此处(带源代码)以实现Canny算法
边缘的概要可被认为是图像中的一定数量的点亮度发生变化的地方。 边缘检测器大致计算该亮度变化的导数,根据导数的大小确定亮度变化的大小,确定目标和背景。 在经典的边缘检测算法中,Roberts运算符、Prewitt运算符、Sobel运算符属于一阶差分运算符、LoG运算符、Canny运算符属于二阶差分运算符。 一阶差分算子通过求出图像灰度变化曲线的导数,可以强调图像中的对象的边缘,二阶差分算子通过求出图像的灰度变化导数的导数,对图像中灰度变化强的地方变得敏感,可以强调图像的纹理结构Canny算子是经典的一阶算子边缘检测方法的思路,同时继承了二阶LOG算子xfdl平滑滤波的思路,提出了基于独特梯度方向将梯度幅度抑制在极大值以外的核心思路,综合了传统边缘检测的优点,使边缘检测效果得到了新的Canny算子的提出已是上个世纪的事,但已广泛应用于当今数字图像处理,被誉为最好的边缘检测算法之一。
Roberts运算符Roberts运算符是最简单的运算符,是使用局部差分方式查找边缘的运算符。
定义水平坡度:
g_x=f(x1,y 1)-f (x,y ) ) )。
对应的操作员模板:
定义垂直坡度:
g_y=f(x1,y )-f (x,y 1) )。
对应的操作员模板:
从算子模板来看,Roberts算子是一种斜偏差梯度计算方法,梯度的大小表示边缘的强度,梯度的方向与边缘的方向垂直正交。
从图像处理的实际效果来看,22模板计算简单,边缘定位准确,但正因为采用了22模板,所以对于使用关于中心点对称的模板来计算边缘方向并不太有用,不会产生噪声适用于边缘清晰、降噪的图像分割。
以下面的图像为例,根据Roberts运算符的原理创建算法以实现函数myRoberts,并将效果图与matlab所具有的edge(I,‘Roberts’)函数的效果进行比较。
function[bw]=my%Roberts(I,th ) Roberts运算符if(Exist )、(var )|isempty ) th=0.08; 如果%阈值th不存在,则默认阈值为0.08endifndims(I )2 grayI=rgb2gray(I ) I; else grayI=I; 判断是否为%灰度,否则转移到end[m,n]=size(Grayi ); newI=grayI; robertsNum=0; forj=1: m-1 fork=1: n-1 Roberts num=ABS (grayi (j,k )-grayI(j ) j1,k 1 ) ) ABS (grayi ) j1,grayi 电子商务(j,k )=0; endendendbw=im2bw(newi ); 前两个if为了提高函数的通用性,一个是设定了默认的边缘阈值,另一个是与rgb图像输入一致。 重点的Roberts算法的实现原理体现在以下双重for循环中。 扫描图像的像素点,根据上述Roberts算子定义的水平方向和垂直方向的梯度计算大小,并与设定的阈值进行比较。 一般而言,想要输入的阈值th在0~1之间,但灰度图像的像素点由8比特即255灰度来表示,所以在比较时th乘以255,如果该点的梯度大于阈值,则将该点判定为梯度变化大的位置的边缘,为255 最后将灰度图像转换为二值图像。
此函数的效果(默认阈值0.08 )如下:
使用matlab中的函数可以获得以下效果:
Prewitt、Sobel Prewitt和Sobel操作符采用33模板操作符,在33模板中:
定义水平差异:
g_x=(z_7z_8z_9)-(Z_1 Z_2 Z_3) ) ) ) ) ) ) ) )
对应的操作员模板:
定义垂直差异:
g_y=(z_3z_6z_9)-(z_1z_4z_7) ) ) ) ) ) ) )
对应的操作员模板:
定义对角线方向的差分:
g_x=(z_2z_3z_6)-(Z_4 Z_7 Z_8) ) ) ) ) ) ) ) )
g_y=(z_6z_9z_8)-)-(Z_2 Z_1 Z_4) ) ) ) ) ) ) )
Sobel运算符基于Prewitt运算符进行了改进,通过在中心系数中使用权重2,与Prewitt运算符相比,Sobel模板可以更好地抑制(平滑)噪声。
由于采用了3*3模板,Prewitt算子的边缘检测结果在水平方向和垂直方向上都比Robert算子明显。 另一方面,Sobel算子将xfdl平滑和一阶差分相结合,在Prewitt算子中增加了权重的概念。 相邻点的距离越近,被认为对当前像素点的影响越不同,距离越近,对应于当前像素的影响越大,实现图像的锐化和边缘轮廓的强调。
有了运算符模板,算法的实现方式与Roberts运算符一致,只需根据模板定义的梯度表达式进行一点修改即可,在此不多做说明。
日志操作符
p>LoG(Laplacian of Gaussain)算法就是先对图像进行xfdl平滑处理,再进行二阶差分的拉普拉斯算子锐化边缘。xfdl平滑算子:
二阶拉普拉斯方程:
∇^2 f(x,y)=(∂^2 f)/(∂^2 x)+(∂^2 f)/∂y
写成二维离散形式:
∇^2 f(x,y)=f(x+1,y)+f(x-1,y)+f(x,y+1)+f(x,y-1)-4f(x,y)
对应的二阶拉普拉斯算子模板:
下边仍以上图为例,根据log算子原理编写算法实现函数myLog,将效果图与matlab自带edge(I,‘log’)函数效果对比:
与上述算子的算法不同点在于遍历像素点之前做了以xfdl平滑算子与图像卷积实现了xfdl平滑滤波。梯度计算时采用的是二阶拉普拉斯算子。
效果图如下;
matlab自带函数效果图如下:
从表面效果上来讲,Canny算法是对Sobel、Prewitt等算子效果的进一步细化和更加准确的定位,同时借鉴了LoG算子先进行xfdl滤波(噪声平滑)再进行图像梯度计算的思想。
关于Canny算法实现请参考我的这篇博文:
基于matlab的Canny算法实现(附源代码)