Canny
边缘检测器,对受白噪声影响的阶跃型边缘是最优的.
1.Canny边缘检测基本原理
(1)图象边缘检测必须满足两个条件:一能有效地抑制噪声;二必须尽量精确确定边缘的位置。
(2)根据对信噪比与定位乘积进行测度,得到最优化逼近算子。这就是Canny边缘检测算子。
(3)类似与Marr(LoG)边缘检测方法,也属于先平滑后求导数的方法。
2.Canny边缘检测算法:
step1:用高斯滤波器平滑图象;
step2:用一阶偏导的有限差分来计算梯度的幅值和方向;
step3:对梯度幅值进行非极大值抑制;
step4:用双阈值算法检测和连接边缘。
step1:高斯平滑函数
step3:非极大值抑制
仅仅得到全局的梯度并不足以确定边缘,因此为确定边缘,必须保留局部梯度最大的点,而抑制非极大值。(non-maxima
suppression,NMS)
解决方法:利用梯度的方向。
图2非极大值抑制
四个扇区的标号为0到3,对应3*3邻域的四种可能组合。
在每一点上,邻域的中心象素M与沿着梯度线的两个象素相比。如果M的梯度值不比沿梯度线的两个相邻象素梯度值大,则令M=0。
step4:阈值化
减少假边缘段数量的典型方法是对N[i,j]使用一个阈值。将低于阈值的所有值赋零值。但问题是如何选取阈值?
解决方法:双阈值算法。双阈值算法对非极大值抑制图象作用两个阈值τ1和τ2,且2τ1≈τ2,从而可以得到两个阈值边缘图象N1[i,j]和
N2[i,j]。由于N2[i,j]使用高阈值得到,因而含有很少的假边缘,但有间断(不闭合)。双阈值法要在N2[i,j]中把边缘连接成轮廓,当到达轮廓的端点时,该算法就在N1[i,j]的8邻点位置寻找可以连接到轮廓上的边缘,这样,算法不断地在N1[i,j]中收集边缘,直到将N2[i,j]连接起来为止。
1. 用高斯滤波器平滑图像.
2. 用一阶偏导有限差分计算梯度幅值和方向.
3. 对梯度幅值进行非极大值抑制 .
4. 用双阈值算法检测和连接边缘.
function
can()
I = imread('un.bmp');
gray =
rgb2gray(I);
a =
im2single(gray);
[m,n] =
size(a);
%
用于输出的边界位图
e = false(m,n);
% Magic
numbers
GaussianDieOff = .0001;
PercentOfPixelsNotEdges = .7; % 用于阀值选择
ThresholdRatio =
.4;
% 低阀值相对高阀值的比值
sigma = 1;
%设置sigma
thresh =
[];
% 设计滤波器
- a
gaussian和它的导数
pw = 1:30; % possible widths
ssq =
sigma^2;
width =
find(exp(-(pw.*pw)/(2*ssq))>GaussianDieOff,1,'last');%find函数很给力...
if
isempty(width)
width =
1; % the user entered a really small sigma
end
t =
(-width:width);
gau =
exp(-(t.*t)/(2*ssq))/(2*pi*ssq);
% 高斯一维滤波
% Find
the directional derivative of 2D Gaussian (along X-axis)
% Since the
result is symmetric along X, we can get the derivative along
% Y-axis
simply by transposing the result for X
direction.
[x,y]=meshgrid(-width:width,-width:width);
dgau2D=-x.*exp(-(x.*x+y.*y)/(2*ssq))/(pi*ssq);%二维高斯方向导数
%
Convolve the filters with the image in each direction
% The canny
edge detector first requires convolution with
% 2D
gaussian, and then with the derivitave of a gaussian.
% Since
gaussian filter is separable, for smoothing, we can use
% two 1D
convolutions in order to achieve the effect of convolving
% with 2D
Gaussian. We convolve along rows and then
columns.
%用一阶高斯滤波器平滑图像
aSmooth=imfilter(a,gau,'conv','replicate');
% run the filter accross rows
aSmooth=imfilter(aSmooth,gau','conv','replicate'); % and then
accross columns
%应用方向导数
ax = imfilter(aSmooth, dgau2D, 'conv','replicate');
ay =
imfilter(aSmooth, dgau2D', 'conv','replicate');
%计算梯度幅值
mag = sqrt((ax.*ax) + (ay.*ay));
magmax =
max(mag(:));
if
magmax>0
mag = mag / magmax; %
normalize
end
%
选择高低两个阀值,用于双阀值算法检测和连接边缘.
if isempty(thresh)
counts=imhist(mag, 64);
highThresh = find(cumsum(counts) >
PercentOfPixelsNotEdges*m*n,...
1,'first') / 64;
lowThresh = ThresholdRatio*highThresh;
thresh = [lowThresh highThresh];
elseif
length(thresh)==1
highThresh = thresh;
if thresh>=1
eid = sprintf('Images:%s:thresholdMustBeLessThanOne',
mfilename);
msg = 'The threshold must be less than 1.';
error(eid,'%s',msg);
end
lowThresh = ThresholdRatio*thresh;
thresh = [lowThresh highThresh];
elseif length(thresh)==2
lowThresh = thresh(1);
highThresh = thresh(2);
if (lowThresh >= highThresh) || (highThresh
>= 1)
eid = sprintf('Images:%s:thresholdOutOfRange', mfilename);
msg = 'Thresh must be [low high], where low < high
< 1.';