一、简介
1.1题目内容\ 金属板广泛应用在工业生产与生产生活的各方面。由于金属板制造过程涉及到的设备、工艺等多因素的影响,金属板表面容易出现种类较多、形态各异的缺陷,这些缺陷对金属板的耐磨性、抗腐蚀性、电磁特性及美观性都会造成不同程度的影响,最终影响金属板的电磁特性和涂镀效果。因此对于生产金属板的企业来说,表面缺陷检测是必不可少的一个工序,一方面可以通过表面缺陷检测及时检测到缺陷产品,保证所产金属板的质量,维护企业的信誉,另一方面也可以通过分析检测结果及时发现生产过程中存在的问题,并及时解决[1]。我们将依据网上提供的金属表面缺陷照片数据集为图片来源,构造相应的算法对金属表面的缺陷进行检测,识别,分类与大小测量。\ 1.2题目要求\ 金属表面缺陷识别与分类有以下具体要求:\ (1)依据金属表面缺陷图片的特性,对图片进行适当的灰度变换(对比度增强与滤波处理);\ (2)对金属表面缺陷图片进行全局优化阈值分割;\ (3)提取二值图片区域边界坐标;\ (4)对金属缺陷进行特征提取;\ (5)对金属缺陷进行分类有监督训练;\ (6)完成对金属缺陷类型的判断与位置大小的计算;\ (7)完成金属缺陷检测的GUI设计。\ 2.题目分析\ 我们查阅相关资料了解到常见的金属表面缺陷主要有如下几种,其分别是:细裂纹(crazing),表面杂质(inclusion),斑点(patches),麻点(pitted surface),轧入氧化皮(rolled-in scale)与划痕(scratches)。其分别对应图(a)-图(f)。\ \ 我们只考虑其中的三种类型:表面斑点(图b),表面轧入氧化皮(图(e))与表面划痕(图(f))。\ 图像处理的主要步骤有:对比度增强,滤波处理,阈值分割,形态学处理,特征提取,分类训练,缺陷位置大小计算及GUI集成操作显示。\ Step.1:对比度增强\ 由于照明方式等缘故,我们发现原始图像中的金属表面缺陷和整个金属表面背景之间的灰度差较小,灰度范围较小,因而其对比度较低,金属缺陷并不明显,这不利于图像的后期处理,我们需要使用一些方法来增加图像的对比度。常见的对比度增强方法有对数变换,幂律变换,灰度级分层,灰度归一化,对比度拉伸,直方图均衡化,直方图规定化等。考虑到不同照片的背景光强并不相同,所以恒定参数的方法(如对数变换,幂律变换,灰度级分层,对比度拉伸)并不对所有图片适用,故我们考虑使用灰度归一化和直方图均衡化。\ Step.2:滤波处理\ 拍摄照片时,在采集过程将会不可避免的引入各种噪声,包括高斯噪声和椒盐噪声等。同时,金属表面本身就具有一定的纹理。噪声和纹理将一定程度上将金属表面缺陷掩盖,从而导致会提取中产生错误,我们需要先对图像进行滤波处理以减少后续误检测。滤波方法主要分为空域滤波与频域滤波,且二者的关系满足卷积定理。其中空域滤波主要有均值滤波,中值滤波,高斯滤波与双边滤波;频率滤波注意有傅里叶变换滤波,离散余弦变换滤波与小波变换滤波。这些算法虽然可以减少噪声,但是也会滤除部分细节信息,导致某些缺陷细节的丢失。所有我们需要寻找新的滤波算法来实现。\ Step.3:阈值分割\ 我们得到滤波图像后,还需要进行二值化阈值处理,从而恰当提取出缺陷信息。传统的阈值分割需要确定阈值,但对于不同复杂的金属缺陷图片,我们无法对所有的图片使用相同的阈值,我们拟使用全局/局部优化阈值分割,自动确定最佳的阈值。\ Step.4:形态学处理\ 受限于原图质量与图像阈值分割算法,二值图像中某些应该连通的区域可能被阈值分割了,例如划痕缺陷由于在某处灰度值较低而被错误分割,导致一条划痕可能会被分离为多个线段。故我们需要进行闭运算来连接临近物体。同时,图片中某些缺陷较大(例如划痕宽度较大),在后续边缘检测后,一条直线的两个边缘相距较大,直线提取算法会误将同一根线作为两根相互平行划痕。故我们还需要对缺陷进行细化操作。\ Step.5: 特征提取\ 该部分可以使用两种方法,一种是基于通用的特征提取算法(例如HOG, LBP, Haar算法等);另一种是基于我们所要检测的特定金属缺陷进行特定的特征来直接对划痕进行分类。我将分别对这两种方法进行测试。\ Step.6: 分类训练\ 如果我们使用了通用的特征提取算法,我们将要对其进行分类监督训练,常用的监督学习算法包括:K临近算法(KNN),朴素贝叶斯算法,决策树算法,支持向量机(svm),逻辑回归等。由于支持向量机具有优秀的泛化能力,且在小样本训练集能够得到比其他算法好的多的效果[6],我们拟选择支持向量机算法。\ Step.7: 缺陷位置大小计算\ 我们提取到缺陷后,需要不同特征来表征缺陷的大小与位置。对与’轧入氧化皮’,我们使用’轧入氧化皮’个数来表征缺陷大小,用其质心表征其位置;对于斑点,我们使用斑点中的面积占整个图片的比例来表征缺陷大小。对于划痕,我们使用划痕的两个端点来表征缺陷位置,用划痕长度标准缺陷大小。\ Step.8: GUI设计\ 为了方便用户使用,我们设计了GUI界面,能够选择电脑中的图片,且能在点击’图像处理’后显示提取到的缺陷信息(类型与位置大小),对于划痕长度,我们能够让用户输入相机的焦距与物距长度,从而根据几何光学知识计算出实际划痕大小,并将每个划痕的像面大小与实际大小显示出来。同时GUI能够让用户通过按键前往数据集的下载网站。
二、源代码
``` //作品概述: 本代码主要功能是实现金属表面三种缺陷的检测、分类及测量,并使用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提供,无需修改
guiSingleton = 1; guiState = struct('guiName', mfilename, ... 'guiSingleton', guiSingleton, ... 'guiOpeningFcn', @appOpeningFcn, ... 'guiOutputFcn', @appOutputFcn, ... 'guiLayoutFcn', [] , ... 'guiCallback', []); if nargin && ischar(varargin{1}) guiState.gui_Callback = str2func(varargin{1}); end
if nargout [varargout{1:nargout}] = guimainfcn(guiState, varargin{:}); else guimainfcn(guiState, 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
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
```