直线的解析式有多种形式,由于用斜率描述的直线存在斜率无穷大的特殊情况,这里选用直线的极坐标描述:ρ=хcos(θ)+уsin(θ)
式中ρ为直线到原点的距离,θ为限定了直线的斜率。对于任意一组确定的(ρ,θ),上式都可以唯一确定一条直线。开辟二维参数空间H(ρ,θ),对ρ,θ整数化,则对于任意有限平面区域,参数空间H可以表示为有限个点的集合。而H(ρ,θ)中任意点都一一对应原平面区域上的一条直线。
将上述结论推广到任意平面图像上可知,图像上任意直线区域都可以一一对应参数空间H(ρ,θ)中一个点,而图像上的任意像素都同时存在于很多直线区域之上。可以将图像上的直线区域想象为容器,把特定像素想象成放在容器中的棋子,只不过在这里,每个棋子都可以同时存在于多个容器中。那么Hough变换可以理解为依次检查图像上的每个棋子(特定像素),对于每个棋子,找到所有包含它的容器(平面上的直线区域),并为每个容器的计数器加1,这们就可以统计出每个容器所包含的棋子数量。当图像中某个直线区域包含的特定像素足够多(大于设定的阈值K)时,就可以认为直线区域表示的直线存在。
用二维向量(ρ,θ)描述图像上的每一条直线区域,则可将图像上的直线区域计数器映射到参数空间H(ρ,θ)中的存储单元。由于ρ为直线区域到原点的距离,因此对于对角线长度为n的图像,固定左上角为原点,可得到ρ的取值范围为[0,n],令θ以1度为增量,可得到θ的取值范围为[0,180]。定义二维数组
accarray(ρ, θ)作为存储单元,其中对于任意(ρ,θ)决定的直线区域,计数器为accarray(ρ,
θ)。
对于
直线的Hough变换过程可以简单描述为,依次遍历图像的所有像素,对于每个像素判断是否满足特定的条件,若满足则对经过该像素的所有直线区域的计数器加1,否则继续判断下一个像素。为了得到经过某个像素的所有直线区域,可以依次用θ的所有可能取值,借助此像素的坐标和直线的极坐标方程计算ρ,而每一组(ρ,θ)就对应了一条经过此像素的直线区域。
RGB = imread('olympic.jpg');%Read the image
Highlight=RGB;
I=rgb2gray(RGB); %transform the image to gray
[x,y]=size(I); %get the size of the
picture
BW=edge(I);
%get the edge of the picture
rho_max=floor(sqrt(x^2+y^2))+1; %由原图数组坐标算出ρ最大值,并取整数部分加1
%此值作为ρ,θ坐标系ρ最大值
accarray=zeros(rho_max,180); %定义ρ,θ坐标系的数组,初值为0。
%θ的最大值,180度
Theta=[0:pi/180:pi]; %定义θ数组,确定θ取值范围
for n=1:x,
for m=1:y
if BW(n,m)==1
for
k=1:180
%将θ值代入hough变换方程,求ρ值
rho=(m*cos(Theta(k)))+(n*sin(Theta(k)));
%将ρ值与ρ最大值的和的一半作为ρ的坐标值(数组坐标),这样做是为了防止ρ值出现负数
rho_int=round(rho/2+rho_max/2);
%在ρθ坐标(数组)中标识点,即计数累加
accarray(rho_int,k)=accarray(rho_int,k)+1;
end
end
end
end
%=======利用hough变换提取直线======%
%寻找100个像素以上的直线在hough变换后形成的点
K=1; %存储数组计数器
for rho_n=1:rho_max %在hough变换后的数组中搜索
for theta_m=1:180
if accarray(rho_n,theta_m)>=100
%设定直线的最小值。
case_accarray_n(K)=rho_n; %存储搜索出的数组下标
case_accarray_m(K)=theta_m;
K=K+1;
end
end
end
%=====把这些点构成的直线提取出来,输出图像数组为I_out===%
I_out=zeros(x,y);
I_jiao_class=zeros(x,y);
for n=1:x,
for m=1:y
if BW(n,m)==1
for k=1:180
rho=(m*cos(Theta(k)))+(n*sin(Theta(k)));
rho_int=round(rho/2+rho_max/2);
%如果正在计算的点属于100像素以上点,则把它提取出来
for a=1:K-1
if
rho_int==case_accarray_n(a)&k==case_accarray_m(a)%%%==gai==%%%
k==case_accarray_m(a)&rho_int==case_accarray_n(a)
I_out(n,m)=BW(n,m);
for p=0:5
%在原RGB图像上高亮
Highlight(n,m+p,1)=255;
Highlight(n,m+p,2)=0;
Highlight(n,m+p,3)=0;
end
I_jiao_class(n,m)=k;
end
end
end
end
end
end
figure,imshow(RGB);
title('原图');
imwrite(RGB,'原图.jpg','jpg');
figure,imshow(BW);
title('edge处理后的边界图');
imwrite(BW,'edge处理后的边界图.jpg','jpg');
figure,imshow(I_out);
title('Hough变换检测出的直线');
imwrite(I_out,'Hough变换检测出的直线.jpg','jpg');
figure,imshow(Highlight);
title('高亮后的图');
imwrite(Highlight,'高亮后的图.jpg','jpg');