药板缺陷检测
本文原创,如有引用请标记来源
一、药板图片
第一类
正常的药板
有缺陷的药板
第二类
正常的药板
有缺陷的药板
鉴于药板的复杂程序来说,我们以第二类为栗子,讲解具体的识别过程
先上代码
clear all
clc
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Liuz JN university
% 2021-12-21/0:13
% Version__6.1
% 如有参考,请适当修改
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 1. 读取图片
a=imread('D:\OldLaptop\图像\Final project\images of project\set 2\bl-130-28.tiff');
% 灰度化 对下面有用,
a2=rgb2gray(a);
% figure(1)
% imshow(a);
% figure(2)
% imshow(a2)
%% 修正
level=graythresh(a); %使用最大类间方差法找到图片的一个合适的阈值
bw=im2bw(a,level); %根据阈值,使用im2bw函数将灰度图像转换为二值图像时
% figure(10);imshow(bw);
[m,n]=size(bw); %获取尺寸
pMax=round(sqrt(m^2+n^2)); %计算最大p
thetaMax=180; %设定最大角度
countMatrix=zeros(pMax,thetaMax); %关于p和角度的计数矩阵
tic;
for i=1:m
for j=1:n
if bw(i,j)==0
for theta=1:thetaMax %对theta作循环
p=floor( abs( i*cos(3.14*theta/180) + j*sin(3.14*theta/180) ) ); %在theta循环过程中计算图像矩阵中一个像素点对应的p值
countMatrix(p+1,theta)=countMatrix(p+1,theta)+1; %像素点对应的计数矩阵中(p+1,theta)处计数
end
end
end
end
[m,n]=size(countMatrix);
for i=1:m
for j=1:n
if countMatrix(i,j)>countMatrix(1,1)
countMatrix(1,1)=countMatrix(i,j); %获取最多曲线的相交点
angle=j; %获取相交点处对应的角度
end
end
end
if angle<=90
rot=angle;
else
rot=180-angle;
end
if rot>3
pic=a;
else
pic=imrotate(a,-rot,'crop');
end
% pic= %旋转图像
figure(11)
imshow(pic)
%% 去背景
a1 = pic;
b = im2bw(a1,0.5);
se1 = strel('disk',5);
b0=imopen(b,se1);
% figure(3)
% imshow(b0)
[x0,y0]=find(b0==1);% 药板的边界获取
xmin=min(x0(:)); %获得最左边的,最右边,最上边,最下边的像素点,简而言之就是这个药板剪出来
xmax=max(x0(:));
ymin=min(y0(:));
ymax=max(y0(:));
b1=im2bw(a1,0.4); %类似于上面,选用的阈值为0.6
% figure(4)
% imshow(b1)
c0=[xmin,xmax,xmax,xmin]; %将上面的获得的边界进行赋值给c0,c1.
c1=[ymin,ymin,ymax,ymax];
b2=roipoly(b1,c1,c0); %roipoly函数选择感兴趣的多边形区域 也就是一把大剪刀,从b1剪下来感兴趣的区域,区域内全是1剪下来但是没有改变维度
b4=b1|~b2;
%去除边界的黑框,上次b4遗留下来的,这样就全部 这里的数字是需要调节的
b4(xmin:xmax,ymin:ymin+40)=1; %左边框
b4(xmin:xmin+15,ymin:ymax)=1; %上边框
b4(xmax-35:xmax,ymin:ymax)=1; %下边框
b4(xmin:xmax,ymax-10:ymax)=1; %右边框
% figure(5)
% imshow(b4)
%% 边缘获取,确定胶囊点位置
se3=strel('disk',4);
b5=imerode(b4,se3); %进行腐蚀 用点进行的 因为这里有洞
b6=edge(b5,'sobel'); %自动选择阈值用Sobel算子进行边缘检测 ,简而言之就是获得边缘
% figure(7)
% imshow(b6)
[x1,y1]=find(b6==1); %获取边缘的边界坐标 这个点有问题 找的左上角的点
x1min=min(x1(:)); %获取最小行
y1min=min(y1(:)); %获取最小列
x2=zeros(10,1);%x2,y2生成两个10维度向量。10个药丸
y2=zeros(10,1);
for i=1:10 %每个药丸的初始坐标 x170,y90
if(rem(i,5)~=0)
y2(i,1)=y1min+86*(rem(i,5)-1); %求余数
else
y2(i,1)=y1min+88*4;
end
x2(i,1)=x1min+158*(ceil(i/5)-1);
end
%% 计算点数作为评判标准
rc=1-b5;%计算的点数
% rectangle('Position',[y2(10,1),x2(10,1),50,123],'Linewidth',2,'Edgecolor','g')%46,123
% %找到了初始点 并将初始点对应的药物框出来
% hold off;
figure(6)
imshow(rc)
% r = sum(sum(rc(x2(4,1):x2(4,1)+123,y2(4,1):y2(4,1)+46)));
% 定义r为像素点为1的个数,判断是否有问题胶囊
r=ones(10,1);
flag=ones(10,1);%定义标志位,判断颜色使用
% 计算像素点
for i=1:1:10
r(i,1) = sum(sum(rc(x2(i,1):x2(i,1)+133,y2(i,1)-10:y2(i,1)+60))); %适当调节那个数点的框框
end
%% 判断像素点是否满足条件,打印输出
for i=1:1:10
if r(i)>2340&&r(i)<3200
flag(i)=1;
else
flag(i)=0;
end
end
figure(8)
imshow(a1)
hold on;
for i=1:1:10
if flag(i)==1
rectangle('Position',[y2(i,1),x2(i,1),50,123],'Linewidth',2,'Edgecolor','g')
else
rectangle('Position',[y2(i,1),x2(i,1),50,123],'Linewidth',2,'Edgecolor','r')
end
end
%%
实验结果
总结
这里面的一些参数我们需要根据具体的进行调节,当然程序也有很多不足,希望大家能够改进!