%利用canny算子提取边缘
clc,clear
% 读入图片
rice_img = imread('rice.jpg');
figure,imshow(rice_img);
title('原始图像')
[m,n] = size(rice_img);
%%
%对图像进行高斯平滑,选用的模板为3*3的模板
% 生成高斯模板
[x,y] = meshgrid([-3:3],[-3:3]);
sigma = 0.5;
h = exp(-(x.*x+y.*y)./(2*sigma^2))/(2*pi*sigma^2)
% 接着进行归一化处理
sumh = sum(h(:))
h = h/sumh;
% 模板已经生成,接下来开始模板处理图像
[hh,hw] = size(h);
H_size = floor(hh/2);
l_img1 = zeros(m+H_size*2,n+H_size*2);
l_img1(H_size+1:H_size+m,H_size+1:H_size+n) = rice_img;
rice_img_Gauss = zeros(m,n);
for i =1:m
for j=1:n
t = l_img1(i:i+hh-1,j:hw+j-1).*h;
rice_img_Gauss (i,j) = sum(t(:));
end
end;
figure,imshow(uint8(rice_img_Gauss));
title('高斯平滑之后的图像');
%%
%利用sobel算子计算图像的两个方向的梯度幅值
%sobel算子
Gy = [-1 0 1; -2 0 2; -1 0 1];
Gx = [-1 -2 -1; 0 0 0; 1 2 1];
%填充图像
[M1,N1] = size(rice_img_Gauss);
l_img2 = zeros(M1+2,N1+2);
l_img2(2:M1+1,2:N1+1) = rice_img_Gauss;
l_img2(1,2:N1+1) = rice_img_Gauss(1,:);
l_img2(M1+2,2:N1+1) = rice_img_Gauss(M1,:);
l_img2(2:M1+1,1) = rice_img_Gauss(:,1);
l_img2(2:M1+1,N1+2) = rice_img_Gauss(:,N1);
for i =1:m
for j =1:n
t1 = l_img2(i:i+2,j:j+2).*Gx;
t2 = l_img2(i:i+2,j:j+2).*Gy;
rice_img_sobel_x(i,j) = sum(t1(:));
rice_img_sobel_y(i,j) = sum(t2(:));
end
end
%计算梯度的幅值和方向
rice_img_sobel = abs(rice_img_sobel_x)+abs(rice_img_sobel_y);
rice_img_seta = atan2(rice_img_sobel_y,rice_img_sobel_x);
rice_img_sobel = uint8(rice_img_sobel);
% 角度值的范围在-3.14---0.14
%%
%接下来确定每个点的方向,并进行标记
% 2 1 4
% 3 3
% 4 1 2
rice_img_seta = rice_img_seta/pi*180;
% 将角度映射到-180--180°上
rice_dirction_mark = zeros(m,n);
for i =1:m
for j =1:n
if((rice_img_seta(i,j)>=-22.5)&&(rice_img_seta(i,j)<22.5))||((rice_img_seta(i,j)>=-180)&&(rice_img_seta(i,j)<-157.5))||(rice_img_seta(i,j)>=157.5)
rice_dirction_mark(i,j) = 1;
else if ((rice_img_seta(i,j)>=22.5)&&(rice_img_seta(i,j)<67.5))||((rice_img_seta(i,j)>=-157.5)&&(rice_img_seta(i,j)<-122.5))
rice_dirction_mark(i,j) = 2;
else if((rice_img_seta(i,j)>=67.5)&&(rice_img_seta(i,j)<122.5))||((rice_img_seta(i,j)>=-122.5)&&(rice_img_seta(i,j)<-67.5))
rice_dirction_mark(i,j) = 3;
else
rice_dirction_mark(i,j) = 4;
end
end
end
end
end
%%
% 下面依据标记的结果,进行非极大值抑制
% 设置上下阈值
max_rate = 0.9;
min_rate = 0.6;
% 最低阈值调高,会使最后的效果更好
threshold_max = max_rate * 255;
threshold_min = min_rate * 255;
match_list = [1 1 0 -1 -1 -1 0 1;
0 1 1 1 0 -1 -1 -1 ];
img_non_maxmum_suppression_result = zeros(m,n);
for i =2:m-1
for j =2:n-1
if(rice_img_sobel(i,j)>=threshold_max)
img_non_maxmum_suppression_result(i,j) = 255;
else if(rice_img_sobel(i,j)<=threshold_min)
img_non_maxmum_suppression_result(i,j) = 0;
else
nb_point_1 = rice_img_sobel(i + match_list(1,rice_dirction_mark(i,j)),j + match_list(2,rice_dirction_mark(i,j)));
nb_point_2 = rice_img_sobel(i + match_list(1,rice_dirction_mark(i,j)+4),j + match_list(2,rice_dirction_mark(i,j)+4))
if(rice_img_sobel(i,j)>=nb_point_1)&&(rice_img_sobel(i,j)>=nb_point_2)
img_non_maxmum_suppression_result(i,j) = 250;
else
img_non_maxmum_suppression_result(i,j) = 0;
end
end
end
end
end
img_non_maxmum_suppression_result = uint8(img_non_maxmum_suppression_result);
figure,imshow(img_non_maxmum_suppression_result);
title('canny处理后的结果')
原始图像
滤波之后的图像
canny处理之后的图像
效果还不错