二维码的定位

该文介绍了DataMatrix二维码的结构和特性,包括寻边区、数据区以及采用的Reed-Solomon纠错编码。实验步骤涉及图像预处理,使用Canny算子进行边缘检测和膨胀操作,然后通过霍夫变换寻找圆和直线来定位二维码。通过对图像进行旋转和二值化,最终解析二维码的0、1内容矩阵。
摘要由CSDN通过智能技术生成

1、实验原理

Data Matrix二维码是二维码的一种,其由黑白相间的两种颜色组成的图形,每一个相同大小的黑色或白色方格称为一个数据单位。由于自身小的缘故可被广泛用于标示集成电路、药品等小件物品。

DM由寻边区和数据区组成,寻边区对二维码的边界进行识别,数据区则是二维码的数据编码部分。

 

fa9b61d19e6745a78d51fe5a50267fb6.png

上图中第二幅图又可分为L型实线和L型虚线。

此外DM采用了Reed -SoIomon 交织交插编码,编码时加入了纠错码, 使DM的纠错性能比较强。

直线型边缘在图像中较为常见,容易对二维码的定位造成干扰,在二维码区域加入其它特征,例如圆,可以辅助二维码定位。

哈夫变换可以查找图片中的圆和线,通过这些特征的查找可定位二维码,进而读取二维码的内容。

2、实验步骤

  1. 图片预处理
    1. 进行边缘像素查找
  2. 霍夫变换
    1. 查找图片中的圆
    2. 查找图片中的直线
  3. 获取位置
    1. 取圆心为二维码中心
  4. 获取二维码内容
    1. 通过直线的角度获取二维码偏转角(原点在左下角,向右为X轴,向上为Y轴,与X轴逆时针旋转角度为二维码角度)
    2. 将二维码转正
    3. 将二维码区域进行截取
    4. 将该子区域进行二值化
    5. 根据二维码方格数目(本实验二维码内容格子数目为10x10),获取二维码0、1内容矩阵。
  5. 示例图片

5c7f6d75734d4d1183871443b6e69a7b.jpeg

 上代码:

clc
clear
img = imread('DM01.bmp');

%对图像进行边缘检测并进行膨胀操作
BW=edge(img,'canny',[0.04,0.1],3);
se = strel('line',10,150);
BW1 = imdilate(BW,se);
figure(1)
imshow(BW1);


%进行霍夫变换检测园
[HOUGH_SPACE,HOUGH_CIRCLE,PARA] = hough_circle(BW1,1,0.1,160,300,0.5);
hold off


%处理数据,根据得到的矩阵将圆心坐标半径求均值
m = length(PARA);
n = fix(m/2);
sum1 = sum(PARA(:,1:n),2);
sum2 = sum(PARA(:,n+1:m),2);
s1 = sum1/n;
s2 = sum2/(m-n);
y1=s1(1,1);
x1=s1(2,1);
r1=s1(3,1);
r2=s2(3,1);
 %x1;y1; 


[dm,dn]=size(BW1);
img1 = zeros(dm,dn);
 
for i = 1:dm
    for j = 1:dn
        if (i - y1).^2+(j - x1).^2 <= r1.^2
           img1(i,j) = BW(i,j); 
        end
    end 
end

% BW2=edge(img1,'canny',[0.04,0.1],3);
% se = strel('line',10,150);
% BW3 = imdilate(BW2,se);
% figure(6)
% imshow(BW3)



[H,T,R] = hough(img1);%计算二值图像的标准霍夫变换,H为霍夫变换矩阵,I,R为计算霍夫变换的角度和半径值
figure(2)
imshow(H,[],'XData',T,'YData',R,'InitialMagnification','fit');%hough变换的图像
xlabel('\theta'), ylabel('\rho');
axis on,axis square,hold on;
P  = houghpeaks(H,2);%提取2个极值点
% m = P(1,2);
q = P(2,2);
x2 = T(P(:,2)); 
y2 = R(P(:,1));
plot(x2,y2,'s','color','white');%标出极值点
lines=houghlines(img1,T,R,P);%提取线段


figure(3)
imshow(img), hold on;
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');%画出线段
plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');%起点
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');%终点
end


%根据上面得到的数据画出大圆小圆
rectangle('Position',[x1-r1,y1-r1,2*r1,2*r1], ...
        'Curvature',[1,1],'EdgeColor','m','LineWidth',3)
rectangle('Position',[x1-r2,y1-r2,2*r2,2*r2], ...
        'Curvature',[1,1],'EdgeColor','r','LineWidth',3)


%旋转图像
Theta = 90-q;
J = imrotate(img,-Theta,'bilinear','crop');
figure(4)
imshow(J);


%截图
img2 = f_Cut_for_circleMask(J,y1,x1,r2,1);
figure(5)
imshow(img2);

% %将图像二值化
% I = double(img2);
% thresh = graythresh(I);     %自动确定二值化阈值
% I2 = im2bw(img2,thresh);       %对图像二值化
% figure(6)
% imshow(I2);


x = (lines(1).point1(:,1))/2+(lines(2).point1(:,1))/2;%左上角x
y = lines(1).point1(:,2)/2+lines(2).point1(:,2)/2;%左上角y
a = (lines(2).point2(:,1)-x)/10;%边长
b1 = (lines(2).point2(:,2)-y)/11;%每行差的高度
xx = x+a*0.5;%第一个格子的坐标
 
b = (lines(1).point2(:,2)-y)/12;
a1 = (lines(1).point2(:,1)-x)/11;%每列差的宽度
yy = y+b*0.2;%第一个格子的坐标
%
code = zeros(11,11);
%
X = zeros(dm,dn);
for i=1:dm
    for j=1:dn
        if img(i,j)>60
            X(i,j) = 1;
        end
    end
end
% 
figure;
imshow(X);
hold on;
% % plot(round(xx),round(yy), 'r+'); 
% % plot(round(xx+2*a+2*a1),round(yy+2*b+2*b1), 'r+'); 
% % plot(round(xx+3*a+2*a1),round(yy+2*b+3*b1), 'r+'); 
% % plot(round(xx+4*a+2*a1),round(yy+2*b+4*b1), 'r+'); 
% % plot(round(xx+5*a+2*a1),round(yy+2*b+5*b1), 'r+'); 
% 
n = 0;
for i = 1:11
    for j = 1:11 
        sum(i,j) = 0;
 
        for k = -1:1
            for l = -1:1 
                m1 = xx+i*a+j*a1+k;
                n1 = yy+j*b+i*b1+l;
                aa = X(round(n1),round(m1));
                sum(i,j) = sum(i,j)+aa;
            end
        end
        
        if sum(i,j)>=5
            code(i,j) = 1;
        else
            code(i,j) = 0;
        end
 
    if code(i,j) == 1
        plot(round(xx+i*a+j*a1),round(yy+j*b+i*b1), 'b+');  %白格子
    else
        plot(round(xx+i*a+j*a1),round(yy+j*b+i*b1), 'r+');  %黑格子
    end
    
end
end
%code = code';
figure;imshow(code);

效果展示

9166ec15b747417496a871abe2836dc2.pngd785ce42e3a747109d1ee01e46d8608e.png

 9e16ab1988024fde88a04b3fe1cb4162.png9d434a0e2bf14b1684d9a4517f993a4f.png

 2f805816a84e4a80b954a3495f23a0f3.png2fb413c1751c4e22a30692c03a0efa50.png

 6b9130f0e85341f380c4e4bf58e82fc1.png

 

 

 

 

 

  • 10
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值