LOG算子和CANNY算子边缘提取
边缘的含义:
在数字图像中,边缘是指图像局部变化最显著的部分,边缘主要存在于目标与目标,目标与背景之间,是图像局部特性的不连续性,如灰度的突变、纹理结构的突变、颜色的突变等。尽管图像的边缘点产生的原因各不相同,但他们都是图形上灰度不连续或灰度急剧变化的点,图像边缘分为阶跃状、斜坡状和屋顶状。
一般图像边缘检测方法主要有如下四个步骤:
图像滤波:传统边缘检测算法主要是基于图像强度的一阶和二阶导数,但导数的计算对噪声很敏感,因此必须使用滤波器来改善与噪声有关的边缘检测器的性能。需要指出的是,大多数滤波器在降低噪声的同时也造成了边缘强度的损失,因此,在增强边缘和降低噪声之间需要一个折衷的选择。
图像增强:增强边缘的基础是确定图像各点邻域强度的变化值。增强算法可以将邻域(或局部)强度值有显著变化的点突显出来。边缘增强一般是通过计算梯度的幅值来完成的。
图像检测:在图像中有许多点的梯度幅值比较大,而这些点在特定的应用领域中并不都是边缘,所以应该用某种方法来确定哪些点是边缘点。最简单的边缘检测判断依据是梯度幅值。
图像定位:如果某一应用场合要求确定边缘位置,则边缘的位置可在子像素分辨率上来估计,边缘的方位也可以被估计出来。
LOG边缘检测算子
在20世纪70年代,Marr理论根据神经生理学实验得出了以下结论:物体的边界是将亮度图像与其解释连接起来的最重要线索。边缘检测技术在当时是基于很小邻域的卷积,只对特殊图像效果好。这些边缘检测子的主要缺点是它们依赖物体的大小且对噪声敏感。
基于二阶导数过零点的边缘检测技术探究了阶跃边缘对应于图像函数陡峭的变化这一事实。图像函数的一阶导数在对应于图像边缘的位置上应该取得极值,因此二阶导数在同一位置应该为0;而寻找过零点位置比起极值来得更容易和更准确。关键的问题是如何稳定地计算二阶导数,一种可能性是首先平滑图像(减小噪声),再计算二阶导数。在选择平滑滤波器时,需要满足两个标准:
滤波器应该是平滑的且在邻域中大致上是有限带宽的,以便减少会导致函数变化的可能频率数。
空间定位的约束要求滤波器的响应来自于图像中邻近的点。这两个标准矛盾的,但是可以通过使用高斯分布同时得到优化。在实践中,需要准确地考虑优化的含义。
选择Laplacian算子的基础有两个基本概念。第一,算子的高斯部分会模糊图像,从而在尺寸上将结构的灰度(包括噪声)降低到远小于σ的程度,而且高斯函数能在空间和频率两个域平滑图像,因而在原图像中引入不存在的人为干扰(如振铃)的可能性很小。第二,拉普拉斯有各向同性(旋转不变)的重要优点,符合人的视觉系统特性,而且对任何模板方向的灰度变化有相等的响应,从而避免了使用多个模板去计算图像中任何点处的最强响应。
LOG算法步骤如下:
取样得到的高斯低通滤波器对输入图像滤波。
计算第一步得到图像的拉普拉斯。
找到步骤2所得图像的零交叉。
Canny边缘检测算子介绍
1986年,JOHN CANNY 提出一个很好的边缘检测算法,被称为Canny边缘检测器,
Canny方法基于三个基本的目标:
检测标准: 低错误率。所有的边缘都应该被找到,并且没有假边缘。
行为标准: 边缘点应被很好的定位。测到的边缘点与真实边缘的中心之间距离应该最小。
单响应标准: 单一的边缘点效应。对于真实的边缘点,检测器应该仅仅返回一个点。也就是真实边缘的局部最大数应该是最小的。意味着仅存在单一边缘点的位置,检测器不应指出多个边缘像素。
Canny边缘检测算法由一下基本步骤组成:
用一个高斯滤波器平滑输入图像。
计算梯度幅值图像和角度图像。
对梯度幅值图像应用非最大抑制。
用双阈值处理和连接分析来检测并连接边缘。
比较分析
相同尺度下的LOG算子总是能比Canny算子检测出更多的细节,Canny算子能对真正比较显著地边缘给出检测。LOG算子容易受尺度的影响,不同尺度下的边缘点要用不同尺度的LOG算子检测,Canny 算子受尺度的影响不太明显,不同尺度下,边缘点的位置都有偏差,但几乎相同;
从对噪声的敏感程度来看,LOG边缘检测子是采用二阶导数过零点的检测方法,故对噪声更敏感一些,因此从抑制噪声方面来讲,Canny边缘检测子不容易受到噪声的干扰,而相同尺度下LOG算子却容易受到噪声的干扰,抑制噪声的能力要弱一些。LOG算子对噪声的抑制能力随着尺度的增加而增加,相同尺度下的Canny算子比LOG算子的抗噪声能力强,而LOG算子比Canny算子的边缘点准确;
对于弱边缘,由于Canny边缘检测子采用两种不同的阈值分别检测强边缘和弱边缘,并且当弱边缘和强边缘相连时,才将弱边缘包含在输出图像中,故而Canny算子更能检测出真正的弱边缘,但是Canny边缘检测子检测出的边缘的位置会有一定范围的误差,
对于假边缘,LOG边缘检测子相对比较容易受到噪声干扰,会检测出更多的细节,也容易检测出一些由于噪声引起的假边缘,但是LOG边缘检测子对边缘位置的检测还是很准确的。
参考文献
[1] D.Marr and E. Hildreth, Theory of Edge Detection, Proc. R. Soc. Lond. B207:187-217.
[2] John Canny, A Computational Approach to Edge Detection, IEEE Trans. PAMI, 8(6):679-698.
[3] James J. Clark, Authenticating Edges Produced by Zero-crossing Algorithms, IEEE T. PAMI, 11(1), 1989, pp.43-57.
附录:实验代码
code:独立加性高斯白噪声
function [distImg,endtImg] = add_noise(origImg,u)
origImg = im2double(origImg);
distImg = imnoise(origImg, 'gaussian', 0, u);
endtImg = distImg.*255;
end
code:对图像进行高斯滤波
function g=my_gaussian(src,n,k)
n1=(n+1)/2;
[m,l]=size(src);
b=zeros(n,n);
I=zeros(m,l);
g=zeros(m,l);
img=zeros(m,l);
[Ay, Ax ,dim ] = size(src);
if dim>1
src = rgb2gray(src);
end
for i=1:n
for j=1:n
b(i,j)=(exp(-((i-n1)^2 +(j-n1)^2)/(2*k)))/(2*pi*k);
end
end
b = b/sum(b(:));
I=double(src);
img=conv2(I,b,'same');
g=uint8(img);
end
code:LOG算子实现图像处理以及结果展示
function [thrr] =log_img(noise,n,k,thr)
[filename, pathname] = uigetfile({'*.jpg'; '*.bmp'; '*.gif'}, '选择图片');
if filename == 0
return;
end
imgsrc = imread([pathname, filename]);
[y, x, dim] = size(imgsrc); %转换为灰度图像
if dim>1
imgsrc = rgb2gray(imgsrc);
end
if (x~=256 && y~=256) %转换为8bit 256*256图像
imgsrc = im2uint8(imgsrc);
imgsrc=imresize(imgsrc,[256,256]);
end
[showing_noise, img_noise]= add_noise(imgsrc,noise);
img= my_gaussian(img_noise,n,k);
[img_log,thrr]=edge(img,'log',thr);
figure(1)
imshow(imgsrc);%原图
figure(2)
imshow(showing_noise);
figure(3)
imshow(img);%高斯滤波后
figure(4)
imshow(img_log);
end
code:CANNY算子实现
function [ m, theta, sector, canny1, canny2, bin] = canny_step( src, lowTh)
[Ay, Ax, dim ] = size(src);
if dim>1
src = rgb2gray(src);
end
src = double(src);
m = zeros(Ay, Ax);
theta = zeros(Ay, Ax);
sector = zeros(Ay, Ax);
canny1 = zeros(Ay, Ax);
canny2 = zeros(Ay, Ax);
bin = zeros(Ay, Ax);
%梯度计算
for y = 1:(Ay-1)
for x = 1:(Ax-1)
gx = src(y, x) + src(y+1, x) - src(y, x+1) - src(y+1, x+1);
gy = -src(y, x) + src(y+1, x) - src(y, x+1) + src(y+1, x+1);
m(y,x) = (gx^2+gy^2)^0.5 ;
theta(y,x) = atand(gx/gy) ;
tem = theta(y,x);
if (tem<67.5)&&(tem>22.5)
sector(y,x) = 0;
elseif (tem<22.5)&&(tem>-22.5)
sector(y,x) = 3;
elseif (tem<-22.5)&&(tem>-67.5)
sector(y,x) = 2;
else
sector(y,x) = 1;
end
end
end
%非极大值抑制
for y = 2:(Ay-1)
for x = 2:(Ax-1)
if 0 == sector(y,x) %右上 - 左下
if ( m(y,x)>m(y-1,x+1) )&&( m(y,x)>m(y+1,x-1) )
canny1(y,x) = m(y,x);
else
canny1(y,x) = 0;
end
elseif 1 == sector(y,x) %竖直方向
if ( m(y,x)>m(y-1,x) )&&( m(y,x)>m(y+1,x) )
canny1(y,x) = m(y,x);
else
canny1(y,x) = 0;
end
elseif 2 == sector(y,x) %左上 - 右下
if ( m(y,x)>m(y-1,x-1) )&&( m(y,x)>m(y+1,x+1) )
canny1(y,x) = m(y,x);
else
canny1(y,x) = 0;
end
elseif 3 == sector(y,x) %横方向
if ( m(y,x)>m(y,x+1) )&&( m(y,x)>m(y,x-1) )
canny1(y,x) = m(y,x);
else
canny1(y,x) = 0;
end
end
end
end
%双阈值检测
ratio = 2;
for y = 2:(Ay-1)
for x = 2:(Ax-1)
if canny1(y,x)<lowTh
canny2(y,x) = 0;
bin(y,x) = 0;
continue;
elseif canny1(y,x)>ratio*lowTh
canny2(y,x) = canny1(y,x);
bin(y,x) = 1;
continue;
else
tem =[canny1(y-1,x-1), canny1(y-1,x), canny1(y-1,x+1);
canny1(y,x-1), canny1(y,x), canny1(y,x+1);
canny1(y+1,x-1), canny1(y+1,x), canny1(y+1,x+1)];
temMax = max(tem);
if temMax(1) > ratio*lowTh
canny2(y,x) = temMax(1);
bin(y,x) = 1;
continue;
else
canny2(y,x) = 0;
bin(y,x) = 0;
continue;
end
end
end
end
end
code:CANNY图像处理及结果展示
function canny_plotimg(noise,n,thr,k)
[filename, pathname] = uigetfile({'*.jpg'; '*.bmp'; '*.gif'}, '选择图片');
if filename == 0
return;
end
imgsrc = imread([pathname, filename]);
[y, x, dim] = size(imgsrc);
if dim>1
imgsrc = rgb2gray(imgsrc);
end
if (x~=256 && y~=256) %转换为8bit 256*256图像
imgsrc = im2uint8(imgsrc);
imgsrc=imresize(imgsrc,[256,256]);
end
[showing_noise, img_noise]= add_noise(imgsrc,noise);
img= my_gaussian(img_noise,n,k);
[m theta sector canny1 canny2 bin] = canny1step(img, thr);
figure(1)
imshow(imgsrc);%原图
figure(2)
imshow(showing_noise);
figure(3)
imshow(img);%高斯滤波后
figure(4)
imshow(uint8(m));%导数
figure(5)
imshow(uint8(canny1));%非极大值抑制
figure(6)
imshow(uint8(canny2));%双阈值