實驗名稱:條碼缺陷檢測
-
實驗內容
條碼中可能存在的斷碼、白點、黑點等影響條碼外觀的瑕疵,檢測這些瑕疵,並用紅色矩形框將其標出。 -
分析過程
需要用到圖像形態學知識,先確定條碼目標,再對ROI區域內進行缺陷檢測。步驟如下:
① 預處理:對圖形進行二值化;
② 確定ROI:圖形取反,膨脹,得到最大的兩個連通域目標,即爲兩個條碼區域ROI;
③ 取條碼圖形:將ROI區域與原圖形做邏輯與操作,得到只有原條碼的圖片;
④ 去噪:中值濾波,去除過小的噪聲,並讓過小的缺陷橫向特徵更明顯;
⑤ 去條碼:再次取反,進行開運算,先通過腐蝕操作使用長橫條形狀內核去除豎碼條,再通過膨脹操作讓缺陷部分更突出;
⑥ 確定缺陷塊:將去除了豎條碼區域的圖像和ROI區域做與運算,得到缺陷小塊集合;
⑦ 優化:不同內核的多次中值濾波,進一步濾去未消除乾淨的豎條碼,再次膨脹突出缺陷;
⑧ 標記:使用紅色矩形框對各連通域進行標記。 -
實驗效果圖
可以看到,大多數缺陷都已經可以檢測出,但依舊有些地方檢測不到,有待改進。 -
實驗代碼(Matlab)
Main.m
clear;
close all;
clc;
%% Binarize the input image
im = imread('images/barcode_7.png');
im_gray = rgb2gray(im);
level = graythresh(im_gray)
bw = im2bw(im_gray, level);
figure;
subplot(3, 2, 1); imshow(im_gray); title('original image');
subplot(3, 2, 2); imshow(bw); title('binary result');
%% 請基於二值圖像bw,將二維碼瑕疵區域檢測出來
detect = ~bw;
% subplot(3, 2, 3);imshow(detect); title('detect');
hold on
SE=strel('rectangle',[1 30]);
detect = imdilate(~bw, SE);
f = maxLianTongYu(detect); %分離第一個二維碼
s = maxLianTongYu(detect-f); %分離第二個二維碼
f = f + s;
ROI = imdilate(f, strel('rectangle',[30 30]));
ROI = imerode(ROI, strel('rectangle',[40 40])); %白色二維碼區域
first = f&~bw;
first = medfilt2(first,[1,5]); %中值濾波,讓過小的缺陷橫向特徵更明顯
% subplot(3, 2, 4);imshow(~first); title('first');
first = imerode(~first, strel('rectangle',[1 35])); %去除豎碼條
first = imdilate(first, strel('rectangle',[10 10])); %讓缺陷部分更突出
first = first & ROI;
first = medfilt2(first,[15,2]); %中值濾波[15,14]
first = medfilt2(first,[18,12]);
first = imdilate(first, strel('rectangle',[10 10]));
% subplot(3, 2, 5); imshow(first); title('second');
imLabel = bwlabel(first); %對各連通域進行標記
stats = regionprops(imLabel,'Area', 'boundingbox'); %求各連通域的大小
area = cat(1,stats.Area);
rects = cat(1,stats.BoundingBox);
subplot(3, 2, [3 6]); imshow(im); title('final');
for i = 1:size(rects, 1)
rectangle('position', rects(i, :), 'EdgeColor', 'r');
end
maxLianTongYu.m
%function [img]=maxLianTongYu(I):求圖像中最大的連通域
%輸入:I 輸入圖像
%輸出:img 僅包含最大連通域的圖像
function [img]=maxLianTongYu(I)
if length(size(I))>2
I = rgb2gray(I);
end
if ~islogical(I)
imBw = im2bw(I); %轉換爲二值化圖像
else
imBw = I;
end
imLabel = bwlabel(imBw); %對各連通域進行標記
stats = regionprops(imLabel,'Area'); %求各連通域的大小
area = cat(1,stats.Area);
index = find(area == max(area)); %求最大連通域的索引
img = ismember(imLabel,index); %獲取最大連通域圖像