Hough 变换检测圆—-Matlab实现(以虹膜检测为例)

一、hough变换的原理:

  1. 圆方程

(1)xy空间一个圆对应三维参数空间一个点(a,b,r)
(2)xy空间圆上一个点(x,y)对应参数空间一条曲线
(3)xy空间圆上n个点对应参数空间n条相交于一点的曲线
注:对于原图中每一点,在参数空间确定一条曲线,经过曲线最多的点为原图中圆的参数

  1. 算法步骤:

(1)假设原图像已经处理为二值边缘图像,扫描图中的每一个像素点:
①背景点,不作任何处理
② 目标点,确定曲线:参数空间上的对应曲线上所有点的值累加1
(2)循环扫描所有点
(3)参数空间上累计值为最大的点(a*,b*,r*)为所求圆参数
(4)按照该参数与原图像同等大小的空白图像上绘制圆

  1. 简化运算

三维参数空间,计算量大,可以采样其他形式,如极坐标式,进行进一步简化。

二、主函数

I=rgb2gray(imread('renyan.png'));
BW = edge(I,'sobel'); %目的检测圆的轮廓,如果直接就是圆图像,不用这个
% 用sobel进行边缘检测  
%设置参数:  
%检测的圆半径步长为0.5  
Step_r = 0.5;  %步长过短,运行时间会很长
%角度步长0.1,单位为弧度  
Step_angle = 0.1;   %步长过短,运行时间会很长
%最小圆半径30(圆半径根据实际检测调整)
minr =30;  
%最大圆半径50  
maxr=50;  
%以thresh*hough_space的最大值为阈值,thresh取0-1之间的数  
thresh = 0.8;  
circleParaXYR=[];  
%---------------------------------------------------------------------------------  
%开始检测  
[Hough_space,Hough_circle_result,Para] = Hough_circle(BW,Step_r,Step_angle,minr,maxr,thresh);  
circleParaXYR=Para;  
axis equal  
figure(1);  
imshow(BW,[]),title('边缘');  
axis equal  
figure(2);  
imshow(Hough_circle_result,[]),title('检测结果');  
axis equal  
figure(3),imshow(I,[]),title('检测出图中的圆')  
hold on  
%---------------------------------------------------------------------------------  
%以红色线标记出的检测圆心与圆  
plot(circleParaXYR(:,2), circleParaXYR(:,1), 'r+');  
for k = 1 : size(circleParaXYR, 1)  
    t=0:0.01*pi:2*pi;  
    x=cos(t).*circleParaXYR(k,3)+circleParaXYR(k,2);  
    y=sin(t).*circleParaXYR(k,3)+circleParaXYR(k,1);  
    plot(x,y,'r-');  
end  

三、构造Hough变换检测圆函数(主函数调用即可)

function [Hough_space,Hough_circle_result,Para] = Hough_circle(BW,Step_r,Step_angle,r_min,r_max,p)  
circleParaXYR=[];  
Para=[];  
%得到二值图像大小  
[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;%h(a,b,r)的坐标,圆心和半径  
            end  
        end  
    end  
end  
% 搜索超过阈值的聚集点,对于多个圆的检测,阈值要设的小一点!通过调此值,可以求出所有圆的圆心和半径返回值就是这个矩阵的最大值  
max_para = max(max(max(Hough_space)));  
%一个矩阵中,想找到其中大于max_para*p数的位置  
index = find(Hough_space>=max_para*p);  
length = size(index);%符合阈值的个数  
Hough_circle_result=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)  
            Hough_circle_result(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;    
    circleParaXYR = [circleParaXYR;par1,par2,par3];    
    Hough_circle_result(par1,par2)= 1; %这时得到好多圆心和半径,不同的圆的圆心处聚集好多点,这是因为所给的圆不是标准的圆    
end   
%集中在各个圆的圆心处的点取平均,得到针对每个圆的精确圆心和半径;  
while size(circleParaXYR,1) >= 1  
    num=1;  
    XYR=[];  
    temp1=circleParaXYR(1,1);  
    temp2=circleParaXYR(1,2);  
    temp3=circleParaXYR(1,3);  
    c1=temp1;  
    c2=temp2;  
    c3=temp3;  
    temp3= r_min+(temp3-1)*Step_r;  
    if size(circleParaXYR,1)>1  
        for k=2:size(circleParaXYR,1)  
            if (circleParaXYR(k,1)-temp1)^2+(circleParaXYR(k,2)-temp2)^2 > temp3^2  
                XYR=[XYR;circleParaXYR(k,1),circleParaXYR(k,2),circleParaXYR(k,3)];  %保存剩下圆的圆心和半径位置  
            else  
                c1=c1+circleParaXYR(k,1);  
                c2=c2+circleParaXYR(k,2);  
                c3=c3+circleParaXYR(k,3);  
                num=num+1;  
            end  
        end  
    end  
    c1=round(c1/num);  
    c2=round(c2/num);  
    c3=round(c3/num);  
    c3=r_min+(c3-1)*Step_r;  
    Para=[Para;c1,c2,c3]; %保存各个圆的圆心和半径的值  
    circleParaXYR=XYR;  
end  

四、结果
(1)眼睛的虹膜检测属于较难的检测,主函数加强预处理部分可提高效果;
(2)如果直接用Hough变换检测圆,调用该函数会得到较好效果;
(3)如果是彩色复杂图像,则采用预处理将圆大致提取出来,设置好Hough变换的参数,就可以完成识别。

支持可以关注我哦,持续分享编写的代码。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
xiaoxingxing的头像xiaoxingxing管理团队
上一篇 2022年4月26日
下一篇 2022年4月26日

相关推荐