问题描述:
已有传送带上的二值零件图,将传送带上的工件按有孔和无孔进行分类;
算法:
(1)填充孔洞后得到I1:imfill
(2)I1减去原图,得到以孔洞为目标的图
(3)分别标记原图与孔洞图的连通域:bwlabel
(4)分别测量孔洞连通域的中心以及原图连通域的坐标:regionprops函数
(5)遍历连通域,计算每个连通域坐标的最小值与最大值,判断孔洞的中心点是否在连通域中,若在连通域中,则记录此连通域的flag为1。
(6)显示原图,并且遍历连通域,当flag为1时,表明此连通域是由孔洞的,用绿色的框标出,flag为0时,表明此连通域无孔洞,用红色的框标出。
代码实现:
clear all
I=imread("blocks.png");
subplot(1,3,1)
imshow(I);
title("原图");
%% 孔洞检测
I1=imfill(I,'holes');
img=I1-I;
subplot(1,3,2)
imshow(img);
title("孔洞提取");
[L,num]=bwlabel(I);
[L1,num1]=bwlabel(img);
img_reg = regionprops(L,'area', 'boundingbox');
img_reg1 = regionprops(L1,'Centroid','area', 'boundingbox');
points=cat(1,img_reg1.Centroid); %孔洞的中心点
xq=points(:,1); %孔洞中心点像素的x值
yq=points(:,2); %孔洞中心点像素的y值
rects = round(cat(1,img_reg.BoundingBox)); %连通域的左上角像素点x,y以及长、宽
for i = 1:size(rects, 1) %遍历连通域
area_min=[rects(i,1),rects(i,2)]; %计算连通域左上角的像素点
area_max=[rects(i,1)+rects(i,3),rects(i,2)+rects(i,4)]; %计算连通域右下的像素点
for j = 1:size(xq)
%如果中心点在连通域中,即中心点的x值大于左上角的x值像素点,小于右下角的x值像素点
if (area_min(1)<xq(j) && xq(j)<area_max(1))
if (area_min(2)<yq(j) && yq(j)<area_max(2))
flag(i)=1; %一旦检测连通域中有孔洞,则标记此连通域为有孔,flag为1
break;
end
else
flag(i)=0;
end
end
end
subplot(1,3,3)
imshow(I);
title("有孔与无孔的分类");
for i = 1:size(rects, 1)
if (flag(i)==0) %flag为0时,工件无孔,用红色标出
rectangle('position', rects(i, :), 'EdgeColor', 'r','LineWidth',1);
else %flag为1时,工件有孔,用绿色标出
rectangle('position', rects(i, :), 'EdgeColor', 'g','LineWidth',1);
end
end