正文之前
没错,我回来了。十天没有更新了,感觉自己都不像自己了!今天开始狂更???可以的!!
正文
本次文章,没有太多好写的,就是最近做的一个机器视觉的课程设计作业,是要做一个流水线的生产线建模以及对于产品的检测识别,我个人承包了圆心半径检测的内容,熬了好几天,终于找到了一个好的算法可以比较迅速准确的找到圆了。天不负我!!
这是我要检测图片,因为我们的要求是检测大小接近的图,所以我把检测半径范围规定在很小的范围内,这样的话会极大地加快速度!!所以这才是致胜的关键!!
%%%%%%%%%% main.m %%%%%%%%%%%
% 文件2 main.m
clc;
clear;
circleParaXYR=[];
I = imread('/Users/zhangzhaobo/program/MATLAB/Machine_vision/Picture/9.bmp');
%取整张图的三维尺寸
[m,n,l] = size(I);
% 通过判断对象类型来决定是否转化为灰度图
if l>1
I = rgb2gray(I);
end
%采用sobel算子来进行边缘检测
BW = edge(I,'sobel');
[m,n]=size(BW);
% 步长为1,即每次检测的时候增加的半径长度
step_r = 1;
%检测的时候每次转过的角度
step_angle = 0.1;
% 对检测的圆的大小范围预估,在实际项目中因为产品大小固定,所以可以给定较小范围,提高运行速度
minr = 508;
maxr = 510;
% 自动取最优的灰度阈值
thresh = graythresh(I);
% 调用hough_circle函数进行霍夫变换检测圆
[hough_space,hough_circle,para] = hough_circle(BW,step_r,step_angle,minr,maxr,thresh);
figure(1),imshow(I),title('原图')
figure(2),imshow(BW),title('边缘')
figure(3),imshow(hough_circle),title('检测结果')
circleParaXYR=para;
%输出
fprintf(1,'\n---------------圆统计----------------\n');
[r,c]=size(circleParaXYR); % r=size(circleParaXYR,1);
fprintf(1,' 检测出%d个圆\n',r); % 圆的个数
fprintf(1,' 圆心 半径\n'); % 圆的个数
for n=1:r
% x0=floor(circleParaXYR(n,1));
% y0=floor(circleParaXYR(n,2));
% if x0>0.25*m && x0<0.75*m && y0>0.25*n && y0<0.75*n
fprintf(1,'%d (%d,%d) %d\n',n,floor(circleParaXYR(n,1)),floor(circleParaXYR(n,2)),floor(circleParaXYR(n,3)));
% end
end
%标出圆
figure(4),imshow(I),title('检测出图中的圆')
%figure(1),imshow(I),title('检测出图中的圆')
hold on;
plot(circleParaXYR(:,2), circleParaXYR(:,1), 'r+');
for k = 1 : r %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
% R_max=maxr;
% acu=zeros(R_max);
% stor =[];
% for j=1:R_max
% for n=1:r
% if j == floor(circleParaXYR(n,3))
% acu(j)= acu(j)+1;
% end
% end
% stor=[stor;j,acu(j)];
% %fprintf(1,'%d,%d\n',j,acu(j));
% end
% fprintf(1,'\n------------粒子大小,数目统计---------\n');
% fprintf(1,'粒子半径,粒子个数\n');
% for j=1:R_max
% if acu(j) > 0
% fprintf(1,'%4d %8d\n',stor(j,1),stor(j,2));
% end
% end
% fprintf(1,'----------------------------------------\n');
% figure(5),plot(stor(:,1),stor(:,2),'-k','LineWidth',2),title('粒径谱');
% xlabel('粒子大小');
% ylabel('粒子个数');
% grid on;
% 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的坐标
% Z=z(:);
% S=floor(abs(Z)*1);
% C=floor(abs(Z)*0.5);
% figure(6),scatter3(circleParaXYR(:,1),circleParaXYR(:,2),Z,circleParaXYR(:,3)*7,'filled'),title('构建三维粒子场');
上面是👆main函数,也就是最终的直接调用的函数,下面是hough_circle的m函数,在main中要调用这个函数的!
%%%%%%%%%% hough_circle.m %%%%%%%%%%%
% 文件1---hough_circle.m
function [hough_space,hough_circle,para] = hough_circle(BW,step_r,step_angle,r_min,r_max,p)
% *****************************************************
% 参数输入
% BW:二值图像;
% step_r:检测的圆半径步长
% step_angle:角度步长,单位为弧度
% r_min:最小圆半径
% r_max:最大圆半径
% p:阈值,0,1之间的数 通过调此值可以得到图中圆的圆心和半径
% *****************************************************
% 参数返回
% hough_space:参数空间,h(a,b,r)表示圆心在(a,b)半径为r的圆上的点数
% hough_circl:二值图像,检测到的圆
% para:检测到的圆的圆心、半径
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,