基于图像处理技术的工业缺陷检测

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cuixing001/article/details/83246218

       工业缺陷检测有很多应用的地方,如汽车轮毂制造的缺陷、手机壳的缺陷、太阳能电池板的缺陷等等。由于问题比较简单,这次针对太阳能电池板进行缺陷检测,即电池板上有很多条状撕裂细纹或者小斑点视为缺陷。由于图像很多(成千上万,每块板有6*10小块,基本均匀大小分布),这里只给出代表性的一整块太阳能电池板,其中最后一小块(patch)有细纹缺陷,其他小块略有斑点缺陷。

一、求解思路

这里主要用基本的图像处理技术即可识别出缺陷,其主要算法思路为:

  • step1:对整张电池板进行背景前景分割。背景为外圈黑色,前景为patchs小块,二值化整个图像,阈值设为0.35,大致可以得到基本轮廓;采用闭操作,消除峡沟,孔洞,找出最大连通域,最终可以得到完整的前景图像。
  • step2:电池小块进行定位。由于是均匀同大小分布的,故可以几何上得到完整的小块图像。
  • step3:分别对每个小块进行图像处理。由于每小块有横线存在,这个不属于缺陷,故可以用水平检测核(比如prewitt算子)先检测出横线,注意阈值选取,用canny算子检测所有纹理边界;
  • step4:排除横线及小块四周边界线的干扰,保留缺陷纹理。这里对prewitt检测的横线进行膨胀操作,目的是获取非横线区域的mask,再与canny的mask求交即可获取缺陷位置。
  • step5:缺陷标记。获取识别位置后,组建一个预先的三通道图像,对缺陷位置的像素灰度值标记为红色。

二、实现代码

这里给出实现代码和识别结果。

%% 用于太阳能电池板缺陷检测,缺陷用红色标记,正常就不标记
patch_rows = 6;
patch_cols = 10;
imds = imageDatastore('./defect_image_cell',... % 改成自己.jpg图像所在目录即可
    'includeSubfolders',true,...
    'fileExtensions',{'.jpg'});
nums = length(imds.Files);


%% main loop
for k = 1:nums
    img1 = imresize(readimage(imds,k),0.3);
    if size(img1,3)==3
        img1 = rgb2gray(img1);
    end
    
    %% get max rect
    bw = imbinarize(img1,0.35);
    se = strel('disk',3);
    bw_close = imclose(bw,se);
    s = regionprops(bw_close,'BoundingBox');
    max_area = 0;
    max_rect = [];
    for i = 1:length(s)
        area = s(i).BoundingBox(3)*s(i).BoundingBox(4);
        if area>=max_area
            max_area = area;
            max_rect = s(i).BoundingBox;
        end
    end
    
    %% get all patches rects
    x = linspace(max_rect(1),max_rect(1)+max_rect(3),11);
    y = linspace(max_rect(2),max_rect(2)+max_rect(4),7);
    [X,Y] = meshgrid(x,y);
    square_rects = zeros(patch_rows*patch_cols,4);
    for i = 1:patch_rows
        for j = 1:patch_cols
            square_rects(patch_cols*(i-1)+j,:) = [X(i,j),Y(i,j),X(i,j+1)-X(i,j),Y(i+1,j)-Y(i,j)];
            current_rect = square_rects(patch_cols*(i-1)+j,:);
        end
    end
    
    %% detect each patch defect
    img1_RGB = cat(3,img1,img1,img1);
    for i = 1:patch_rows*patch_cols
        x = floor(square_rects(i,1));
        y = floor(square_rects(i,2));
        width = floor(square_rects(i,3));
        height = floor(square_rects(i,4));
        current_patch = img1(y:(y+height),x:(x+width));
        [bw_ed,threshOut] = edge(current_patch,'prewitt',0.040);
        SE = strel('disk',3,6);
        dilate_img = imdilate(bw_ed,SE);
        [bw,threshold] = edge(current_patch,'canny',[0.0585,0.2563]);
        border = round(0.12*size(bw,1));
        bw_mask = false(size(bw));
        bw_mask(border:size(bw,1)-border,border:size(bw,2)-border) = true;
        mask = bw_mask&bw;
        mask = mask&(~dilate_img);
        R = current_patch;G = current_patch;B = current_patch;
        R(mask) = 255;G(mask) = 0;B(mask) = 0;
        draw_patch = cat(3,R,G,B);
        img1_RGB(y:(y+size(draw_patch,1)-1),x:(x+size(draw_patch,2)-1),:) = draw_patch;
    end
    [path,name,~] = fileparts(imds.Files{k});
    save_name = fullfile(path,[name,'_draw.png']);
    imwrite(img1_RGB,save_name);
%     imshowpair(img1,img1_RGB,'montage')
end

识别结果图:

所有源码和图像这里下载

猜你喜欢

转载自blog.csdn.net/cuixing001/article/details/83246218