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.仿真结果
A10-38