霍夫变换函数检测条纹图像中的黑色条纹
边缘检测在图像处理中经常用到,目的是标识数字图像中亮度变化明显的点,即存在亮度跳跃的区域。Matlab中有edge函数来实现这个功能,利用传入参数的不同可以使用不同的算子,比如Prewitt、Canny等,通过这个函数返回的是一个二值图像矩阵。我们再利用这个矩阵作霍夫变换找到图像中的条纹。
1、读入图像
figure;
[I,map] = imread(filename);
subplot(2,2,1);
imshow(I,map);
axis on,hold on;
title('原图读入');
2、加入高斯滤波器减噪
经过测试,发现窗口大小为[5,5],标准差为0.5的时候最合适。
sigma = 0.5;
gausFilter = fspecial('gaussian', [5,5], sigma);
I= imfilter(I, gausFilter, 'replicate');
imshow(I);
axis on,hold on;
title('经过高斯降噪');
3、边缘检测
BW = edge(I,'Prewitt');%Prewitt算子边缘检测
4、标准霍夫变换
[H,T,R] = hough(BW);%计算二值图像的标准霍夫变换,H为霍夫变换矩阵,I,R为计算霍夫变换的角度和半径值
subplot(2,2,3);
imshow(H,[],'XData',T,'YData',R,'InitialMagnification','fit');%hough变换后的图像
title('hough变换后的图像');
xlabel('\theta'), ylabel('\rho');
axis on,axis square,hold on;
5、在霍夫变换矩阵中选取8个峰值
在霍夫变换矩阵H中一个点实际上代表一条直线,由直线的参数方程得知。
P是一个Q×2的矩阵,每行的两个元素分别是某一峰值点在H中的行、列索引,Q为找到的峰值点的数目。
P = houghpeaks(H,8);
x = T(P(:,2));
y = R(P(:,1));
plot(x,y,'s','color','white');%标出极值点
6、提取线段
line是一个结构体数组,包括point1(起点)、point2(终点),theta,rho。其中theta,rho分别代表直线的参数方程ρ=x*cosθ+y*sinθ中的θ和ρ。line数组中的每一个元素代表一条线段。
line=houghlines(BW,T,R,P,'FillGap', 40, 'MinLength', 10);%提取线段
7、合并横坐标相同的线段
由于存在计算误差,相同的一条线段可能被检测成两条,因此需要将它们合并,并且按照横坐标从小到大排序。
[lines]=combineLines(line);
subplot(2,2,4);
imshow(I), hold on;
axis on,hold on;
8、画出线段并且计算相邻线段之间的距离
由于直线都是平行于y轴,因此直接由横坐标相减便可得到两线段之间的距离。
temp = 0;
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',1,'Color','white');%画出线段
if temp>0
text(temp,300,num2str(xy(1,1)-temp),'color','green','fontsize',8);
end
temp = xy(1,1);
end
title('数字表示相邻线段之间的距离(px)');
end
附录
https://www.zybuluo.com/lutingting/note/554459#hough变换原始形式-直线检测