JohnCanny于1986年提出Canny算子,它与Marr(LoG)边缘检测方法类似,也属于是先平滑后求导数的方法。本文对根据上述的边缘检测过程对Canny检测算法的原理进行介绍。 并结合实验,对canny算法进行理解,指出参数选取中容易产生的问题。
canny边缘检测一共四个部分:
1. 用高斯滤波器平滑图像;(图像去噪)
2. 用一阶偏导有限差分计算梯度幅值和方向;(特征增强)
3. 对梯度幅值进行非极大值抑制 ;(边缘检测)
4. 用双阈值算法检测和连接边缘。(形态学处理)
平滑去噪
canny边缘检测的前两步相对不复杂,所以我就直接调用系统函数了。
IM=imread('2.tif');
IM=imnoise(IM); %imnoise对uint8类型加噪为0-255,e对double类型加噪为0-1,
[m,n]=size(IM);
IM=double(IM);
%高斯滤波
w=fspecial('gaussian',[9 9]);
img=imfilter(IM,w,'replicate');
值得注意的是,在选取滤波窗口w时,根据我的实验(无噪声情况实验,若有噪声,也会影响后续的非极大值抑制),滤波窗口w边长为偶数时,将导致得到的梯度只有单像素最大幅值。而对边缘分析可知,应该产生双像素的梯度幅值才符合实际情况,所以滤波窗口w的选取一定要为基数边长。
实例如下,当选偶数边长时,幅值结果如下
当选基数边长时,幅值结果如下
计算幅值
%%sobel边缘检测
w_h=[1,2,1;0,0,0;-1,-2,-1]; %Sobel算子,梯度方向朝上为正
img_h=imfilter(img,w_h,'replicate'); %梯度是竖着的边缘,即横边缘
w_w=[-1,0,1;-2,0,2;-1,0,1]; %Sobel算子,梯度方向朝右为正
img_