一维条码解码

来源:互联网 发布:windows hadoop_home 编辑:程序博客网 时间:2024/04/29 17:00

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

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

EAN-13解码:

EAN-13码结构


解码流程:

一维条码解码matlab代码

function [code]=one_dimensional_codeself(img)%% 图片的读取f=imread(img);% read figureg=rgb2gray(f);  %turn to gray figurefigure(1);imshow(g);title('原图像');[M,N]=size(g);%% 图片的处理T=graythresh(g)*255; %get thresholdg= Thresholding(g,T); %二值化%% 噪声过滤g=medfilt2(g); %filterfigure(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');endfigure(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    endend

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    endend

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    endendleft_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;    endendright_sum=0;for i=m:-1:1    if(kk(i)==61)        for j=1:10            right_sum=right_sum+kk(i+j);%同上        end        break;    endendif 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);endsum=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    endend

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    endend


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;endA=[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

2 0
原创粉丝点击