matlab 霍夫变换——检测圆弧

类似的代码网上一搜全都是,不少代码运行起来各种错误,真正正确的还是要靠自己慢慢尝试和修改。以下是本人亲测,绝对正确可行的代码。

首先需要新建两个脚本,功能分别是图像的前期处理和检测圆弧,话不多说,代码实现如下:

function [bw] = image_deal(bw)
 
%UNTITLED2 Summary of this function goes here
%   Detailed explanation goes here
%------------------------------输入参数-----------------------------  
% BW:处理前图像;  
%-------------------------------------------------------------------  
  
%------------------------------输出参数-----------------------------  
% BW:二值后图像;  
%-------------------------------------------------------------------  
  
% From Nanjing University of Science and Technology,ZLy 
%%建立sobel算子
sobel_xl=[-1,0,1;-2,0,2;-1,0,1];
sobel_xr=[1,0,-1;2,0,-2;1,0,-1];
sobel_yl=[1,2,1;0,0,0;-1,-2,-1];
sobel_yr=[-1,-2,-1;0,0,0;1,2,1];
%%图像灰度化
bw=rgb2gray(bw);
%%把图像数据类型转换为双精度浮点类型
bw=im2double(bw);
%%图像与sobel算子进行卷积
A=conv2(bw,sobel_xl);
B=conv2(bw,sobel_xr);
C=conv2(bw,sobel_yl);
D=conv2(bw,sobel_yr);
%%图像二值化
A=im2bw(A,graythresh(A));
B=im2bw(B,graythresh(B));
C=im2bw(C,graythresh(C));
D=im2bw(D,graythresh(D));
%%图像相加
bw=A+B+C+D;
imshow(bw);title('卷积后的图像');
%消除噪点
se=strel('disk',2);
bw=imclose(bw,se);
figure;imshow(bw);title('消除噪点后的图像');
end

 

function [hough_space,hough_circle,para] = hough_circle(BW,step_r,step_angle,r_min,r_max,p,AW) 
%[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之间的数  
% AW:原始图像;
%-------------------------------------------------------------------  
  
%------------------------------输出参数-----------------------------  
% hough_space:参数空间,h(a,b,r)表示圆心在(a,b)半径为r的圆上的点数  
% hough_circl:二值图像,检测到的圆  
% 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); %返回BW中非零元素的一个列或行向量v,同时返回行和列的索引值。
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)));  %求出hough_space的最大值,三个方向上a,b,r
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  
% 打印结果  
fprintf('圆的个数 %d\n',length);
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]';
    %%找出对应参数,圆中心加蓝
    AW(par1,par2,1)=0;
    AW(par1,par2,2)=232; 
    AW(par1,par2,3)=232; 
    %%圆周加红
    for angle=0:0.005:2*pi
        x = round(par1+par3*cos(angle));
        y = round(par2+par3*sin(angle));
        if(x>0&y>0)
           AW(x,y,1)=232;
           AW(x,y,2)=0;            
           AW(x,y,3)=0;
        end   
    end
end 
%输出识别后图像
imshow(AW);title('圆心加蓝,圆周加红');

在命令窗口输入:

>> bw=imread('p.jpg');
>> aw=bw;
>> bw=image_deal(bw);
>> f=hough_circle(bw,10,0.03,100,150,0.5,aw);

原图:

matlab 霍夫变换——检测圆弧

检测结果:

matlab 霍夫变换——检测圆弧