机器视觉的作业
基于matlab的一个代码作业,其中借鉴了网络一个人的代码,对它进行了更加符合作业要求的改写。(找不到之前年前写作业的时候的那个文章了,其中有一段我认为写的不太对,运行起来总有问题)
(1)图片预处理:
首先需要将图片进行预处理,使用函数rgb2gray将图片转化为二值图,使所有像素点的值位于0-255(黑到白),显示灰度直方图。直方图描述了该图像中关于颜色的数量特征,可以反映图像颜色的统计分布和基本色调,一般情况下,由于图像上的背景和前景物体颜色分布明显不同,从而在直方图上会出现双峰特性。阈值分割的基本思想是确定一个阈值,然后把每个像素点的灰度值和阈值相比较,根据比较的结果把该像素划分为两类——前景或背景。图像阈值化分割是一种传统的最常用的图像分割方法,因其实现简单、计算量小、性能较稳定而成为图像分割中最基本和应用最广泛的分割技术。它特别适用于目标和背景占据不同灰度级范围的图像。通过阈值分割达到去除背景的目的,流程图:
(2)找出胶囊位置 :
将图片进行预处理后,胶囊区域分割为不同的连通域。判断连通域个数来判断胶囊的粒数,通过与正确粒数对比,判断胶囊是否缺失。由于蓝白胶囊的白色区域与药板底色一样,无法判断白色部分大小及位置,蓝色胶囊仅判断蓝色区域。然后对连通域进行框选,确定胶囊具体位置,且标出质心位置,以便后续对胶囊种类的判断。
3.判断胶囊种类
判别胶囊种类目前可以通过连通域大小、颜色识别的方法。在MATLAB中一幅RGB图像可表示为一个MN3的三维矩阵。其中每一个彩色像素都在特定空间位置的彩色图像中对应红、绿、蓝3个分量。分量图像的数据类型决定了他们的取值范围。若一幅RGB图像的数据类型是uint8,则每个分量图像的取值范围是[0,255]。颜色识别方法为,读取该矩阵点的B分量,将上一步得到的质心坐标取出,判断质心附近的像素,通过筛选蓝色像素的方法,判断蓝色胶囊的个数。
二:具体流程
(1)读取待处理彩色药板图像,获取目标图像。
(2)图像预处理,原始彩色图像转化为灰度图。
(3)通过阈值分割,去除背景。
(4)再次根据阈值,判断出黄颜色区域。
(5)对图片进行取反,,利用闭循环先膨胀后腐蚀,将胶囊边缘处理的平滑整齐。
(6)将药板填充,确定药板边缘。
(7)通过三角形定理,确定边缘倾斜角度,将图片进行旋转。
(8)由于处理后噪点过多,再次进行闭运算,去除小的噪点。
(9)划分连通域,将每个连通域用最小矩阵框出,并标出矩阵质心。
(10)用颜色识别确定胶囊种类。
(11)计算各类胶囊个数,输出结果至图片下方以及命令执行窗口。
以下为代码,图片是网络随便找的,代码中有些数据仅针对该图片管用,如果换一个图,可能降噪不理想,提取出各种大大小小的区域。
clc; close all;clear all; %清除之前所有信息
%%
%图片初步处理
I=imread('089.png'); %打开图片
a=rgb2gray(I); %进行灰度处理
figure %第一张图
imshow(I); title('原图'); %显示原图
figure %第二张图
imshow(a); title('灰度图'); %显示灰度处理后的图片
%%
%将背景去掉
x=size(a,1); %把a的行赋值给x
y=size(a,2); %把a的列赋值给y
g=zeros(x,y); %建立一个空矩阵g,行数是x,列数是y
for i=1:1:x %for循环,a矩阵中背景颜色小于120的点变成0(白到黑 0-255)
for j=1:1:y
if(a(i,j)<120)
g(i,j)=0 ;
else
g(i,j)=255;
end
end
end
%%
figure
imshow(g);
title('过滤背景');
I=imread('089.png');
[m,n,d]=size(I); %提取黄色区域
for i=1:m
for j=1:n
if(I(i,j,1)>150 && I(i,j,1)<256)&&(I(i,j,2)>150 && I(i,j,2)<255)&&(I(i,j,3)>0 && I(i,j,3)<100); %找出黄色像素
g(i,j)=0;
end
end
end
figure,imshow(g);
title('去除彩色区域');
%%
%图片闭运算处理胶囊位置
fa=1-g; %取反
se=strel('square',5); %将胶囊的边缘平滑整齐
closeg=imclose(fa,se); %填充图片,闭运算先膨胀后腐蚀
closeg=1-closeg;
figure,
imshow(closeg);
title('闭运算后')
%药板边缘确定
fillg=zeros(x,y); %又建立了一个空矩阵
fillg=imfill(g,'holes'); %填充了图片
BW=edge(fillg,'roberts'); %边缘提取
figure,
imshow(BW);
title('药板边缘确定');
%将胶囊的边缘平滑整齐
%%
tiqu1=(y-1)/2-150;
tiqu2=(y-1)/2+150;
cishu1=1;
cishu2=1;
x1=0;
x2=0;
for i=1:1:x
if cishu1==1
if g(i,tiqu1)==255
x1=i;
cishu1=0;
end
end
end
for i=1:1:x
if cishu2==1
if g(i,tiqu2)==255
x2=i;
cishu2=0;
end
end
end
theta=atan(abs(x1-x2)/abs(tiqu2-tiqu1))*180/pi; %算出旋转度数
%%
S = imrotate(BW,-theta);
A= imrotate(closeg,-theta);
B= imrotate(fillg,-theta);
I= imrotate(I,-theta);
BW=imrotate(BW,-theta);
C=B-A;
figure
imshow(C);
title('提取胶囊轮廓');
%%
%由于处理过后噪点太多,取反闭运算,再取反
C=1-C;
se=strel('square',5);
closeg=imclose(C,se);
closeg=1-closeg; %再次闭运算,先膨胀
figure,
imshow(closeg);
title('边缘检测后再次闭运算')
C=closeg;
%%
%标签定位
fill_write=B;
figure
imshow(B);title('确定药板位置');
start1=0;
start2=0;
sta_x1=0;
sta_x2=0;
sta_y=0;
for i=1:1:y
if(start1==1)
if(BW(i,y/2)==1)
sta_y=i;
start1=1;
end
end
end
for i=1:1:x
if(start2==1)
if(BW(i,x/2)==1)
sta_x1=i;
start2=1;
i=i+20;
end
end
if(start2==1)
if(BW(i,x/2)==1)
sta_x2=i;
start2=2;
i=i+20;
end
end
end
sta_x=sta_x2-sta_x1;
for j=(sta_y+round(sta_x/3)):1:y
for i=1:1:x
%fill_write(i,j)=0;
end
end
img = regionprops(fill_write,'boundingbox');
locate = cat(1,img.BoundingBox);
%%
T = graythresh(C); %找到合适阈值
bw_img = im2bw(C, T); %图片进行二值化处理
img_reg = regionprops(bw_img,'area', 'boundingbox','Centroid'); %regionprops,分割连通域,求出质心
areas = [img_reg.Area];
rects = cat(1,img_reg.BoundingBox);
zhixin = cat(1,img_reg.Centroid);
figure;
imshow(I); title('识别结果')
%%
for i = 1:size(rects, 1) %size查询矩阵维数
rectangle('position', rects(i, :), 'EdgeColor', 'r');%rectangle绘制矩形
hold on
plot(zhixin(i,1),zhixin(i,2),'ob'); %在中心处画出空心圆
hold on
end
for i = 1:size(locate, 1) %圈出药板位置
rectangle('position', locate(i, :), 'EdgeColor', 'r');
hold on
end
%%
%确定药丸颜色
gre=0; %绿色药丸个数
blu=0; %蓝色药丸个数
zhixin1=ceil(zhixin); %质心坐标取整
[q,~]=size(zhixin); %判断质心点上下20个像素是否为绿色或蓝色
for i=1:q
xx=zhixin1(i,1);
yy=zhixin1(i,2);
if I(yy,xx,3)>130||I(yy+20,xx,3)>130||I(yy-20,xx,3)>130
blu=blu+1;
else
gre=gre+1;
end
end
%正确药板数为:12
right=12;
quie=right-q;
if quie==0
text(150,380,'药板无药粒缺失');
else
text(150,380,'药板缺失药粒,缺失个数为:');
text(360,380,num2str(quie));
end
text(150,400,'绿色胶囊个数为:')
text(300,400,num2str(gre));
text(150,420,'蓝色胶囊个数为:')
text(300,420,num2str(blu));
%%
qts={'缺失个数为:'};
qs=num2str(quie);
gts={'绿色胶囊个数为:'};
as=num2str(gre);
bts={'蓝色胶囊个数为:'};
bs=num2str(blu);
gts=[qts qs;gts as;bts bs];
gts