1、Canny边缘提取原理
Canny边缘检测方法利用了梯度方向信息,采用“非极大抑制”以及双阈值技术,获得了单像素连续边缘,是目前所认为的检测效果较好的一种边缘检测方法。
先利用高斯函数对图像进行低通滤波;然后对图像中的每个像素进行处理,寻找边缘的位置及在该位置的边缘法向,并采用一种称之为“非极值抑制”的技术在边缘法向寻找局部最大值;最后对边缘图像做滞后阈值化处理,消除虚假响应。
Canny为一个边缘检测算法自定义了目标集,并用优化的方法实现了边缘检测。根据Canny的说法,一个边缘算子必须满足的三个准则是:
(1)低错误率:边缘算子应该只对边缘响应,并能找到所有的边,而对于非边缘应能舍弃。
(2)定位精度:被边缘算子找到的边缘像素与真正的边缘像素间的距离应该尽可能的小。
(3)在单边存在的地方,检测结果不应出现多边。
需要找到一个能够使三个准则都得到优化的滤波器函数。
假设滤波器函数是f,那么滤波器函数对边缘B的响应由下面的卷积给出:
最后Canny证明了Gaussian函数的一阶导数是边缘检测滤波器的有效近似。
在一维情况下,Gaussian函数为:
对x的微分为:
二维情况下Gaussian函数为:
二维Gaussian函数在x、y方向上有偏导数,与Canny优化的边缘检测滤波器近似的是G’。所以把输入图像和G’进行卷积,得到一个边缘增强的图像。
卷积实现起来比较简单,但是计算量大,而对于二维卷积计算是成倍增长的。由于一个二维的高斯卷积可以分解成两个一维的高斯卷积,而且微分也可以分解成两个方向上的一维卷积,因此Canny用一维卷积实现了边缘检测算法。
高斯卷积得到的边缘图像还存在一些具有较高梯度值、非边缘的点,这对真正的边缘是一种干扰,应该去除掉。对于一个边缘像素,都有一个与该点所在的边垂直的梯度方向,并且该像素的梯度值要大于该边两侧的像素的梯度值。Canny根据这种思想用抑制非极大值点的算法对梯度图像做了后续处理,最后得到了理想的梯度图像。
2、 算子计算步骤:
(1) 先利用高斯平滑滤波器来平滑图像以除去噪声(即用高斯平滑滤波器与图像作卷积);
(2) 计算梯度的幅值和方向
(3)对梯度幅值进行非极大值抑制;
(4) 用双阈值检测和连接边缘。
3、Matlab实现
clc;clear all;close all;I=rgb2gray(imread('F:\D_Photogrammetry\DSC00438.JPG.jpg')); Img=double(I); sz=size(I); %% 第一步、Gaussian卷积平滑滤波alf=3; n=7; n0=floor((n+1)/2);for i=1:n %%Gaussian卷积核计算for j=1:n h(i,j)=exp(-((i-n0)^2+(j-n0)^2)/(2*alf))/(2*pi*alf); end end Img_n=uint8(conv2(Img,h,'same')); % 通过创建的高斯卷积核进行高斯滤波,并转换为8为整型数据figure(); imshow(I); title('Gray Image'); figure(); imshow(Img_n); title('Gaussian Filter Result'); M = zeros(sz(1),sz(2));
theta = zeros(sz(1),sz(2));
canny1 = zeros(sz(1),sz(2));%非极大值抑制
canny2 = zeros(sz(1),sz(2));%双阈值检测和连接Img_n=double(Img_n); for i=2:(sz(1)-2) for j=2:(sz(2)-2) %% 第二步 计算x 和 Y 方向的幅度和方向梯度Sx=Img_n(i-1,j-1)+2*Img_n(i,j-1)+Img_n(i+1,j-1)-Img_n(i-1,j+1)-2*Img_n(i,j+1)-Img_n(i+1,j+1); Sy=Img_n(i+1,j-1)+2*Img_n(i+1,j)+Img_n(i+1,j+1)-Img_n(i-1,j-1)-2*Img_n(i-1,j)-Img_n(i-1,j+1); M(i,j)=sqrt(Sx^2+Sy^2); %记录幅度值theta(i,j)= atan(Sx/Sy);%记录方位角,反应梯度方向,与梯度垂直的方向即为边缘方向%% 第三步,分四个方向进行比较,非极大值抑制dirc = theta(i,j);if abs(dirc) <= pi / 8if (M(i,j) > M(i-1,j-1) )&&( M(i,j)> M(i+1,j+1) )canny1(i, j) = M(i, j);endelseif abs(dirc) >= 3 * pi / 8if (M(i,j) > M(i-1,j-1) )&&( M(i,j)> M(i+1,j+1) )canny1(i, j) = M(i, j);endelseif dirc > pi / 8 && dirc < 3 * pi / 8if ( M(i,j) > M(i-1,j-1) )&&( M(i,j)> M(i+1,j+1) )canny1(i, j) = M(i, j);endelseif dirc > - 3 * pi / 8 && dirc < - pi / 8if (M(i,j) > M(i-1,j-1) )&&( M(i,j)> M(i+1,j+1) )canny1(i, j) = M(i, j);endendend end %% 第四步,双阈值监测和边缘连接 lowTh = 0.2 *max(max(canny1));%高阈值higtTh = 0.4 *max(max(canny1));%低阈值
for i = 2 : sz(1)for j = 2 : sz(2)if canny1(i,j) >lowTh && canny1(i,j) < higtThcanny2(i,j) = canny1(i,j);endend
endfigure() ;imshow(uint8(M)); title('Canny Amplitude values'); figure() ;imshow(uint8(canny1)); title('Nonmaximum inhibition:Canny1 Edge detection results'); figure() ;imshow(uint8(canny2)); title('Double threshold monitoring:Canny2 Edge detection results');