基于Canny算子的边缘检测————MATLAB
一、概念
Canny算子是一种非常重要的边缘检测算子,是最优的阶梯型边缘检测算子。它的最优性主要表现在以下三个方面;
好的检测:Canny算子可以尽可能多地标识出原始图像中的实际边缘。
好的定位:它所标记出来的边缘尽可能给你地接近实际图像中的实际边缘。
最小响应:图像中的边缘只能标识一次,并且可能存在的图像噪声不标识成边缘。
二、Canny算子的具体实现步骤如下:
①去噪声:任何边缘检测算法都不可能在没有经过处理的原始图像上很好地处理,所以首先要对原始图像数据与二维高斯滤波模板进行卷积运算,得到的图像与原始图像相比有轻发的模糊,这样可以消除噪声
②梯度计算,利用导数算子(如Prewitt算子和Sobel算子)来找到图像灰度沿着两个方向的导数G、G,然后就可以分别求出梯度的幅值和方向:
③梯度方向确定:求出了边缘的方向,就可以把边缘的梯度方向大略分成几种角度(如0°、45°、90°和135 ), 并可以找到这个像素梯度方向的邻接像素。
④遍历图像:若是某个像素的灰度值与它的梯度方向上前后两个像素的灰度值相比不是最大的,那么这个像素灰度值就置为0,即不是边缘。
⑤用累计直方图来计算两个阈值:凡是大稿阙值的定是边缘)凡是小于低阈值的一定不是边缘。如果检测结果在两个阈值之间,就根据这个像素的印接像素中有没有超过高阈值的边缘像素进行判断,若有,就是边缘;否则就不是边缘。
三、MATLAB代码实现
% 去噪声
clear all;
clc;
image = imread('Lena.jpg');
image = rgb2gray(image);
subplot(221);
imshow(image);
title('原始图像');
image = double(image)/256;
[m,n] = size(image);
w = fspecial('gaussian');
image_1 = imfilter(image,w,'replicate');
subplot(222);
imshow(int8(256*image_1));
title('高斯滤波后的图像');
% 梯度计算
op = fspecial('sobel')/4; % 用Sobel算子来求导数
x = op';
y =op;
bx = imfilter(image_1,x,'replicate');
by = imfilter(image_1,y,'replicate');
b_abs = sqrt(bx.*bx+by.*by); % 求梯度的幅值
b_angle = angle(by-i*bx);
b_ang = b_angle/3.1416*180; % 求梯度的方向
% 梯度方向确定
for r = 1:m
for c = 1:n
if((b_ang(r,c)>=22.5 & b_ang(r,c)<67.5)...
| (b_ang(r,c)>=-157.5 & b_ang(r,c)<-112.5))
dir(r,c) = 1;
elseif ((b_ang(r,c)>=67.5 & b_ang(r,c)<112.5)...
| (b_ang(r,c)>=-112.5 & b_ang(r,c)<-67.5))
dir(r,c) = 2;
elseif ((b_ang(r,c)>=112.5 & b_ang(r,c)<157.5)...
| (b_ang(r,c)>=-67.5 & b_ang(r,c)<-22.5))
dir(r,c) = 3;
else
dir(r,c) = 0;
end
end
end
% 遍历图像
b_ab = [zeros(m,1),b_abs,zeros(m,1)]; % 串联矩阵
b_ab = [zeros(1,n+2);b_ab;zeros(1,n+2)];
for r = 2:m+1
for c = 2:n+1
switch dir(r-1,c-1)
case 0
if((b_ab(r,c)<b_ab(r+1,c))| (b_ab(r,c)<b_ab(r-1,c)))
b1(r-1,c-1) = 0;
else
b1(r-1,c-1) = b_ab(r,c);
end
case 1
if((b_ab(r,c)<b_ab(r+1,c-1))| (b_ab(r,c)<b_ab(r-1,c+1)))
b1(r-1,c-1) = 0;
else
b1(r-1,c-1) = b_ab(r,c);
end
case 2
if((b_ab(r,c)<b_ab(r,c-1))| (b_ab(r,c)<b_ab(r,c+1)))
b1(r-1,c-1) = 0;
else
b1(r-1,c-1) = b_ab(r,c);
end
case 3
if((b_ab(r,c)<b_ab(r-1,c-1))| (b_ab(r,c)<b_ab(r+1,c+1)))
b1(r-1,c-1) = 0;
else
b1(r-1,c-1) = b_ab(r,c);
end
end
end
end
for r = 1:m
for c = 1:n
if (b1(r,c)>0.24)
b2(r,c) = 1;
else
b2(r,c) = 0;
end
end
end
for r = 1:m
for c = 1:n
if(b1(r,c)>0.36)
b3(r,c)=1;
else
b3(r,c) = 0;
end
end
end
image_2 = b3;
for k = 1:10
for r = 2:m-1
for c = 2: n-1
if (b2(r,c)==1 & (image_2(r,c)==1|image_2(r+1,c)==1 ...
|image_2(r+1,c-1)==1|image_2(r+1,c+1)==1|image_2(r,c-1)==1 ...
|image_2(r,c+1)==1|image_2(r-1,c-1)==1|image_2(r-1,c)==1 ...
|image_2(r-1,c+1)==1))
image_2(r,c) = 1;
else
image_2(r,c) = 0;
end
end
end
end
subplot(223);
imshow(image_2);
title('Canny算子检测后的图像');
四、实验结果如下