一、实验目的
(1)掌握 hough 变换的算法思想,能够利用 hough 变换检测直线和圆。
二、实验内容
必做项:
(1)对 Logo 和车道线等图像进行边缘检测;
(2)参考 PPT 上的代码对边缘图像进行 hough 变换,可视化参数空间投票矩阵,即ρ-θ图。
(3)参考实验指导书,自己编码实现 Matlab 中的 Hough()函数功能,即输入边缘数据(二值图像),计算得到投票矩阵。
(4)根据同样的思想,参考实验指导书,编写圆的 hough 变换函数,检测出 Logo 图像中的圆。
选做项:
椭圆的方程和圆近似,是否可以通过这个想法实现椭圆检测。用 matlab 实现。
三、实验原理
该实验类型为应用型实验:以hough变换的算法的理论为基础,完成对直线和圆的检测的设计,掌握hough变换原理的应用,掌握MATLAB平台的设计方法。
四、实验结果分析
(1)对 Logo 和车道线等图像进行边缘检测,具体代码如下:
J=imread('车道线1.png');
G=im2bw(J);
% 提取二值图像图像边缘
BW=bwperim(G);
figure;
imshow(BW);title('边缘图像');
J=imread('logo.png');
G=im2bw(J);
% 提取二值图像图像边缘
BW=bwperim(G);
figure;
imshow(BW);title('边缘图像');
J=imread('车道线2.png');
G=im2bw(J);
% 提取二值图像图像边缘
BW=bwperim(G);figure;
imshow(BW);title('边缘图像');
运行后可以得到下图所示的图形:
图1 车道线1边缘检测图像
图2 logo边缘检测图像
图3 车道线2边缘图像
由上面三个图可看到,Logo 和车道线等的图像的边缘状况,其边缘状况与原图像大致是吻合的,以此说明该代码运行准确。
(2)对边缘图像进行 hough 变换,可视化参数空间投票矩阵,即ρ-θ图。
I=imread('车道线2.png');
I=rgb2gray(I);
figure
imshow(I);
rotl=imrotate(I,14,'crop');
BW=edge(rotl,'canny');
[H,T,R]=hough(BW);
figure
imshow(H,[],'XData',T,'YData',R,'InitialMagnification','fit');
axis on;
axis normal;
hold on;
xlabel('\theta');
ylabel('\rho');
P=houghpeaks(H,5,'threshold',ceil(0.3*max(H(:))));
x=T(P(:,2));
y=R(P(:,1));
plot(x,y,'s','color','white');
lines=houghlines(BW,T,R,P,'FillGap',5,'MinLength',7);
figure
imshow(rotl);hold on;
max_len=0;
for k=1:length(lines) xy=[lines(k).point1;lines(k).point2]; plot(xy(:,1),xy(:,2),'linewidth',1,'color','green'); plot(xy(1,1),xy(1,2),'x','linewidth',2,'color','yellow'); plot(xy(2,1),xy(2,2),'x','linewidth',2,'color','red');
len=norm(lines(k).point1-lines(k).point2);
if(len>max_len)
max_len=len;
xy_long=xy;
end
end
plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','blue');
如下所示:
图4
图5
图6
对边缘图像进行 hough 变换,可视化参数空间投票矩阵,即ρ-θ图。实际上图像中的边缘点数是非常多的,利用 hough 变换进行图像的直线检测时,就需要
找出图像中R最大的值构建ρ-θ坐标系。通常情况下我们会利用图像的对角线长构建出最大的坐标系,由于在图像像素坐标系中坐标都是正数,这意味着只需考虑第一象限的直线,为了减少创建的参数空间使用的内存,适当的进行坐标平移减少参数空间的大小。把参数空间变为三维,每个点都给他一个值。当有一条曲线经过这个点时候值就加一。当遍历完所有的点时候分析这个累加器的值,符合我们要求的点,就可以找到图像中的直线了。
(3)参考实验指导书,自己编码实现 Matlab 中的 Hough()函数功能,即输入边缘数据(二值图像),计算得到投票矩阵。
function[H,T,R]=my_hough(BW)
[m,n]=size(BW);
theta_max=90;
rho_max=floor(sqrt(m^2+n^2))-1;
T=-theta_max:theta_max-1;
R=-rho_max:rho_max;
H=zeros(length(R),length(T));
for i=1:1:m
for j=1:1:n
if BW(i,j)>0
x=j-1;
y=i-1;
for theta=T rho=round((x*cosd(theta))+(y*sind(theta))); rho_index=rho+rho_max+1; theta_index=theta+theta_max+1; H(rho_index,theta_index)=H(rho_index,theta_index)+1;
end
end
end
end
脚本:
J=imread('logo.png');
J=imresize(J,1/4);
G=im2bw(J);
BW=bwperim(G);
[H,T,R]=my_hough(BW);
P=houghpeaks(H,18,'threshold',ceil(0.1*max(H(:))));
figure;
imshow(J);
figure;
imshow(BW);
hold on;
figure;
x=T(P(:,2));
y=R(P(:,1));
set(0,'defaultFigurePosition',[100,100,1000,500]);
set(0,'defaultFigurecolor',[1 1 1]);
imshow(imadjust(mat2gray(H)),'XData',T,'YData',R,'InitialMagnification','fit');
axis on;
axis normal;
hold on;
xlabel('\theta');
ylabel('\rho');
hold on;
plot(x,y,'s','color','red');
figure;
lines=houghlines(BW,T,R,P,'FillGap',5,'MinLength',7);
imshow(BW);
hold on;
for k=1:length(lines) xy=[lines(k).point1;lines(k).point2]; plot(xy(:,1),xy(:,2),'linewidth',1,'color','green'); plot(xy(1,1),xy(1,2),'x','linewidth',2,'color','yellow'); plot(xy(2,1),xy(2,2),'x','linewidth',2,'color','red');
end
在命令窗口运行,可以得到如下图所示的图形。
图7
图8
图9
图10
输入边缘数据(二值图像),计算得到投票矩阵
(4)根据同样的思想,参考实验指导书,编写圆的 hough 变换函数,检测出 Logo 图像中的圆。代码如下:
function[hough_space,hough_circle,para] = hough_circle(BW,step_r,step_angle,r_min,r_max,p)
%[HOUGH_SPACE,HOUGH_CIRCLE,PARA] =HOUGH_CIRCLE(BW,STEP_R,STEP_ANGLE,R_MAX,P)
%算法概述
% 该算法通过a = x-r*cos(angle),b = y-r*sin(angle)将圆图像中的边缘点
% 映射到参数空间(a,b,r)中,由于是数字图像且采取极坐标,angle和r都取
% 一定的范围和步长,这样通过两重循环(angle循环和r循环)即可将原图像
% 空间的点映射到参数空间中,再在参数空间(即一个由许多小立方体组成的
% 大立方体)中寻找圆心,然后求出半径坐标。输入参数
% BW:二值图像;
% step_r:检测的圆半径步长
% step_angle:角度步长,单位为弧度
% r_min:最小圆半径
% r_max:最大圆半径
% p:以p*hough_space的最大值为阈值,p取0,1之间的数
%输出参数
% hough_space:参数空间,h(a,b,r)表示圆心在(a,b)半径为r的圆上的点数
% hough_circl:二值图像,检测到的圆
% para:检测到的圆的圆心、半径
% From Internet,Modified by mhjerry,2011-12-11
[m,n] = size(BW);
size_r=round((r_max-r_min)/step_r)+1;
size_angle= round(2*pi/step_angle);
hough_space = zeros(m,n,size_r);
[rows,cols] = find(BW);
ecount = size(rows);
% Hough变换
% 将图像空间(x,y)对应到参数空间(a,b,r)
% a = x-r*cos(angle)
% b = y-r*sin(angle)
for i=1:ecount
for r=1:size_r
for k=1:size_angle
a = round(rows(i)-(r_min+(r-1)*step_r)*cos(k*step_angle));
b = round(cols(i)-(r_min+(r-1)*step_r)*sin(k*step_angle));
if(a>0&&a<=m&&b>0&&b<=n)
hough_space(a,b,r) = hough_space(a,b,r)+1;
end
end
end
end
% 搜索超过阈值的聚集点
max_para= max(max(max(hough_space)));
index=find(hough_space>=max_para*p);
length = size(index);
hough_circle=zeros(m,n);
for i=1:ecount
for k=1:length
par3 = floor(index(k)/(m*n))+1;
par2 = floor((index(k)-(par3-1)*(m*n))/m)+1;
par1 = index(k)-(par3-1)*(m*n)-(par2-1)*m;
if((rows(i)-par1)^2+(cols(i)-par2)^2<(r_min+(par3-1)*step_r)^2+5&&...
(rows(i)-par1)^2+(cols(i)-par2)^2>(r_min+(par3-1)*step_r)^2-5) hough_circle(rows(i),cols(i)) = 1;
end
end
end
% 打印结果
for k=1:length
par3= floor(index(k)/(m*n))+1;
par2 = floor((index(k)-(par3-1)*(m*n))/m)+1;
par1 = index(k)-(par3-1)*(m*n)-(par2-1)*m;
par3 = r_min+(par3-1)*step_r;
fprintf(1,'Center %d %d radius %d\n',par1,par2,par3);
para(:,k) = [par1,par2,par3]';
end
脚本:
I=imread('logo.jpg');
[m,n,k] = size(I);
if k>1
I = rgb2gray(I);
end
BW = edge(I,'sobel');
step_r = 5;
step_angle = 0.1;% 5.7296 degrees
r_min = 30; %need to modify by factr_max = 70; %need to modify by fact
p = 0.5; % 76.8000
[hough_space,hough_circle,para] =hough_circle(BW,step_r,step_angle,r_min,r_max,p);
subplot(2,2,1),imshow(I),title('原图');
subplot(2,2,2),imshow(BW),title('边缘');
subplot(2,2,3),imshow(hough_circle),title('检测结果');
subplot(2,2,4),imshow(I,[]),title('检测出图中的圆') ;
hold on
%以红色线标记出的检测圆心与圆
plot(para(:,1), para(:,1), 'r+');
for k = 1:size(para, 1)
t=0:0.01*pi:2*pi;
x=cos(t).*para(k,2)+para(k,2);
y=sin(t).*para(k,2)+para(k,1);
plot(x,y,'r-');
end
在命令窗口运行,可以得到如下图所示的图形
图 11
1)算法原理:xy空间一个圆对应三维参数空间一个点(a,b,r),xy空间圆上一个点(x,y)对应参数空间一条曲线,xy空间圆上n个点对应参数空间n条相交于一点的曲线,对于原图中每一点,在参数空间确定一条曲线,经过曲线最多的点为原图中圆的参数。2)算法步骤:(1)假设原图像已经处理为二值边缘图像,扫描图中的每一个像素点:①背景点,不作任何处理②目标点,确定曲线:参数空间上的对应曲线上所有点的值累加1;(2)循环扫描所有点;(3)参数空间上累计值为最大的点为所求圆参数;(4)按照该参数与原图像同等大小的空白图像上绘制圆。3)简化运算:三维参数空间,计算量大,可以采样其他形式,如极坐标式,进行进一步简化;检测圆的时候可以采用类似检测直线的措施,由于圆方程的定义为(x-a)2+y-b2=r2
,这时候出现了三个参数 a,b,r。把这方程映射到极坐标系上。这时候a=x-ρ*cosθ
, b=y-ρ*sinθ
, r=ρ
,可以通过 r 来进一步确定参数空间中 a 和 b 的取值。把所有可能的圆映射到参数空间中的点,通过检索累加器的值找出最合适的圆。由图可知该程序运行成功。
五、实验小结
本次实验在理论学习的基础上,掌握了对于hough变换的算法思想,并利用 hough变换完成了实际应用:直线和圆的检测。Hough变换是一种使用表决方式的参数估计技术,其原理是利用图像空间和Hough参数空间的线-点对偶性,把图像空间中的检测问题转换到参数空间中进行。