一、简介
霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,它通过一种投票算法检测具有特定形状的物体。该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换结果。霍夫变换于1962年由Paul Hough 首次提出[53],后于1972年由Richard Duda和Peter Hart推广使用[54],经典霍夫变换用来检测图像中的直线,后来霍夫变换扩展到任意形状物体的识别,多为圆和椭圆。
霍夫变换运用两个坐标空间之间的变换将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转化为统计峰值问题,上一节中已经介绍了车道的直线特征,本节中介绍hough变换检测直线的原理和检测结果。
我们知道,一条直线在直角坐标系下可以用y=kx+b表示, 霍夫变换的主要思想是将该方程的参数和变量交换,即用x,y作为已知量k,b作为变量坐标,所以直角坐标系下的直线y=kx+b在参数空间表示为点(k,b),而一个点(x1,y1)在直角坐标系下表示为一条直线y1=x1·k+b,其中(k,b)是该直线上的任意点。为了计算方便,我们将参数空间的坐标表示为极坐标下的γ和θ。因为同一条直线上的点对应的(γ,θ)是相同的,因此可以先将图片进行边缘检测,然后对图像上每一个非零像素点,在参数坐标下变换为一条直线,那么在直角坐标下属于同一条直线的点便在参数空间形成多条直线并内交于一点。因此可用该原理进行直线检测。
如图 所示,对于原图内任一点(x,y)都可以在参数空间形成一条直线,以图中一条直线为例有参数(γ,θ)=(69.641,30°),所有属于同一条直线上的点会在参数空间交于一点,该点即为对应直线的参数。由该图中所有直线所得到的(γ,θ)在参数空间中得到一系列对应曲线见图 霍夫统计变换结果。
二、源代码
clear all;
close all;
i=imread('yanjing.bmp');
imshow(i);
iii=i;
%把输入图象二值化,用canny算法返回阈值
sigma=3.0;
thresh=[0.03,0.09];
bw_1=i>70;
edgerm=edge(bw_1,'canny',thresh,sigma);
figure,imshow(edgerm);
t1=280;
s=0;
while t1>10
t2=1;
while t2<310
%查找第一个边缘点
if edgerm(t1,t2)==1
u1=t1;
u2=t2;
s=1;
end
if s==1
break;
end
t2=t2+1;
end
t1=t1-1;
end
po=1;
sum2=0;
%第一个边缘点
o1=u1;
o2=u2;
hang=zeros(0,0);
lie=zeros(0,0);
while (po==1)
while (po==1)
sum1=0;
for t3=1:5
for t4=1:5
% 第一个边缘点的左上方5个像素内有边缘点
if edgerm(u1-t3+1,u2+t4-1)==1
% 第一个边缘点周围的边缘点个数
sum1=sum1+1;
sum2=sum2+1;
% 第sum1个边缘点位置x
hang(sum1,1)=u1-t3+1;
% 第sum1个边缘点位置y
hang(sum1,2)=u2+t4-1;
lie(sum2,1)=u1-t3+1;
lie(sum2,2)=u2+t4-1;
end
end
end
% 边缘点只有一个
if sum1==1
po=0;
% 没有边缘点
elseif sum1==0
po=0;
else
% 以最后的边缘点为起点,进行下一轮搜索
u1=hang(sum1,1);
u2=hang(sum1,2);
po=1;
end
end
% 边缘点个数小于30个
if sum2<30
u1=o1;
u2=o2+1;
po=1;
sum2=0;
% 横坐标不变,改变纵坐标值得到边缘点
while (edgerm(u1,u2)~=1)
while (edgerm(u1,u2)~=1)&(u2<310)
% 不是边缘点,纵坐标加1
u2=u2+1;
end
% 没有得到边缘点
if u2==310
u1=u1-1;
u2=1;
end
end
% x不变,改变y重新得到边缘点
o1=u1;
o2=u2;
else
break;
end
end
% 边缘点个数
a1=size(lie);
w1=lie(a1(1),1);
w2=lie(a1(1),2);
po1=1;
while (po1==1)
sum1=0;
for t1=1:3
for t2=1:5
% 边缘点向左方3个像素,上方5个像素
if edgerm(w1-t1+1,w2-t2+1)==1
sum1=sum1+1;
sum2=sum2+1;
lie(sum2,1)=w1-t1+1;
lie(sum2,2)=w2-t2+1;
hang(sum1,1)=w1-t1+1;
hang(sum1,2)=w2-t2+1;
end
end
end
% 边缘点只有一个
if sum1==1
po1=0;
else
po1=1;
w1=hang(sum1,1);
w2=hang(sum1,2);
end
end
po2=1;
while (po2==1)
sum1=0;
for t1=1:7
for t2=1:15
if edgerm(w1+t1-1,w2-t2+1)==1
sum1=sum1+1;
sum2=sum2+1;
lie(sum2,1)=w1+t1-1;
lie(sum2,2)=w2-t2+1;
hang(sum1,1)=w1+t1-1;
hang(sum1,2)=w2-t2+1;
end
end
end
if sum1==1
po2=0;
else
po2=1;
w1=hang(sum1,1);
w2=hang(sum1,2);
end
end
%不止一个边缘点
while (w1~=lie(1,1))&(w2~=lie(1,2))
sum1=0;
for t1=1:5
for t2=1:5
%向右向上5个像素搜索边缘点
if edgerm(w1+t1-1,w2+t2-1)==1
sum1=sum1+1;
sum2=sum2+1;
lie(sum2,1)=w1+t1-1;
lie(sum2,2)=w2+t2-1;
hang(sum1,1)=w1+t1-1;
hang(sum1,2)=w2+t2-1;
end
end
end
w1=hang(sum1,1);
w2=hang(sum1,2);
end
for t1=1:280
for t2=1:320
% 初始化Hough矩阵
e(t1,t2)=0;
end
end
% 边缘点个数
for t1=1:size(lie)
% 将是边缘点的位置设为1
e(lie(t1,1),lie(t1,2))=1;
end
%确定瞳孔的边缘的上下限
minl=320;
maxl=1;
minh=280;
maxh=1;
for t1=1:280
for t2=1:320
if (e(t1,t2)==1)&(t2<minl)
minl=t2;
end
if (e(t1,t2)==1)&(t2>maxl)
maxl=t2;
end
if (e(t1,t2)==1)&(t1<minh)
minh=t1;
end
if (e(t1,t2)==1)&(t1>maxh)
maxh=t1;
end
end
end
% 采用二值化的方法求得瞳孔的面积sum3
sum3=0;
t1=minh;
while t1<=maxh
t2=minl;
while t2<=maxl
if (bw_1(t1,t2)==0)
sum3=sum3+1;
end
t2=t2+1;
end
t1=t1+1;
end
% 得到瞳孔r1半径向上取整,sum3表示瞳孔的面积
r1=ceil(sqrt(sum3/pi));
% 向下取整 估算出瞳孔圆心x坐标
c(1,1)=floor((maxh-minh)/2+minh);
c(1,2)=ceil((maxl-minl)/2+minl);
r2=ceil(r1/3);
r3=2*r2;
for t1=1:ceil(r1/6)*2
for t2=1:ceil(r1/6)*2
pu(t1,t2)=0;
end
end
%pu中存放有相同圆心点的个数,以下找一个最大的pu认为是瞳孔的圆心
t1=minh;
while t1<=maxh
t2=minl;
while t2<=maxl
if (e(t1,t2)==1)
for a=1:2*ceil(r1/6)
for b=1:2*ceil(r1/6)
if (((t1-(c(1,1)+ceil(r1/6)-a))^2+(t2-(c(1,2)-ceil(r1/6)+b))^2-r1^2)>-10)&(((t1-(c(1,1)+ceil(r1/6)-a))^2+(t2-(c(1,2)-ceil(r1/6)+b))^2-r1^2)<10)
% 以a,b为圆心的圆累加个数
pu(a,b)=pu(a,b)+1;
end
end
end
end
t2=t2+1;
end
t1=t1+1;
end
ma=pu(1,1);
% 选取同心圆最多的圆心
for a=1:2*ceil(r1/6)
for b=1:2*ceil(r1/6)
if (ma<pu(a,b))
ma=pu(a,b);
row=a;
col=b;
end
end
end
% 圆心坐标
c(1,1)=c(1,1)+ceil(r1/6)-row;
c(1,2)=c(1,2)-ceil(r1/6)+col;
j=double(i);
for t1=1:280
for t2=1:320
%虹膜内边缘设为白色
if ((t1-c(1,1))^2+(t2-c(1,2))^2-r1^2<80)&((t1-c(1,1))^2+(t2-c(1,2))^2-r1^2>-80)
i(t1,t2)=255;
end
end
end
row1=c(1,1);
col1=c(1,2);
%以上找到圆心(row1,col1),半径r1;
ha=row1;
li=col1;
sh1=1;
zong=0;
while sh1<=3
sh2=1;
while sh2<=3
zong=zong+1;
% 圆心向左、不变、向右移动2
row1=ha-4+sh1*2;
col1=li-4+sh2*2;
j1=double(i);
u=zeros(0,0);
for t1=1:row1
t2=col1;
while t2<=310
%第一像限的图像对角变换
u(row1-t1+1,t2-col1+1)=j1(t1,t2);
t2=t2+1;
end
end
u1=double(u);
%第一像限图像的行列数
yy=size(u);
%瞳孔半径r1
rr=r1+40;
l1=r1+40;
l2=1;
ll1=0;
n1=l1;
sq1=0;
%yy(1,2)表示第一像限的矩阵列数,yy(1,1)行数
while (l2<l1)&(l1<yy(1,2))&(l2<yy(1,1))
pk=(l1-1/2)^2+(l2+1)^2-rr^2;
%半径在rr+40范围内
if pk<0
%沿着l1方向灰度值累加
sq1=sq1+u1(l2+1,l1);
%记录sql的个数
ll1=ll1+1;
l1=l1;
l2=l2+1;
else sq1=sq1+u1(l2+1,l1-1);
ll1=ll1+1;
l1=l1-1;
l2=l2+1;
end
end
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
- 248.
- 249.
- 250.
- 251.
- 252.
- 253.
- 254.
- 255.
- 256.
- 257.
- 258.
- 259.
- 260.
- 261.
- 262.
- 263.
- 264.
- 265.
- 266.
- 267.
- 268.
- 269.
- 270.
- 271.
- 272.
- 273.
- 274.
- 275.
- 276.
- 277.
- 278.
- 279.
- 280.
- 281.
- 282.
- 283.
- 284.
- 285.
- 286.
- 287.
- 288.
- 289.
- 290.
- 291.
- 292.
- 293.
- 294.
- 295.
- 296.
- 297.
- 298.
- 299.
- 300.
- 301.
- 302.
- 303.
- 304.
- 305.
- 306.
- 307.
- 308.
- 309.
- 310.
- 311.
- 312.
- 313.
- 314.
- 315.
- 316.