基本步骤
1、 图像与高斯平滑滤波器卷积

2、 利用一阶有限差分计算偏导数阵列P与Q

3、 计算梯度幅值与方向角

4、非极大值抑制(NMS)
-
模块梯度方向分为4个,垂直,水平,正对角线,副对角线
-
模块梯度方向离散化

-22.5~22.5为0
22.5~67.5 为1
67.5~112.5 为2
112.5~157为3
以此类推
0代表水平,1代表副对角,2代表垂直,3代表正对角 -
梯度方向两边比较 p大于自身梯度方向两邻点的梯度,则保留,否则去除;
5、阈值化与边缘连接
- 设置两个阈值,一个高阈值,一个低阈值
- 根据高阈值的边缘点梯度方向,进行边缘连接,找不到点去低阈值找
- 从高阈值对应的点到低阈值图像的8领域找,找到就将其选为边缘点
代码
% 1、读入图像实现高斯滤波平滑
src=imread('lena.png');
gausFilter = fspecial('gaussian', [3,3], 1);
src= imfilter(src, gausFilter, 'replicate');
[Ax,Ay,~] = size(src);%获取图像尺寸
src = double(src);%类型转double
% 2、梯度大小方向计算 梯度方向离散化
m = zeros(Ax, Ay);%用来存储梯度大小
theta = zeros(Ax, Ay);%用来存储梯度方向
sector = zeros(Ax, Ay);%用来存储离散梯度值
for x = 1:(Ax-1)
for y = 1:(Ay-1)
gx = src(x+1, y)-src(x+1, y)-src(x, y+1)+src(x+1, y+1);%水平差分
gy = src(x, y+1)-src(x, y)+src(x+1, y+1)-src(x+1, y);%垂直差分
m(x,y) = (gx^2+gy^2)^0.5 ;%梯度大小
theta(x,y) = atand(gx/gy);%梯度方向
tem = theta(x,y);
if (tem<67.5)&&(tem>22.5)%副对角
sector(x,y) = 0;
elseif (tem<22.5)&&(tem>-22.5)%水平
sector(x,y) = 3;
elseif (tem<-22.5)&&(tem>-67.5)%正对角
sector(x,y) = 2;
else%垂直
sector(x,y) = 1;
end
end
end
% 3、非极大值抑制
canny = zeros(Ax, Ay);
for x = 2:(Ax-1)
for y = 2:(Ay-1)
if 0 == sector(x,y) %副对角
if (m(x,y)>m(x-1,y+1) )&&(m(x,y)>m(x+1,y-1))
canny(x,y) = m(x,y);
else
canny(x,y) = 0;
end
elseif 1 == sector(x,y) %垂直
if (m(x,y)>m(x-1,y))&&(m(x,y)>m(x+1,y))
canny(x,y) = m(x,y);
else
canny(x,y) = 0;
end
elseif 2 == sector(x,y) %正对角
if (m(x,y)>m(x-1,y-1))&&(m(x,y)>m(x+1,y+1))
canny(x,y) = m(x,y);
else
canny(x,y) = 0;
end
elseif 3 == sector(x,y) %水平
if (m(x,y)>m(x,y+1))&&( m(x,y)>m(x,y-1))
canny(x,y) = m(x,y);
else
canny(x,y) = 0;
end
end
end
end
% 4、双阈值检测
high = zeros(Ax, Ay);
low = zeros(Ax,Ay);
highTh = 35;
lowTh = 20;
for x = 2:(Ax-1)
for y = 2:(Ay-1)
if canny(x,y)>highTh
high(x,y) = 1;
end
if canny(x,y)>lowTh
low(x,y) = 1;
end
end
end
% 5、边缘连接——高阈值没有 低阈值8领域找查找
A=high;
for x = 2:(Ax-1)
for y = 2:(Ay-1)
tem =[low(x-1,y-1), low(x-1,y), low(x-1,y+1);
low(x,y-1), low(x,y), low(x,y+1);
low(x+1,y-1), low(x+1,y), low(x+1,y+1)];
temMax = max(tem);
if (high(x,y)==0)
if(temMax==1)
A(x,y)=1;
end
end
end
end
% 显示化结果
subplot(2,3,1),imshow(theta),title('梯度方向矩阵');
subplot(2,3,2),imshow(sector),title('梯度方向离散化矩阵');
subplot(2,3,3),imshow(canny),title("非极大值抑制后");
subplot(2,3,4),imshow(low),title("低阈值");
subplot(2,3,5),imshow(high),title("高阈值");
subplot(2,3,6),imshow(A),title("canny结果");
结果

- 实现的效果不是很好,边缘不够平滑
- 可能连接步骤理解的不够深刻,实现起来太粗暴
本文详细介绍了Canny边缘检测算法的实现过程,包括图像预处理、梯度计算、非极大值抑制和双阈值检测等步骤。通过MATLAB代码展示了每个阶段的操作,但结果显示边缘不够平滑,可能在边缘连接步骤存在改进空间。
236





