hough算法及其应用

一、实验目的

(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)中,由于是数字图像且采取极坐标,angler都取

% 一定的范围和步长,这样通过两重循环(angle循环和r循环)即可将原图像

% 空间的点映射到参数空间中,再在参数空间(即一个由许多小立方体组成的

% 大立方体)中寻找圆心,然后求出半径坐标。输入参数

% BW:二值图像;

% step_r:检测的圆半径步长

% step_angle:角度步长,单位为弧度

% r_min:最小圆半径

% r_max:最大圆半径

% p:p*hough_space的最大值为阈值,p01之间的数

%输出参数

% 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参数空间的线-点对偶性,把图像空间中的检测问题转换到参数空间中进行。

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值