天天看點

【二維碼圖像矯正增強】基于MATLAB的二維碼圖像矯正增強處理仿真

1.軟體版本

matlab2013b

2.算法流程概述

通過形态學處理獲得二維碼部分的圖像區域及邊界;

采用凸包算法來計算邊界上的點集;

然後根據點集來尋找二維碼的四個頂點,

然後透視變換矯正,二維碼分割得到每個格子中的點。

進行二維碼圖像歸一化。完成二維碼修正。

然後做實驗比較與其他采用邊緣檢測加hough變換進行矯正後圖像的識别率。

在二值化操作之前進行光照增強,采用同态濾波和直方圖均衡化結合的方式來做,然後采用ostu法進行二值化。

通過定位二維碼三個角點的位置,然後通過膨脹處理,并進行連通區域。将不是這三個探測圖元所在的連通區域删除,然後将剩下的連通區域腐蝕,進行邊緣檢測,将得到的邊緣上的點集用凸包法進行連接配接,

大緻确定二維碼的邊界,然後使用到四條外界直線距離最短的方式來确定四個頂點。

3.部分源碼

clc;
clear all;
close all;
warning off;
addpath 'func\'


%filename ='1.jpg';
%filename ='2.jpg';
%filename ='3.jpg';
filename ='4.jpg';

X        = imread(filename);  
%擷取圖像相關資訊
[R,C,K]  = size(X);
if K == 3
   f = rgb2gray(X);
else
   f = X;
end

%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%使用小波濾波+中值濾波的改進濾波方案
figure
subplot(141);
imshow(f);
title('原始圖像');
f = imadjust(f,[0.1 0.8],[]);

f = func_wavelet_filter(f);
subplot(142);
imshow(f);
title('小波濾波和光線增強後圖像');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%基于OSTU方法的二值提取
G   = f;
f   = func_ostu(f); 
f   =~f;
subplot(143);
imshow(f);
title('ostu二值化處理圖像');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%
%形态學膨脹
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SE = strel('disk',8);
I  = imdilate(f,SE);
%删除小的區域
I  = bwareaopen(I,20000);
%求取整幅圖的重心
subplot(144);
imshow(I);
title('形态學膨脹圖像');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%




%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%标記連通域
[L,num]=bwlabel(I,8);
figure
subplot(141);
imshow(L);
%剔除無關連通域,這裡改進了剔除措施,之前的方法很多測試圖檔沒法正确處理
[R,C,K] = size(I);
L2      = zeros(R,C);
for i=1:num
    [r,c]=find(L==i); %計算坐标
    if isempty(r) == 0 & isempty(c) == 0 
       a2(i) = min(r);  %計算坐标
       a1(i) = max(r);  %計算坐标
       b2(i) = min(c);  %計算坐标
       b1(i) = max(c);  %計算坐标
       %根據面積進行判斷是否是正确的區域
       Lss    = a1(i) - a2(i);
       Wss    = b1(i) - b2(i);
       if (Lss>=0.9*Wss & Lss<=1.1*Wss) | (Wss>=0.9*Lss & Wss<=1.1*Lss)
          for j = 1:length(r) 
              L2(r(j),c(j)) = L(r(j),c(j));
          end
       end
    end
end
SE = strel('disk',8);
T=imerode(L2,SE);
T=imfill(T,'holes');
subplot(142);
imshow(T);
title('形态學腐蝕');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%



%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%提取邊緣
T2=edge(T,'prewitt');
subplot(143);
imshow(T2);
title('提取邊緣');
%待判斷凸包的點集,這個部分做了改進,原來的方法存在殘缺問題,會無法檢測邊緣的問題
[y,x] = find(T2==1);
img   = ones(size(T2));
p     = [];
for i=1:length(x)
    img(y(i),x(i))=0; 
    p=[p;x(i),y(i)];     
end
subplot(144);
imshow(img);
%下面計算凸包
[t,index] = max(p(:,2));  
%找到y最大的點
tmp_p     = p(index,:);         
%設一個和y最大的點平行的點
tmp_heng  =[tmp_p(1)+100,tmp_p(2)];    
for i=1:length(p)           
    %求每個點和y最大的點的夾角,自己和自己夾角NAN
    Ang(i) = func_angle(tmp_heng,p(i,:),tmp_p);  
end
Ang   = Ang';
p     =[p,Ang];
%按第三列排序,第三列是夾角度數
p     = sortrows(p,3);    
%re相當于棧
re{1} = p(length(p),1:2);     
re{2} = p(1,1:2);
re{3} = p(2,1:2);
top   = 3; 
for i=3:length(p)-1
    while func_multi(p(i,1:2),re{top-1},re{top})>=eps      
        top=top-1;    
        if top<=1
           break;
        end
    end
    top=top+1;
    re{top}=p(i,1:2);
end
 
%下面是把找到的凸包上的點連線
for i=2:top   
    imgs = drawline(img,re{i-1}(1),re{i-1}(2),re{i}(1),re{i}(2));
end
imgs = drawline(img,re{1}(1),re{1}(2),re{top}(1),re{top}(2));

figure
subplot(231);
imshow(imgs)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%計算四個頂點
jiaodian2             = func_cal_point(imgs);
%這裡使用相似度比對措施對初始頂點進行頂點修正
[jiaodian3,jiaodian4] = func_cal_point_adjust(jiaodian2,G);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%校正
Z=func_adjust(jiaodian4,G);
subplot(232);
imshow(uint8(G))
hold on
for i = 1:4
    plot(jiaodian2(i,2),jiaodian2(i,1),'g.'); 
    hold on;
    text(jiaodian2(i,2),jiaodian2(i,1),num2str(i)); 
end

subplot(233);
imshow(uint8(G))
hold on
for i = 1:4
    plot(jiaodian4(i,2),jiaodian4(i,1),'r.'); 
    hold on;
    plot(jiaodian3(i,2),jiaodian3(i,1),'g.'); 
    hold on;
end

subplot(234);
imshow(uint8(G))
hold on
for i = 1:3
    line([jiaodian4(i,2),jiaodian4(i+1,2)],[jiaodian4(i,1),jiaodian4(i+1,1)],'Color',[0 1 0]); 
    hold on;
end
line([jiaodian4(end,2),jiaodian4(1,2)],[jiaodian4(end,1),jiaodian4(1,1)],'Color',[0 1 0]); 

subplot(235);
Z2 = histeq(uint8(Z));
imshow(Z2);

subplot(236);
thresh=graythresh(Z2);
f   = im2bw(Z2,thresh); 
imshow(f);
 

%%
%對最後的結果進行分割
[R,C] = size(Z2);

Z3    = edge(Z2,'canny');

%行掃描
tmp1  = 0;
tmp2  = 0;
for i = 2:R  
    tmp1    = f(i-1,:);
    tmp2    = f(i,:);
    diff1(i) = abs(mean(tmp1 - tmp2));
end
%搜尋最小值
[pks1,locs1]=findpeaks(-1*diff1,'minpeakdistance',3); % Find peaks 



%列掃描
tmp1  = 0;
tmp2  = 0;
for i = 2:C  
    tmp1    = f(:,i-1);
    tmp2    = f(:,i);
    diff2(i) = abs(mean(tmp1 - tmp2));
end
%搜尋最小值
[pks2,locs2]=findpeaks(-1*diff2,'minpeakdistance',3); % Find peaks 
locs1 = [locs1];
locs2 = [locs2];
%獲得歸一化二維碼
QRcode = zeros(length(locs1),length(locs2));
for i = 1:length(locs1)
    for j = 1:length(locs2)
        QRcode(i,j) = f(locs1(i),locs2(j));
    end
end
%補償
QRcode = QRcode; 


figure;
subplot(3,2,1);
imshow(Z2);
subplot(3,2,2);
imshow(Z3);
subplot(3,2,3);
plot(diff1);
hold on;
plot(locs1,diff1(locs1),'k^','markerfacecolor',[1 0 0]);
title('水準邊緣投影');
subplot(3,2,4);
plot(diff2); 
hold on;
plot(locs2,diff2(locs2),'k^','markerfacecolor',[1 0 0]);
title('垂直邊緣投影');

subplot(3,2,5);   
imshow(Z2,[]);
title('透視糾正後圖像');
subplot(3,2,6);   
imshow(QRcode,[]);
title('歸一化二維碼');







      

4.仿真結果

【二維碼圖像矯正增強】基于MATLAB的二維碼圖像矯正增強處理仿真