基于MATLAB的条码二维码识别系统

  1. 课题介绍

本设计研究的是基于数字图像处理的EAN-13条形码识别算法,通过工具平台MATLAB实现。其中图像处理部分是条码识别重要的前期工作,利用MATLAB强大的图象处理工具箱实现图像的读入、加噪仿真、滤波、二值化处理等工作,最终得到高质量的二值化图像。条码识别就是在二值图像的基础上实现,二值图像的质量直接关系到条码能否正确识读。

二、设计步骤与结果

2.1设计步骤

对于一个条码图像我们先要对其进行一定的处理才能达到正确译码的目的。而要对其进行处理,首先是要将其读入。由于有噪声的存在,必须对其进行滤波。也可以人为地加入一定类型的噪声仿真,然后用合适的滤波方法进行滤波,这样有助于理解各种滤波方法所针对的噪声类型。最后就是要二值化,得到二值图像。

条码图像预处理流程图如图1-7所示。

图2-1 条码图像预处理流程图

⑴ MATLAB中利用函数imread来实现图像文件的读取操作。图1-8是首次需要处理的条码图片。

图2-2 需要处理的条码

一般情况下,通过imread函数读取的大多数图像都是8位的。当把这些图像加载到内存中时,MATLAB就将其存储在类uint8中。此外,MATLAB还支持16位的PNG和TIFF图像。当用户读取这类图像时,MATLAB就将其存储在类uint16中。而对于索引图像来说,即使图像矩阵的本身为uint8或uint16,imread函数仍将颜色映射表读取并存储在一个双精度浮点类型的矩阵中。

例如:I=imread('008.bmp');

该语句可将条码图像读入内存,并以矩阵形式存储。

⑵ MATLAB的图像处理工具箱提供imnoise函数,可以用该函数给图像添加不同种类的噪声。该函数的调用格式如下:

J=imnoise(I,‘type’,parameters)

表1-3列出了imnoise函数能够产生的五种噪声及其对应参数。

表1-3 imnoise函数支持的噪声种类及参数说明

例如:J=imnoise(I,'salt & pepper',0.01);

该语句实现在条码图像I中加入椒盐噪声。

⑶ 条码图像被采集进入计算机,由于设备、以及传输过程中的各种因素的影响,一些噪声将会对图像的质量产生影响。任何一幅未经处理的原始图象,都存在一定程度的噪声干扰。不同的噪声干扰,处理方法不同。影响条码图像质量最典型的噪声是椒盐噪声。椒盐噪声的特点是此干扰在图像中是以孤立点的形式存在的。

针对噪声的类型,采用中值滤波。中值滤波是一种非线性信号处理方法。可以克服线性滤波器如最小均方滤波,平均值滤波(平滑滤波)等所带来的图像细节模糊。而且对于脉冲干扰及点状噪声有良好抑制作用,能较好保持图像边缘。它可以起到既消除噪声又保持图像细节的作用。

为了达到好的滤波效果应选择合适的滤波窗口。从条码图像的特征来讨论选择采用的中值滤波窗口。条码图像的特点在于是由纵向一定宽度黑白条空组成,我们建立不同大小的模板,对含有噪声的图像进行滤波处理,比较它们滤除噪声干扰的效果。

在MATLAB中可以使用imfilter函数或filter2函数调用创建好的滤波器(可以是预定义滤波器,也可以是自定义滤波器)对图像进行滤波。

指定了一个阈值T之后,将图像中的像素与阈值作比较,如果图像中某像素的灰度值小于该阈值,则将该像素的灰度值设置为0,否则灰度值设置为255。

按下式对图像进行处理可得到二值图像g(x,y):

在MATLAB中,通过使用函数graythresh和im2bw创建一个新的二值图像bw:

level=graythresh(L);

bw=im2bw(L,level);

根据上述译码理论,采用相似边距离测量方法对图1-8预处理后的条码图像(二值图像)进行译码,得到如下所示译码结果:

图2-3是第二张需要处理的条码图片。

图2-4 需要处理的条码

根据条码图像预处理的理论知识编译相关的MATLAB程序,得到如图1-10所示的图像预处理结果。

图2-5 条码图像预处理

得到如下所示译码结果:

2.2结果分析

误码率方面,一般情况下条码都能够正确识读。但在由一个字符的归一化的相似边距离

转换为

序列值

时,如果

的值为2.5、3.5、4.5之一,系统将不能正确的将其转换为

序列值,此时存在最大的误码率,条码几乎不能被正确识读。所以应该尽量避免此种情况的发生,这就要求我们做好图像的预处理工作,防止条码线条过度展宽或细化。

需要指出的是,在实际的译码中还存在着正向译码和反向译码的情况,两种情况下字符编码对应着不同的归一化值。因此译码前需要判别译码方向。本设计直接采用正向译码。最后,译码是编码的反过程,编码技术的熟练掌握对译码工作有着事半功倍的效果。

四、参考文献

[1] 邹永星.条码国家标准汇编[M].北京.中国标准出版社.2014:12-21

[2] 中国自动识别技术协会.条码技术基础[M] .武汉.武汉大学出版社.2018:15-16

[3] 黄红, 黄才骏.条码的奥秘[M]. 北京.中国铁道出版社.2010:69-72

[4] 王雅静.EAN-13 条码图像辨识方法的研究[D].青岛.山东科技大学.2013

[5] 唐莉,刘富强.条码国家标准汇编[M].北京.中国标准出版社.2014:11-25

[6] 百度文库

[7 薛红.条码技术及商业自动化系统-条码技术[M] .北京.中国轻工业出版社.2018:67-69

五、源程序

%function code = barcode(pic) %条形码识别

close all

check_left = [13,25,19,61,35,49,47,59,55,11;... %左边数据编码,奇

39,51,27,33,29,57, 5,17, 9,23]; %左边数据编码,偶

check_right = [114,102,108,66,92,78,80,68,72,116]; %右边数据编码

first_num = [31,20,18,17,12,6,3,10,9,5]; %第一位数据编码

bar = imread('123.bmp'); %读输入条形码图片

bar_Gray = rgb2gray(bar); %将RGB图片转换灰度图

figure(1)

imshow(bar)

title('条形码图')

figure(2)

subplot(121),imshow(bar_Gray),title('灰度图')

subplot(122),imhist(bar_Gray),title('灰度图直方图')

bar_Gray= imnoise(bar_Gray, 'salt & pepper', 0.02);

figure(3)

subplot(121); imshow(bar); title('原图像');

subplot(122); imshow(bar_Gray); title('添加椒盐噪声图像');

bar_Gray = medfilt2(bar_Gray); %进行3*3模板中值滤波

figure(4)

imshow(bar_Gray)

title('中值滤波之后图片')

%for i=1:m %对图像进行二值化处理

%for j=1:n

% if bar_Gray(i,j)>150 %选择适当的阈值进行二值化处理

% bar_10(i,j) = 1;

%else

% bar_10(i,j) = 0;

%end

%end

%end

[a_hist x] = imhist(bar_Gray);

hist_max = [];

if a_hist(1)>a_hist(2)

hist_max = [hist_max 1];

end

x = max(x);

for i=2:x

if a_hist(i)>a_hist(i-1) && a_hist(i)>a_hist(i+1)

hist_max = [hist_max i];

end

end

if a_hist(x)<a_hist(x+1)

hist_max = [hist_max x+1];

end

[m,n] = size(hist_max);

k = 0;

max_1 = 0;

max_2 = 0;

temp = a_hist(max_1);

a_hist(max_1) = 0;

k = 0;

for i=1:n

if k<a_hist(hist_max(i))

k = a_hist(hist_max(i));

max_2 = hist_max(i);

end

end

a_hist(max_1) = temp;

if max_1>max_2

k = max_1;

max_1 = max_2;

max_2 = k;

end

T = max_1;

k = a_hist(max_1);

for i=max_1:max_2

if k>a_hist(i)

k = a_hist(i);

T = i;

end

end

[m,n] = size(bar_Gray); %求灰度图的大小

for i=1:m %对图像进行二值化处理

for j=1:n

if bar_Gray(i,j)>T %选择适当的阈值进行二值化处理

bar_10(i,j) = 1;

else

bar_10(i,j) = 0;

end

end

end

figure(5)

imshow(bar_10);

title('二值化图')

l = 0; %检测59根条形码

for i=1:m

k = 1;

l = l+1;

for j=1:n-1

if bar_10(i,j)~=bar_10(i,j+1) %比较同一行相邻两点的颜色是否一致

%bar_x(l,k) = i;

bar_y(l,k) = j; %记录转折点的纵坐标

k = k+1; %准备记录下一个数据点

end

if k>61 %点数大于60,该行应该删掉

l = l-1;

break

end

end

if k<61 %点数小于60,该行应该删掉

l = l-1;

end

end

[m,n] = size(bar_y);

if m<=1 %查看条形码是否有效

code = '0';

fprintf(1,'GameOver!\n');

return

end

for i=1:m %计算每根条形码的宽度

for j=1:n-1

bar_num(i,j) = bar_y(i,j+1) - bar_y(i,j);

if bar_num(i,j)<0

bar_num(i,j) = 0;

end

end

end

bar_sum = sum(bar_num)/m; %求每根条形码宽度的平均值

k = 0;

for i=1:59 %计算59根条形码的总宽度

k = k + bar_sum(i);

end

k = k/95; %计算单位条形码的宽度

for i=1:59 %计算每根条形码所占位数

bar_int(i) = round(bar_sum(i)/k);

end

k = 1;

for i=1:59 %将条形码转换成二进制数

if rem(i,2)

for j=1:bar_int(i) %黑色条用1表示

bar_01(k) = 1;

k = k+1;

end

else

for j=1:bar_int(i) %白色条用0表示

bar_01(k) = 0;

k = k+1;

end

end

end

if ((bar_01(1)&&~bar_01(2)&&bar_01(3))... %判断起始符是否正确

&&(~bar_01(46)&&bar_01(47)&&~bar_01(48)&&bar_01(49)&&~bar_01(50))... %判断中间分隔符是否正确

&&(bar_01(95)&&~bar_01(94)&&bar_01(93))) %判断终止符是否正确

l = 1;

for i=1:6 %将左侧42位二进制数转换为十进制数

bar_left(l) = 0;

for k=1:7

bar_left(l) = bar_left(l)+bar_01(7*(i-1)+k+3)*(2^(7-k));

end

l = l+1;

end

l = 1;

for i=1:6 %将右侧42位二进制数转换为十进制数

bar_right(l) = 0;

for k=1:7

bar_right(l) = bar_right(l)+bar_01(7*(i+6)+k+1)*(2^(7-k));

k = k-1;

end

l = l+1;

end

end

num_bar = '';

num_first = 0;

first = 2;

for i=1:6 %从左边数据编码表中查出条形码编码数字

for j=0:1

for k=0:9

if bar_left(i)==check_left(j+1,k+1)

num_bar = strcat(num_bar , num2str(k));

switch first %记录左边数据的奇偶顺序

case 2

first = j;

break;

case 1

num_first = num_first + j*(2^(6-i));

break;

case 0

num_first = num_first + ~j*(2^(6-i));

break;

otherwise

break;

end

end

end

end

end

for i=1:6 %从右边数据编码表中查出条形码编码数字

for j=0:9

if bar_right(i)==check_right(j+1)

num_bar = strcat(num_bar , num2str(j));

end

end

end

for i=0:9 %从第一位数据编码表中查出第一位数字

if num_first==first_num(i+1)

num_bar = strcat(num2str(i) , num_bar);

break;

end

end

if numel(num_bar)~=13

fprintf(1,'Please Turn It Around!\n');

return

end

check_code = 0;

for i=1:12 %计算校验码

if rem(i,2)

check_code = check_code + str2num(num_bar(i));

else

check_code = check_code + str2num(num_bar(i))*3;

end

end

check_code = rem(check_code,10);

if check_code>0

check_code = 10 - check_code;

end

if check_code==str2num(num_bar(13)) %判断校验码是否正确

disp('识别出的条形码:')

code = num_bar

else

fprintf(1,'Please Turn It Around!\n');

return

end

基于MATLAB的条码二维码识别系统相关推荐

  1. 基于MATLAB的条形码二维码识别系统

    一.课题介绍 本设计研究的是基于数字图像处理的EAN-13条形码识别算法,通过工具平台MATLAB实现.其中图像处理部分是条码识别重要的前期工作,利用MATLAB强大的图象处理工具箱实现图像的读入.加 ...

  2. 基于主要成分分析的人脸二维码识别系统-含Matlab代码

    目录 一.引言 二.人脸图像信息处理 2.1 主成分分析PCA 2.2 PCA人脸压缩与重构算法分析 三.二维码转换以及识别 3.1 QR码 3.2 将人脸图像生成二维码 3.3 二维码的识别与图像还 ...

  3. 基于Android的二维码识别系统的研究与实现(eclipse开发)

    目 录 1 Android系统开发背景与意义 1 1.1 Android系统平台的出现 1 1.2 Android系统的发展 1 1.3 Android系统架构的介绍 1 1.4 Android开放系 ...

  4. 【第 07 章 基于主成分分析的人脸二维码识别MATLAB深度学习实战案例】

    基于主成分分析的人脸二维码识别MATLAB深度学习实战案例 人脸库 全套文件资料目录下载链接–>传送门 本文全文源码下载[链接–>传送门] 如下分析: 主文件 function varar ...

  5. 基于springboot的食品二维码溯源系统

    1 简介 今天向大家介绍一个帮助往届学生完成的毕业设计项目,基于springboot的食品二维码溯源系统. 计算机毕业生设计,课程设计需要帮助的可以找我 2 设计概要 21世纪是信息化时代,随着信息技 ...

  6. 基于halcon的简易二维码识别

    二维码识别 原图 代码 结果 原图 代码 dev_update_off () dev_close_window () read_image (Image, '111.png') get_image_s ...

  7. 【毕业设计】深度学习二维码识别系统 - python opencv

    文章目录 0 前言 2 二维码基础概念 2.1 二维码介绍 2.2 QRCode 2.3 QRCode 特点 3 机器视觉二维码识别技术 3.1 二维码的识别流程 3.2 二维码定位 3.3 常用的扫 ...

  8. 基于Halcon学习的二维码识别【七】2d_data_codes_rectify_symbol.hdev

    这个程序演示了如何通过校正预处理来读取倾斜的二维码 总代码: *更新状态设为off dev_update_off () dev_close_window ()* Get the image and d ...

  9. 基于Halcon学习的二维码识别【一】micro_qr_simple.hdev

    此示例程序演示如何读取符号类型为"Micro QR Code"的二维数据代码.在第一步中,创建一个数据代码模型.在下一步中,将读取数据代码,并在图形窗口中显示结果. 请注意,有些符 ...

最新文章

  1. poj2387(Dijstra算法)
  2. 服务器可视化_系统管理员不可错过的6款服务器监控工具
  3. JVM调优:CMS使用的算法
  4. python3 array为什么不能放不同类型的数据_小白入门Python数据科学全教程lt;一gt;...
  5. svg矩形参数_SVG矩形和其他SVG形状
  6. MySQL check table/optimize table/analyze table/REPAIR TABLE
  7. 计算时间差_小王子是怎么用四步法进行时间计算并成功避开日界线的
  8. 手绘平面设计邮票插画素材,复古元素走起
  9. qtplaintextedit如何删除内容_YouTube:如何删除油管频道Channel
  10. Android View 的scrollTo 和 scrollBy方法
  11. java基础 题和知识点总结, 关于String s是否默认初始化为null......,new一个对象和类静态域,是不是在内存中不是一个地方...
  12. JAVA:实现Gaussian高斯算法(附完整源码)
  13. 8.0强行转换后变成了7_南方Cass软件坐标转换方法!
  14. 【python 生成自己的二维码】推广二维码带log图片
  15. 3台服务器+StarVCenter,搭建“超融合云平台”-完美体验-跑100台虚拟机
  16. 001] 智能手机操作系统介绍
  17. iframe在html中怎么写,html中如何使用iframe标签链接网址呢?
  18. 利用 tesseract 自动识别图片中的文字
  19. 利用FFmpeg玩转Android视频录制与压缩
  20. python是一种编程语言吗?,python语言是编程语言吗

热门文章

  1. android 蓝牙和wifi存在冲突
  2. 实在腾不出手来还好可以刷脸支付
  3. Opencv 环境配置
  4. 母亲将患感冒婴儿扔下楼后跳楼(图)
  5. speedoffice如何隐藏界面的状态栏
  6. 大矩阵的分块乘法及matlab实现
  7. 小米折叠手机售价、发布时间曝光
  8. 巧用Superset大数据分析平台搞定各类图表
  9. 大数据前景和就业方向又是什么样的呢?
  10. DS树结构转换(先序转双亲)