//作品概述:
本代码主要功能是实现金属表面三种缺陷的检测、分类及测量,并使用GUI进行封装以便于用户使用。
该GUI可以导入电脑中的灰度图片,之后进行处理,能确定缺陷的种类,将检测到的缺陷标注在原图上,
并能够测量不同缺陷的大小(不同缺陷衡量标准不同)。
------------------------------------------------------------------------------------------
//重要函数简介:
#pushbutton1_Callback(hObject, eventdata,handles):
按键1(即'图像处理'按键)的回调函数,包含全部图像处理算法
#pushbutton2_Callback(hObject, eventdata,handles):
按键2(即'图片导入'按键)的回调函数,主要是图片的导入
#Ga(theta,num):图像的Garbor卷积核的初始化
#filterimage(a6,Gaborfiter):Garbor滤波算法
#thres(image):灰度图的最大熵阈值分割算法
#location():'轧入氧化皮'缺陷的定位及显示
#houghtran():对于'划痕'缺陷的霍夫圆检测
#lbp(varargin):网上的'局部二值模式'特征提取算法
#svm.m:独立m文件,用于所有金属缺陷照片的LBP特征提取和SVM(支持向量机)监督学习算法的训练与测试
--------------------------------------------------------------------------------------------
%}
%%
function varargout = app(varargin)
%GUI页面主函数,MATLAB提供,无需修改
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @app_OpeningFcn, ...
'gui_OutputFcn', @app_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
%%
function app_OpeningFcn(hObject, eventdata, handles, varargin)
% GUI初始化函数
%修改设置背景
%modified by:Faust.Cao
ha=axes('units','normalized','pos',[0 0 1 1]);
uistack(ha,'down');
%设置程序的背景图为back.jpg
ii=imread('C:\Users\lenovo\Desktop\金属表面缺陷分类与测量GUI系统\金属表面缺陷分类与测量系统\back.jpg');
image(ii);
colormap gray
set(ha,'handlevisibility','off','visible','off');
handles.output = hObject;
guidata(hObject, handles);
%%
function varargout = app_OutputFcn(hObject, eventdata, handles)
% GUI输出函数,MATLAB提供,无需修改
varargout{1} = handles.output;
%%
function pushbutton1_Callback(hObject, eventdata, handles)
% 按键1(即'图像处理'按键)的回调函数,包含全部图像处理算法
global a5;%全局变量
global svmModel;%全局变量,从svm.m文件调用
axis off;%去除axes坐标,完整显示图片
a6=a5;
a=str2double(get(handles.edit1,'string'));%读取用户输入的焦距
b=str2double(get(handles.edit2,'string'));%读取用户输入的物距
d=a/(b-a);%由高斯公式计算垂轴放大率
ma=max(max(a6));
mi=min(min(a6));
%对比度增强,将灰度映射为[0,255]
for ii=1:200
for jj=1:200
a6(ii,jj)=255*double(a6(ii,jj)-mi)./double(ma-mi);
end
end
%图像滤波
ab=filterimage(a6);
%图像最大熵阈值分割
ss=thres(ab);
ab1=im2bw(ab,ss/255);
[B,L]=bwboundaries(ab1);%二值图边缘坐标提取
[x,y]=size(B);
mm=0;
%寻找最大提取区域
for i=1:x
ll=length(B{i});
if ll>mm
mm=ll;
end
end
%判断是否是'轧入氧化皮'缺陷
if mm<120
set(handles.text8,'string','缺陷是轧入氧化皮');%在text8文本框处输出缺陷类型
[xc,yc]=findcenter(B,ab);%求各提取区域的质心位置
axes(handles.axes2);%设置在axes2处显示
imshow(a6);
hold on;
plot(yc+12,xc+12,'*');%加上滤波时失去的边界
[dd,bb]=size(xc);
tex=['一共有',num2str(dd),'个以上的点'];
set(handles.text10,'string',tex);%在text10文本框处输出缺陷信息
%不是'轧入氧化皮'缺陷,继续判断
else
%原图与二值图进行掩模处理,注意二者大小不同,故要先剔除原图边缘
a6(1:12,:)=[];
a6(177:188,:)=[];
a6(:,1:12)=[];
a6(:,177:188)=[];
mu1=uint8(ab1).*a6;
mu2=uint8(1-ab1).*a6;
t0=mu1(mu1~=0);
m1=mean(t0);
t1=mu2(mu2~=0);
m2=mean(t1);
%判断缺陷是斑点还是划痕:斑点比背景暗,划痕比背景凉;将掩模与背景剩余均值比较
%也可以先提取图像的LBP(局部二值模式)特征,再使用SVM训练的结果来进行分类
if m1<m2+20
set(handles.text8,'string','缺陷是斑点');
all=bwarea(ab1);%计算斑点面积
pro=100*all/176/176;%计算所占百分比
tex=['斑点所占面积比为',num2str(pro),'%'];
set(handles.text10,'string',tex);
axes(handles.axes2);
imshow(a6);
hold on;
%标注出斑点边界
for k = 1:length(B)
boundary = B{k};
plot(boundary(:,2), boundary(:,1), 'r', 'LineWidth', 2)
end
%缺陷是划痕
else
a6=adapthisteq(a6);%自适应直方图均衡化再次加强对比度
ss=thres(a6);
ab1=im2bw(a6,ss/255);
ab1=imclose(ab1,strel('square',6));%对二值图做闭运算,将断开部分连接
ab1=bwmorph(ab1,'thin',5);%对二值图再进行细化
ab1=edge(ab1,'Canny');%使用Canny算子边缘提取
set(handles.text8,'string','缺陷是划痕');
axes(handles.axes2);
imshow(a6);
hold on;
%往下是划痕提取的后续处理与显示
[point,ang]=houghtran( ab1 );%对处理好的二值图进行霍夫直线检测
cen=zeros(length(ang),2);
po=zeros(length(ang),4);
an=zeros(length(ang),1);
thm=mean(abs(ang));
%判断划痕是横线还是竖线(直线与y轴夹角)
if abs(thm)<45%竖线
thm=40;
else%横线
thm=60;
end
le=length(cen);
%求取每根直线的中点位置
for kk=1:le
cen(kk,1)=(point(kk,1)+point(kk,3))/2;
cen(kk,2)=(point(kk,2)+point(kk,4))/2;
point(kk,5)=cen(kk,1);
point(kk,6)=cen(kk,2);
end
%按中点对直线进行排序
if thm==40%如果是竖线,按横坐标排序
point=sortrows(point,5);
end
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.