matlab判断图像是否为标准圆形

来源:互联网 发布:高中数学必修三算法 编辑:程序博客网 时间:2024/05/21 21:01

本例中判断一个图像是否为标准的原型有如下步骤:
1.读取图片
2.去除图片噪声
3.寻找边界
4.判断提取出来的边界是否是一个圆
下面是具体步骤:

1.读取图片

其中要将图片转化为二值图像,使用的最新的方法时候imbinarize,如果用不了的话也可以先使用graythresh方法选择阈值,再通过im2bw转为二值图像。

clc,clear%% 1.读取图片rgb=imread('pillsetc.png');I=rgb2gray(rgb);%转化为二值图片%bw=imbinarize(I);threshold =graythresh(I);%取阈值bw=im2bw(I,threshold);

2.去除图片噪声

使用imfill函数填充图像

%% 2.去除噪声bw = bwareaopen(bw,30);se = strel('disk',2);bw = imclose(bw,se);bw = imfill(bw,'holes');%填充subplot(1,3,1),imshow(rgb),title('原图')subplot(1,3,2),imshow(I),title('灰度图')subplot(1,3,3),imshow(bw),title('处理后的二值图像')

这里写图片描述

3.寻找边界

[B,L] = bwboundaries(bw,···)函数拿到连通分量

  • B是连通分量,L是标记矩阵,B内每一行是一个 Q x 2 的矩阵, Q内每一行表示连通体的边界像素的位置坐标(第一列是纵坐标Y,第二列是横坐标X),Q为边界像素的个数.
  • L是一个标记矩阵.
for k = 1:length(B)  boundary = B{k};%第k个连通分量  plot(boundary(:,2), boundary(:,1), 'w', 'LineWidth', 2)%第一列是纵坐标Y,第二列是横坐标Xend

利用上述循环来为每一个连通分量圈出一个圆圈。
下面是这部分的完整代码:

%% 3.找边界%B是一个 P x 1 的数组,其中P代表连通体的个数.B内每一行是一个 Q x 2 的矩阵,%Q内每一行表示连通体的边界像素的位置坐标(第一列是纵坐标Y,第二列是横坐标X),Q为边界像素的个数.%L是一个标记矩阵.[B,L] = bwboundaries(bw,'noholes');figuresubplot(1,2,1),imshow(label2rgb(L, @jet, [.5 .5 .5])),title('填充颜色')subplot(1,2,2),imshow(label2rgb(L, @jet, [.5 .5 .5])),title('增加白色边界')hold onfor k = 1:length(B)  boundary = B{k};%第k个连通分量  plot(boundary(:,2), boundary(:,1), 'w', 'LineWidth', 2)%第一列是纵坐标Y,第二列是横坐标Xendhold off

这里写图片描述

4.判断提取出来的边界是否是一个圆

利用metric = 4*pi*area/perimeter^2公式. 如果得到的metric是1则说明是一个圆,小于1说明不太圆。
regionprops函数度量图像区域属性:

  • ‘Area’:是标量,计算出在图像各个区域中像素总个数。
  • ‘Centroid’:是1行ndims(L)列的向量,给出每个区域的质心(重心)
4.判断提取出来的边界是否是一个圆%metric = 4*pi*area/perimeter^2. 如果得到的metric是1则说明是一个圆,小于1说明不太圆stats = regionprops(L,'Area','Centroid');%用来度量图像区域属性,'Centroid':是1行ndims(L)列的向量,给出每个区域的质心(重心)threshold = 0.94;figureimshow(label2rgb(L, @jet, [.5 .5 .5])),title('增加白色边界')hold onfor k = 1:length(B)  boundary = B{k};%第k个连通分量  plot(boundary(:,2), boundary(:,1), 'w', 'LineWidth', 2)%第一列是纵坐标Y,第二列是横坐标Xend% loop over the boundaries for k = 1:length(B) %遍历每一个连通分量  % obtain (X,Y) boundary coordinates corresponding to label 'k'  boundary = B{k};  % compute a simple estimate of the object's perimeter  delta_sq = diff(boundary).^2;      perimeter = sum(sqrt(sum(delta_sq,2)));  % obtain the area calculation corresponding to label 'k'  area = stats(k).Area;  % compute the roundness metric  metric = 4*pi*area/perimeter^2;  % display the results  metric_string = sprintf('%2.2f',metric);  % mark objects above the threshold with a black circle  if metric > threshold    centroid = stats(k).Centroid;    plot(centroid(1),centroid(2),'ko'); %如果哪个连通分量的判断结果大于0.94,则在中心标记o  end  text(boundary(1,2)-35,boundary(1,1)+13,metric_string,'Color','y',...       'FontSize',14,'FontWeight','bold');endtitle('值越接近1说明越接近圆');hold off

下面是最终结果,程序设置,如果使用公式metric = 4*pi*area/perimeter^2得到的结果大于0.94这说明差不多符合一个标准圆
这里写图片描述