Canny边缘检测算法

来源:互联网 发布:vb中xor是什么意思 编辑:程序博客网 时间:2024/04/29 08:27

Canny边缘检测算法的步骤:

1 用高斯滤波器平滑滤波;

2 用一阶偏导的有限差分来计算图片的梯度的幅值与方向;

3 对梯度幅值进行非极大值检测(目的是细化边缘);

4  通过双阈值算法对进行边缘连接。


第一步:高斯滤波

高斯函数如下公式所示:

G(u,v) = \frac{1}{2\pi \sigma^2} e^{-(u^2 + v^2)/(2 \sigma^2)}

它的图像是这样的:


高斯滤波,其实就是将图片与一个高斯模块求卷积。根据高斯函数的特性,大于3×σ部分,可以不考虑,所以一般而言,这个模板就是(6×σ+1)行,(6×σ+1)列的一个二维矩阵。如下图所示:



注意,这一步的生成的数据可能没有归一化,最好归一化。

接下来将得到的高斯矩阵与图片卷积就可以啦。其中σ越大,滤波后的图片的平滑性就越好,同时图片也越模糊。

下面举个例子,这是原图:


σ=1时的滤波后的图片如下:


σ=5时的图片为:


尺度越大,滤波效果也越好,但同时图片本身的高频分量也会被滤掉。

第二步:通过求差分求解梯度的方向与幅值

差分算子有很多,可以是sobel算子,robert算子,LOG算子等,我用的是canny算子,如下所示:

A=-1/2*[-1 1;-1 1];
B=-1/2*[1 1;-1 -1];

求解X与Y方向的差分公式为:

f'x=1/2*( f(x+1,y)-f(x,y) + f(x+1,y+1)-f(x,y+1) );

f'y=1/2*( f(x,y+1)-f(x,y) + f(x+1,y+1)-f(x+1,y) );

求差分可以通过求卷积得到,如下公式:

pic_x=conv2(double(pic),A);
pic_y=conv2(double(pic),B);
然后再通过下面的公式求梯度的方向与幅值。

gradamp=sqrt(double(pic_x.^2)+double(pic_y.^2));
gradori=atan(double(pic_y)./double(pic_x));


第三步:非极大值抑制

将0-360分成8个区间,分别是0-45,45-90,90-135,135-180及与他们相对的区间。

以0-45为例分析:


C到T1的方向是C点梯度的方向,非极大值抑制就是指,如果C点的值比它梯度方向的点的值要小,那么这个点就会被抑制。而它的梯度方向不一会正好有像素,所以要对之进行插值。经过非极值点抑制后的图像如下:


第四步:双阈值算法

这一步的原理是这样的,要选择两个阈值,第一个阈值比较大,梯度图中,大于它的点都是真边缘点。第二个阈值比较小,大于第二个阈值,但小于第一个阈值的点是假边缘点。如果一个真边缘点周围的点有假边缘点,那么这个假边缘点也会变成真边缘点。经过双阈值算法,图像如下:


上图是我的程序实现的,与MATLAB中给出的效果还有差距。下面的matlab中的canny函数滤波效果


关于算法的问题与改进,希望能与大家交流交流。欢迎拍砖。

0 0