1.一维码简述;
一维条码是一种能用于信息编码和信息自动识别的标准符号,是由一组宽度不同的黑白符号按一定规则交替排列编码组成的图形符号,用于表示一定的信息。
码制指条码符号的类型,不同的类型有不同的编码规则。我们本次实验是基于EAN-13码制。EAN-13码主要由起始符(3)、左侧数据符(42)、中间分割符(5)、右侧数据符(42)、校验符、终止符(3)组成,一共95个模块,表示13个字符。条表示1,空表示0;只能表示0-9这十个数字;每个字符的宽度为7个模块,交替由两个条和两个空组成,每个条或者空的宽度不超过4个模块。起始符101,中间分割符01010,终止符101.
我完成的这个识别程序能解析的条码类型包括标准、受噪声污染以及倾斜的一维码图像。
2.解码方法(分为图像处理和译码两个部分);
2.1 图像处理
2.1.1 用imread()方法载入需要验证的一维码图像;
2.1.2 将载入的RGB三通道图像转化为灰度图像,每个像素点取值范围为0-255,共有256个灰度级别。用rgb2gray()函数可得到灰度图:
2.1.3 用大津法求阀值进而从灰度图像得到二值图,二值图的像素点取值范围不是0就是1,利于我们后续的译码操作.求阀值用graythresh()函数,求二值图用im2bw()函数:
2.1.4 接下来可以对图像进行滤波去噪以及图像校正,这一部分将在后文详细描述。这里先只讨论标准一维码的图像。
2.2 译码
2.2.1 获取条和空的宽度:这里的思路是遍历图像的每一个像素点,在一行中,当遇到像素值与其后一个点像素值不等的时候,记录其位置;后面的位置减去前面的位置,既可以得到条或空的宽度。对于一张标准的一维码图像,边界区域有60个,所以每一行应该有59个条/空的宽度值,当某一行的宽度值不等于59时,忽略该行。同时在这一步做了一个优化操作:由于得到的二值图中的条码的边界可能会出现锯齿和毛刺等现象,这就导致每次计算的宽度可能不一样,减少这个误差的方法是将所有有效行(59个宽度)的宽度相加后取平均值。相关代码如下:
1 [m,n]=size(A); 2 3 number=0; 4 5 for i=1:m 6 7 pos_cnt=1;width_id=1; 8 9 for j=1:n-1 10 11 if A(i,j) ~= A(i,j+1) 12 13 pos(i,pos_cnt)=j; 14 15 if pos_cnt>1 16 17 width(i,width_id)=pos(i,pos_cnt)-pos(i,pos_cnt-1); 18 19 width_id=width_id+1; 20 21 end 22 23 pos_cnt=pos_cnt+1; 24 25 end 26 27 end 28 29 if width_id==60 30 31 number=number+1; 32 33 for k=1:59 34 35 %将所有条/空的宽度都存储在total_len这个二维数组里 36 37 total_len(number,k)=width(i,k); 38 39 end 40 41 end 42 43 end 44 45 end 46 [mm,nn]=size(total_len); 47 for i=1:nn 48 tmp=0; 49 for j=1:mm 50 tmp=tmp+total_len(j,i); %该宽度的所有值求和 51 end 52 final_width(1,i)=tmp/mm; %求均值 53 end
2.2.2 获取单位模块宽度以及条空比例: