这个过去用就写过,这次正好有人问这个算法,所以在这里又把C代码改为了matlab了。
霍夫变换是把原图像中的直线上的每一个点转换到参数空间对应的曲线上,由于每一个点对应一条曲线,因此在参数空间中所有曲线会相交到一个点,形成一个最值。因此原图寻找直线斜率的问题就变成了参数空间寻找最值的问题了。
代码如下:
clear all; close all; clc; %% %以下只是做一个带直线的图像而已 r=300; jiaodu=30; %更改这个值测试,90度270度时不管用 jiaodu1=mod(jiaodu,360); flag=0; if jiaodu1>=0 && jiaodu1<90 jiaodu1=jiaodu1; flag=1; end if jiaodu1>=90 && jiaodu1<180 jiaodu1=180-jiaodu1; flag=2; end if jiaodu1>=180 && jiaodu1<270 jiaodu1=jiaodu1-180; flag=3; end if jiaodu1>=270 && jiaodu1<360 jiaodu1=360-jiaodu1; flag=4; end H=floor(r*sin(jiaodu1*pi/180)); W=floor(r*cos(jiaodu1*pi/180)); if mod(H,2)==0 H=H+1; end if mod(W,2)==0 W=W+1; end w=zeros(H,W); if jiaodu1 ~= 90 && jiaodu1 ~= 270 for i=1:H for j=1:W tmp=floor(j*tan(jiaodu1*pi/180)); if tmp+1==i w(i,j)=r; end end end else for i=1:H w(i,1)=r; end end if flag==1 || flag==3 %如果角度在1,3象限,卷积矩阵上下翻转 w=flipud(w); end %% %下面是真正的霍夫变换 img=mat2gray(w); %处理这个图像 [m n]=size(img); imshow(img); data=zeros(314,2*(m+n)); for i=1:m %将图像二维空间的一个点映射到p=x*cos(theta)+y*sin(theta)方程对应的参数空间的一条曲线 for j=1:n if img(i,j)==1 for theta=0.01:0.01:3.14 data(round(theta*100),round(i*sin(theta)+j*cos(theta)+m+n))= ... data(round(theta*100),round(i*sin(theta)+j*cos(theta)+m+n))+1; end end end end theta=0; ma=0; for i=1:314 %寻找曲线相交最多的那个点,即找最大值 for j=1:2*(m+n) if data(i,j)>ma ma=data(i,j); theta=i/100; rou=j-m-n; end end end figure;imshow(data) %形象的显示参数空间曲线 sr_k=tan(jiaodu*pi/180) %设置的斜率 re_k=cos(theta)/sin(theta) %求得的斜率
做出的一条直线
参数空间中的曲线
30度时斜率是0.5774,霍夫变换求得的斜率是0.5736。