一维条码解码

一维条码是一种能用于信息编码和信息自动识别的标准符号,是由一组宽度不同的黑白符号按一定规则交替排列编码组成的图形符号可用于表示一定的信息。

它是对物品进行代号标识需要依赖数据库或通讯网络才能发挥最大的作用。常见的码制(条码符号类型)有EAN-13码,EAN-8码,UPC码,交叉25码。

EAN-13解码:

EAN-13码结构


解码流程:

一维条码解码matlab代码

function [code]=one_dimensional_codeself(img)
%% 图片的读取
f=imread(img);% read figure
g=rgb2gray(f);  %turn to gray figure
figure(1);
imshow(g);title('原图像');
[M,N]=size(g);
%% 图片的处理
T=graythresh(g)*255; %get threshold
g= Thresholding(g,T); %二值化
%% 噪声过滤
g=medfilt2(g); %filter
figure(2);
imshow(g);title('滤波后的图像');
im_edge=edge(g,'canny'); %边缘检测
figure(3);
imshow(im_edge);title('边缘检测后的图像');
A=line_detection(im_edge);
g=~g; %黑白像素翻转
%% 图片旋转
g=imrotate(g,A*180/pi,'nearest'); %旋转图像
g=~g;
figure(4)
imshow(g);title('旋转后的图像1');
is=is_upsize(g);       %判读是否是正向水平
if is==1
    g=imrotate(g,180,'nearest');
end
figure(5)
imshow(g);title('旋转后的图像2');
bar_width=bar_width_F(g);%获取条空的宽度
decode=dedecode_f(bar_width);%条空换做0,1表示
%% 一维码破解
if check_1(decode)
    code=decode_f(decode);
end

Thresholding.m

%% 图像二值化 T为阀值
function [g]= Thresholding(g,T)
[M,N]=size(g);
for i=1:1:M
    for j=1:1:N
        if g(i,j)<T
            g(i,j)=0;
        else
            g(i,j)=255;
        end
    end
end

line_detection.m

%% 霍夫直线检测
function A=line_detection(im_edge)
[row,col]=size(im_edge); %图像大小
p_max=floor(sqrt((row)^2+(col)^2))+1; %原点到直线最远的距离,就是到图像右上角的距离
accumulation=zeros(p_max,180);
theta=[0:pi/180:pi];%角度
max_num=0;
A=0;
%遍历图像,统计映射的(P,theta),选取最大的统计量对应的角度
for n=1:row
    for m=1:col
        if(im_edge(n,m)==1)
            for k=1:180
                p=(m*cos(theta(k)))+(n*sin(theta(k)));
                p_int=round(p/2+p_max/2);
                accumulation(p_int,k)=accumulation(p_int,k)+1;
                if accumulation(p_int,k)>max_num
                    max_num=accumulation(p_int,k);
                    A=theta(k);
                end
            end
        end
    end
end

is_upsize.m

%% 判读是否是正向水平- 通过将一维码区两边的像素点相加,像素和大的一边为底
function is=is_upsize(g)
row=0;
[m,n]=size(g);
kk=size(m);%kk记录每一行的像素和
for i=1:m
    kk(i)=1;
    for j=1:n-1
        if g(i,j)~=g(i,j+1)
            kk(i)=kk(i)+1;
        end
    end
end
left_sum=0;
for i=1:m
    if(kk(i)==61) %61为标准条码区
        for j=1:10 
            left_sum=left_sum+kk(i-j);%与标准条码区相邻10行的像素和
        end
        break;
    end
end
right_sum=0;
for i=m:-1:1
    if(kk(i)==61)
        for j=1:10
            right_sum=right_sum+kk(i+j);%同上
        end
        break;
    end
end
if left_sum>right_sum %上面像素的大于下面像素和说明倒了
    is=1;
else
    is=0;
end


bar_width_F.m

%% 获得条空比-判断相邻像素的值,不同就是边界,再求得条宽,与单位条宽相比,得到条空比。
function [bar_width]=bar_width_F(g)
[M,N]=size(g);
bar_y=zeros(M,N);%记录边界的列值,bar_y(M,1)记录是不是标准条码区 2-61位为边界列
l=1;
k=2;
for i=1:M
    for j=1:N-1
        if g(i,j)~=g(i,j+1)
            bar_y(l,k)=j;
            k=k+1;
        end
    end
    if k==62
        bar_y(l,1)=1;
    else
        bar_y(l,1)=0;
    end
    l=l+1;
    k=2;
end
%对于每一列求平均值得到,边界列的最终值
bar_width_num=zeros(60);
for i=2:61
    sum=0;
    row=0;
    for j=1:l-1
        if bar_y(j,1)==1
            row=row+1;
            sum=sum+bar_y(j,i);
        end
    end
    bar_width_num(i-1)=sum/row;
end
%相邻的列相减得到宽度
bar_width=zeros(59);
for i=1:59
    bar_width(i)=bar_width_num(i+1)-bar_width_num(i);
end
sum=0;
for i=1:59
    sum=sum+bar_width(i);
end
%得到单位条宽
module_width=sum/95;
%得到条空比
for i=1:59<pre name="code" class="plain">%% 条空换做0,1表示
function [decode]=dedecode_f(bar_width)
index=1;
for i=1:59
    if mod(i,2)==1
        for j=1:1:bar_width(i)
            decode(index)=1;
            index=index+1;
        end
    else
        for j=1:1:bar_width(i)
            decode(index)=0;
            index=index+1;
        end
    end
end

bar_width(i)=round(bar_width(i)/module_width);end

 

check_1.m

function is=check_1(decode)
if decode(1)&&~decode(2)&&decode(3)&&~decode(46)&&decode(47)&&~decode(48)&&decode(49)&&~decode(50)&&decode(95)&&~decode(94)&&decode(93)
    is=1;
    fprintf('起始符,中间分隔符,终止符正确\n')
else
    fprintf('起始符,中间分隔符,终止符错误,译码失败\n');
end

dedecode_f.m

%% 条空换做0,1表示
function [decode]=dedecode_f(bar_width)
index=1;
for i=1:59
    if mod(i,2)==1
        for j=1:1:bar_width(i)
            decode(index)=1;
            index=index+1;
        end
    else
        for j=1:1:bar_width(i)
            decode(index)=0;
            index=index+1;
        end
    end
end


decode_f.m

%% 一维码解码
function code=decode_f(decode)
left_num=size(6);
i=4;
%二进制转化为10进制得到前六个数
for index=1:6
    sum=0;
    for j=1:7
        sum=sum*2+decode(i);
        i=i+1;
    end
        left_num(index)=sum;
end
%得到后六个数
right_num=size(6);
i=51;
for index=1:6
    sum=0;
    for j=1:7
        sum=sum*2+decode(i);
        i=i+1;
    end
        right_num(index)=sum;
end
A=[13,25,19,61,35,49,47,59,55,11];
B=[39,51,27,33,29,57,5,17,9,23];
C=[114,102,108,66,92,78,80,68,72,116];
first_num=[63,52,50,49,44,38,35,42,41,37];
ahead=0;%前置符
%根据前6个十进制的到前置符
dec_left_num=size(6);
index=1;
for i=1:6
    isA=0;
    for j=1:10
          if A(j)==left_num(i)
             dec_left_num(index)=j-1;
             isA=1;
             break;
          end
     end
          if isA==0
              for j=1:10
                  if B(j)==left_num(i)
                        dec_left_num(index)=j-1;
                        break;
                  end
              end
          end
          ahead=ahead*2+isA;
          index=index+1;
      end
        for i=1:10
            if ahead==first_num(i)
                ahead=i-1;
                break;
            end
        end
        dec_right_num=size(6);
        index=1;
        for i=1:6
            for j=1:10
                if C(j)==right_num(i)
                    dec_right_num(index)=j-1;
                    index=index+1;
                    break;
                end
            end
        end
        %检验位
        a=ahead+dec_left_num(2)+dec_left_num(4)+dec_left_num(6)+dec_right_num(2)+dec_right_num(4);
        b=dec_left_num(1)+dec_left_num(3)+dec_left_num(5)+dec_right_num(1)+dec_right_num(3)+dec_right_num(5);
        c=a+3*b;
        c=mod(c,10);
        if c~=0
            c=10-c;
        end
        if c==dec_right_num(6)
            fprintf('校验位正确,译码成功\n');
        else
             fprintf('校验位错误,译码失败\n');
        end
        code=size(13);%译码结果
        code(1)=ahead;
        for i=1:6
            code(i+1)=dec_left_num(i);
            code(i+7)=dec_right_num(i);
        end


已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页