本来打算作canny边缘检测的作业的,但是因为在量化方向那个部分我用的是条件判断,所以速度非常慢,大概十分钟才跑完几行像素,然后就搁置了,ddl前两天才开始做的HOG特征提取。从HOG的算法中得到了一些启发,所以想把没完成的canny边缘检测继续做完。
步骤如下:
l 应用高斯滤波平滑图像,去除噪声
l 计算滤波后图像各像素的梯度
l 应用非最大抑制技术消除可能的边缘误检
l 应用双阈值的方法确定边缘
想着老师的PPT应该也是有版权的,还是别放了,自己有懒得写原理,就算了吧。
代码如下:
clear all;
clc;
img = imread('lena.png'); %读取图像
%subplot(1,3,1);imshow(img);title('原图');
[m,n] = size(img);
w = fspecial('gaussian');
img_1 = imfilter(img,w,'replicate');
%subplot(1,3,2);imshow(img_1);title('高斯滤波后的图像');
%计算滤波后各像素的梯度,sobel算子
hy = [-1,0,1;-2,0,2;-1,0,1]; %定义竖直方向上的模板
hx = [1,2,1;0,0,0;-1,-2,-1]; %定义水平方向上的模板
grady = filter2(hy,img_1); %计算竖直方向梯度
gradx = filter2(hx,img_1); %计算水平方向梯度
grad = sqrt(gradx.^2+grady.^2); %计算梯度幅值
theta = atan(grady/gradx)/3.14159*180; %计算梯度方向
%将梯度方向量化到四个方向上
for i = 1:m
for j = 1:n
if theta(i,j) < 0 %因为atan输出的结果在(-90°,90°)
theta(i,j) = theta(i,j) + 180; %所以将三四象限转到一二象限计算,原点对称
end
theta(i,j) = theta(i,j) + 22.5; %等价于将坐标轴旋转
theta(i,j) = ceil(theta(i,j)/45)-1; %量化
if theta(i,j) == 4; %避免有旋转后有180°的情况
theta(i,j) = 0;
end
end
end
%应用非最大抑制技术消除可能的边缘误检(图像边缘的像素怎么办?)
%选取梯度方向上的最大值
for i = 2:m-1
for j = 2:n-1
if theta(i,j) == 0
A = [grad(i-1,j),grad(i+1,j)];
if grad(i,j) < max(A)
grad(i,j) = 0;
end
elseif theta(i,j) == 1
A = [grad(i+1,j-1),grad(i-1,j+1)];
if grad(i,j) < max(A)
grad(i,j) = 0;
end
elseif theta(i,j) == 2
A = [grad(i,j+1),grad(i,j-1)];
if grad(i,j) < max(A)
grad(i,j) = 0;
end
elseif theta(i,j) == 3
A = [grad(i-1,j-1),grad(i+1,j+1)];
if grad(i,j) < max(A)
grad(i,j) = 0;
end
end
end
end
%应用双阈值的方法确定边缘
%先确定哪些像素一定是边缘和哪些像素一定不是边缘
up = 100 ;%上阈值
low = 33 ; %下阈值
for i = 2:m
for j =2:m
if grad(i,j) >= up
grad(i,j) = 255;
elseif grad(i,j) < low
grad(i,j) = 0;
end
end
end
%然后在剩下的像素的八邻域内是否有边缘,如果有,则这个像素是边缘
for i = 2:m-1
for j = 2:n-1
tem=[grad(i-1,j-1),grad(i,j-1),grad(i+1,j-1);
grad(i,j-1),grad(i,j),grad(i,j+1);
grad(i+1,j-1),grad(i,j+1),grad(i+1,j+1)];
if max(tem) == 255
grad(i,j)=255;
else
grad(i,j)=0;
end
end
end
imshow(grad),title('canny边缘检测');
%imwrite(grad,'result.png');
很悲伤的一件事情,在我写这篇博客记录我的作业的时候,发现我的求梯度水平方向和竖直方向搞错了,所以我求的梯度方向也不对……然而我的HOG特征是直接把canny边缘检测的求梯度复制过去的,而且作业已经交了,难受了。
结果图:
修改了梯度模板的结果
水平模板和竖直模板搞反了的结果
参考博客找不到了,不好意思!