霍夫变换(Hough)通过转换坐标系,将特定形状的检测映射到参数空间中,从而根据参数空间中的值来确定特定形状的相关信息。
Hough变换的比较简单的应用例子有检测直线。
检测直线
设空间中有若干点,我们要判断这些点是否能构成一条直线,即为直线检测。平面中直线的通用公式为xcos(θ)+ysin(θ)=ρxcos(θ)+ysin(θ)=ρ。常用的y=wx+by=wx+b公式,因为不能兼容y=by=b的情况,所以不能使用。对于某个点,其坐标是(xi,yi)(xi,yi),过该点的直线有无数条,这些直线统一表示为xicos(θ)+yisin(θ)=ρxicos(θ)+yisin(θ)=ρ,其中xi,yixi,yi是常量。反过来看,代表这些直线的公式,可以看做θθ为自变量,ρρ为因变量,xi,yixi,yi为常量参数的直线公式。这样,在x-y空间过(xi,yi)(xi,yi)的无数条直线,可以在θ−ρθ−ρ空间中用一条线代表。见下图:
上图是x-y空间,下图是θ−ρθ−ρ空间。其中红、绿、蓝三条线可以汇聚成一个点,说明这三条线对应的点,其在θ−ρθ−ρ空间中的直线参数是一样的。反过来就是说,穿过这三个点的无数直线中,有“三”条直线,其θ,ρθ,ρ值相同,这“三“条直线是一根直线,即这三个点可以共线。
通过量化霍夫参数空间为有限个值间隔等分或者累加格子。当霍夫变换算法开始,每个像素
坐标点P(x, y)被转换到(r, theta)的曲线点上面,累加到对应的格子数据点,当一个波峰出现
时候,说明有直线存在。
编程思路解析:
读取一幅带处理二值图像,最好背景为黑色。
取得源像素数据
根据直线的霍夫变换公式完成霍夫变换,预览霍夫空间结果
寻找最大霍夫值,设置阈值,反变换到图像RGB值空间(程序难点之一)
越界处理,显示霍夫变换处理以后的图像
对于0~70°范围内直线检测结果:
-70~0°范围内直线检测:
matlab代码:
%% 霍夫曼变换 检测直线
clear all;
close all;
% I=imread('gantrycrane.png');
I=imread('3.jpg');
Ihsv=rgb2hsv(I);
Iv=Ihsv(:,:,3);%提取v空间
Ivl=Iv(:,:);%截取下半部
Iedge=edge(Ivl,'sobel');%边沿检测
% Iedge = imdilate(Iedge,ones(3));%图像膨胀
%新建窗口,绘图用
figure;
imshow(uint8(255*Iedge));title('orignal picture')
%左方直线检测与绘制
%得到霍夫空间
[H1,T1,R1] = hough(Iedge,'Theta',0:0.1:75);
figure;
imshow(imadjust(mat2gray(H1)),'XData',T1,'YData',R1,...
'InitialMagnification','fit');
title('Limited theta range Hough transform of gantrycrane.png');
xlabel('\theta'), ylabel('\rho');
axis on, axis normal;
%求极值点
Peaks=houghpeaks(H1,8);
hold;
for i=1:8
plot(T1(Peaks(i,2)),R1(Peaks(i,1)),'ro','LineWidth',4);
end
%得到线段信息
lines=houghlines(Iedge,T1,R1,Peaks);
figure;
imshow(uint8(255*Iedge));title('after picture'); hold on
%绘制线段
for k=1:length(lines)
xy=[lines(k).point1; lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',4);
end
%右方直线检测与绘制
[H2,T2,R2] = hough(Iedge,'Theta',-75:0.1:-20);
Peaks2=houghpeaks(H2,6);
lines2=houghlines(Iedge,T2,R2,Peaks2);
figure;
imshow(imadjust(mat2gray(H2)),'XData',T2,'YData',R2,...
'InitialMagnification','fit');
title('Limited theta range Hough transform of gantrycrane.png');
xlabel('\theta'), ylabel('\rho');
axis on, axis normal;
hold;
for i=1:6
plot(T2(Peaks2(i,2)),R2(Peaks2(i,1)),'ro','LineWidth',4);
end
figure;
imshow(uint8(255*Iedge));title('after picture 2'); hold on
for k=1:length(lines2)
xy2=[lines2(k).point1;lines2(k).point2];
plot(xy2(:,1),xy2(:,2),'LineWidth',4);
end