matlab 霍夫变换—检测圆

 
  1.   
  2. function [hough_space,hough_circle,para] = hough_circle(BW,step_r,step_angle,r_min,r_max,p)  
  3.   
  4. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
  5. % input  
  6. % BW:二值图像;  
  7. % step_r:检测的圆半径步长  
  8. % step_angle:角度步长,单位为弧度  
  9. % r_min:最小圆半径  
  10. % r_max:最大圆半径  
  11. % p:阈值,0,1之间的数 通过调此值可以得到图中圆的圆心和半径  
  12. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
  13. % output  
  14. % hough_space:参数空间,h(a,b,r)表示圆心在(a,b)半径为r的圆上的点数  
  15. % hough_circl:二值图像,检测到的圆  
  16. % para:检测到的圆的圆心、半径  
  17.   
  18. circleParaXYR=[];  
  19. para=[];  
  20.   
  21. [m,n] = size(BW);  
  22. size_r = round((r_max-r_min)/step_r)+1;%四舍五入  
  23. size_angle = round(2*pi/step_angle);  
  24.   
  25. hough_space = zeros(m,n,size_r);  
  26.   
  27. [rows,cols] = find(BW);%查找非零元素的行列坐标  
  28. ecount = size(rows);%非零坐标的个数  
  29.   
  30. % Hough变换  
  31. % 将图像空间(x,y)对应到参数空间(a,b,r)  
  32.   
  33. a = x-r*cos(angle)  
  34. b = y-r*sin(angle)  
  35.   
  36. for i=1:ecount  
  37.     for r=1:size_r %半径步长数  
  38.         for k=1:size_angle %按一定弧度把圆几等分  
  39.             a = round(rows(i)-(r_min+(r-1)*step_r)*cos(k*step_angle));  
  40.             b = round(cols(i)-(r_min+(r-1)*step_r)*sin(k*step_angle));  
  41.             if(a>0&a<=m&b>0&b<=n)  
  42.             hough_space(a,b,r) = hough_space(a,b,r)+1;%h(a,b,r)的坐标,圆心和半径  
  43.             end  
  44.         end  
  45.     end  
  46. end  
  47.   
  48.   
  49. % 搜索超过阈值的聚集点。对于多个圆的检测,阈值要设的小一点!通过调此值,可以求出所有圆的圆心和半径  
  50. max_para = max(max(max(hough_space)));%返回值就是这个矩阵的最大值  
  51. index = find(hough_space>=max_para*p);%一个矩阵中,想找到其中大于max_para*p数的位置  
  52. length = size(index);%符合阈值的个数  
  53. hough_circle = false(m,n);  
  54. %hough_circle = zeros(m,n);  
  55. %通过位置求半径和圆心。  
  56. for i=1:ecount  
  57.     for k=1:length  
  58.         par3 = floor(index(k)/(m*n))+1;  
  59.         par2 = floor((index(k)-(par3-1)*(m*n))/m)+1;  
  60.         par1 = index(k)-(par3-1)*(m*n)-(par2-1)*m;  
  61.         if((rows(i)-par1)^2+(cols(i)-par2)^2<(r_min+(par3-1)*step_r)^2+5&...  
  62.                 (rows(i)-par1)^2+(cols(i)-par2)^2>(r_min+(par3-1)*step_r)^2-5)  
  63.               hough_circle(rows(i),cols(i)) = true;   %检测的圆  
  64.         end  
  65.     end  
  66. end                 
  67.   
  68. % 从超过峰值阈值中得到  
  69. for k=1:length  
  70.     par3 = floor(index(k)/(m*n))+1;%取整  
  71.     par2 = floor((index(k)-(par3-1)*(m*n))/m)+1;  
  72.     par1 = index(k)-(par3-1)*(m*n)-(par2-1)*m;  
  73.     circleParaXYR = [circleParaXYR;par1,par2,par3];  
  74.     hough_circle(par1,par2)= true; %这时得到好多圆心和半径,不同的圆的圆心处聚集好多点,这是因为所给的圆不是标准的圆  
  75.     %fprintf(1,'test1:Center %d %d \n',par1,par2);  
  76. end  
  77.   
  78. %集中在各个圆的圆心处的点取平均,得到针对每个圆的精确圆心和半径!  
  79. while size(circleParaXYR,1) >= 1  
  80.     num=1;  
  81.     XYR=[];  
  82.     temp1=circleParaXYR(1,1);  
  83.     temp2=circleParaXYR(1,2);  
  84.     temp3=circleParaXYR(1,3);  
  85.     c1=temp1;  
  86.     c2=temp2;  
  87.     c3=temp3;  
  88.     temp3r_min+(temp3-1)*step_r;  
  89.    if size(circleParaXYR,1)>1       
  90.      for k=2:size(circleParaXYR,1)  
  91.       if (circleParaXYR(k,1)-temp1)^2+(circleParaXYR(k,2)-temp2)^2 > temp3^2  
  92.          XYR=[XYR;circleParaXYR(k,1),circleParaXYR(k,2),circleParaXYR(k,3)];  %保存剩下圆的圆心和半径位置  
  93.       else    
  94.       c1=c1+circleParaXYR(k,1);  
  95.       c2=c2+circleParaXYR(k,2);  
  96.       c3=c3+circleParaXYR(k,3);  
  97.       num=num+1;  
  98.       end   
  99.     end  
  100.    end   
  101.       %fprintf(1,'sum %d %d radius %d\n',c1,c2,r_min+(c3-1)*step_r);  
  102.       c1=round(c1/num);  
  103.       c2=round(c2/num);  
  104.       c3=round(c3/num);  
  105.       c3=r_min+(c3-1)*step_r;  
  106.       %fprintf(1,'num=%d\n',num)  
  107.       %fprintf(1,'Center %d %d radius %d\n',c1,c2,c3);     
  108.       para=[para;c1,c2,c3]; %保存各个圆的圆心和半径的值  
  109.       circleParaXYR=XYR;  
  110. end  

[html]  view plain  copy
 print ?
  1. 文件2 main.m  
  2. clc,clear all  
  3. circleParaXYR=[];  
  4. I = imread('h6.jpg');  
  5. [m,n,l] = size(I);  
  6. if l>1  
  7.     I = rgb2gray(I);  
  8. end  
  9. BW = edge(I,'sobel');  
  10.   
  11. step_r = 1;  
  12. step_angle = 0.1;  
  13. minr = 3  
  14. maxr = 30;  
  15. thresh = 0.51;  
  16.   
  17. [hough_space,hough_circle,para] = hough_circlefu(BW,step_r,step_angle,minr,maxr,thresh);  
  18. figure(1),imshow(I),title('原图')  
  19. figure(2),imshow(BW),title('边缘')  
  20. figure(3),imshow(hough_circle),title('检测结果')  
  21.   
  22. circleParaXYR=para;  
  23.   
  24. %输出  
  25. fprintf(1,'\n---------------圆统计----------------\n');  
  26. [r,c]=size(circleParaXYR);%r=size(circleParaXYR,1);  
  27. fprintf(1,'  检测出%d个圆\n',r);%圆的个数  
  28. fprintf(1,'  圆心     半径\n');%圆的个数  
  29. for n=1:r  
  30. fprintf(1,'%d (%d,%d)  %d\n',n,floor(circleParaXYR(n,1)),floor(circleParaXYR(n,2)),floor(circleParaXYR(n,3)));  
  31. end  
  32.   
  33. %标出圆  
  34. figure(4),imshow(I),title('检测出图中的圆')  
  35. hold on;  
  36.  plot(circleParaXYR(:,2), circleParaXYR(:,1), 'r+');  
  37.  for k = 1 : size(circleParaXYR, 1)  
  38.   t=0:0.01*pi:2*pi;  
  39.   x=cos(t).*circleParaXYR(k,3)+circleParaXYR(k,2);y=sin(t).*circleParaXYR(k,3)+circleParaXYR(k,1);  
  40.   plot(x,y,'r-');  
  41.  end  
  42.    
  43.   
  44. R_max=maxr;  
  45. acu=zeros(R_max);  
  46. stor =[];  
  47. for j=1:R_max  
  48.   for n=1:r  
  49.    if  j == floor(circleParaXYR(n,3))  
  50.        acu(j)= acu(j)+1;  
  51.    end  
  52.   end  
  53.    stor=[stor;j,acu(j)];  
  54.    %fprintf(1,'%d,%d\n',j,acu(j));  
  55. end  
  56.   
  57. fprintf(1,'\n------------粒子大小,数目统计---------\n');  
  58. fprintf(1,'粒子半径,粒子个数\n');  
  59. for j=1:R_max  
  60.   if acu(j) > 0  
  61.    fprintf(1,'%4d %8d\n',stor(j,1),stor(j,2));  
  62.   end  
  63. end  
  64.   
  65. fprintf(1,'----------------------------------------\n');  
  66. figure(5),plot(stor(:,1),stor(:,2),'-k','LineWidth',2),title('粒径谱');  
  67. xlabel('粒子大小');  
  68. ylabel('粒子个数');  
  69. grid on;  
  70.   
  71. z=[0,10,20,30,40,50,60,70,80,90,11,35,25,42,48,40,20,75,88,94,23,10,20,30,40,78,60,76,84,95,58,10,20,30,40,50,60,70,80,90,100];%给出z的坐标  
  72. Z=z(:);  
  73. S=floor(abs(Z)*1);  
  74. C=floor(abs(Z)*0.5);  
  75. figure(6),scatter3(circleParaXYR(:,1),circleParaXYR(:,2),Z,circleParaXYR(:,3)*7,'filled'),title('构建三维粒子场');  

 

 

注:对网上的代码做了改动,使它更能精准检测每个圆的圆心和半径

 2012-5-31


你可能感兴趣的:(图像处理,MATLAB)