• 、概念条形码由宽度不同、发射率不同的条(黑色)和空(白色)组成。按照特定的编码规则编制,用来表达组数字、字母信息的图形标识符。 工业25码 EAN-13码 为什么用黑色、白色来表示条形码? 因为...

    最近在学习的内容之一,整理一下,图片均为网络图片。提及的条形码主要为EAN-13码。

    一、概念

    条形码由宽度不同、反射率不同的条(黑色)和空(白色)组成。按照特定的编码规则编制,用来表达一组数字、字母信息的图形标识符。
    工业25码
    在这里插入图片描述
    EAN-13码
    在这里插入图片描述
    为什么用黑色、白色来表示条形码?
    因为两种颜色有截然不同的反射率,众所周知,黑色吸收光中的所有颜色,白色反射光中的所有颜色。当然,也可以用其他两种颜色来表示条形码,只要两种颜色有不同的反射率,足够的对比度。

    二、EAN-13码

    EAN-13码是EAN码的一种,用13个字符表示信息,是我国主要采取的编码标准。EAN-13码包含商品的名称、型号、生产厂商、所有国家地区等等信息。
    EAN码是模块组合型条码。
    模块:组成条码的基本宽度单位。说白了,条形码上,每0.33毫米宽代表一个模块。一个模块宽的条(条形码黑色部分)表示二进制“1”,两个模块宽的条(黑)表示二进制“11“,一个模块宽的空(条形码白色部分)表示二进制”0“。
    这样,便可以用二进制的0、1表示信息。在EAN码上,每一个字符(例如:数字1),由两个条(黑)和两个空(白)组成,条和空又分别由1~4个同宽、同颜色的模块组成。每个字符总共有7个模块(宽),并规定每个字符从外观上包含两个条、两个空。所以EAN码又称(7,2)码。
    一个字符:c1表示条的宽度(模块),c2(空),c3(条),c4(空) (c1+c2+c3+c4=7)
    在这里插入图片描述
    EAN-13码的格式如图:
    在这里插入图片描述
    以上节EAN-13码例图来说明
    501(制造码),2345(制造商代码),67890商品标识代码,0(校验码)。
    注意:EAN-13码,在以图形标识符表示时,第1位(例:上图数字”5“)隐式表示,既不用条和空(表示),而用第2位~第7位(总六位)的奇偶性来隐式表示(后面会说)。

    现在,第一位用隐式表示,那么只需要表示13-1=12个字符,将12个字符,分成两半,左侧6个字符,右侧6个字符。
    左侧字符有奇偶性,右侧字符全是偶的。左侧的奇偶性取决于 隐式表示的第一位字符(前置符,即:EAN-13码格式中的F1)。具体奇偶性如图:E代表偶数位,O代表奇数位,如前置符0表示,左侧六个字符都是奇数位。
    在这里插入图片描述
    那么奇、偶数位有什么用呢?
    相同字符在偶数位、和奇数位的二进制表示是不一样的。如图:
    在这里插入图片描述

    校验码有什么用?
    EAN-13码最后一个字符是校验码,用来保证条形码识别的正确性。
    EAN-13码校验算法如下:
    (1)从右至左,将13个字符按顺序排序。
    (2)第2、4、6、8、10、12等偶数位的数据相加,将结果乘以3,得到P.
    (3)将3、5、7、9、11、13等奇数位数据相加,等N。
    (4)N+P得 M
    (5)用M除以10,取余数。求余数以10为模的补数 C。
    (6)若C与 校验码 数值相等,则译码正确。

    EAN-13码识别原理

    在这里插入图片描述
    如图,表示条形码的一个字符。
    C1,C2,C3,C4表示该字符中四个相邻的条(黑)或空(白)的宽度,T是一个字符的宽度。C1+C2+C3+C4=7(模块)
    用n表示一个模块的宽度,n=T/7。
    用mi=Ci/n,i=1,2,3,4,便可以得到编码。
    若m1=1,m2=3,m3=1,m4=2,且条码排列位条——空——条——空,则当前字符二进制编码为 1 000 1 00,是右侧偶字符“7”。
    这种方法只是最基本的识别方法,当条空间距较小,或印刷质量不好时,很容易识别错误。
    条形码识别的方法还有许多,网上有许多资料,有兴趣的朋友可以自行学习。

    相关系列

    展开全文
  • 数字图像处理 包涵条形码识别全过程 自己的代码 可以帮助熟悉条形码和bmp文件
  • 基于数字图像处理条形码识别方法 条形码识别方法 适合学习数字图像处理的同学看
  • 基于MATLAB的一维码识别系统,对损坏的条码图像时执行光电软仿真,识别率很高。
  • 以下为一个示意图,一维条形码一共有如下几个区域组成(其实一个条形码下面已经给出了代表哪些数字了,我写的这篇文章讲述其原理,教机器如何读取)     首先明白如下几点: 一、条码的黑色条表示二进制的1...

    这里我随便在我的编译原理这本书后面拍的一个条形码来进行说明

    以下为一个示意图,一维条形码一共有如下几个区域组成(其实一个条形码下面已经给出了代表哪些数字了,我写的这篇文章讲述其原理,教机器如何读取)

     

     

    首先明白如下几点:

    一、条码的黑色条表示二进制的1,白色代表0,而且0.33mm宽度的黑色或者白色条为一个基本的二进制位,下面可以看出有的黑色条很宽,说明连着好几个二进制1,下面这个图是上面那个图的放大。

    二、一维条形码只能表示数字,不能表示字母符号和汉字,每个数字由7个二进制位组成,而且这些二进制组成的规则不是ASCII码,而是自己的一套编码规则,比如 0000 101,这个表示的不是数字5(ASCII码表示的就是5),应该按照官方给的如下编码表进行解码,查找下面的表发现是左侧数据符的偶性字符(B组)中的6。起始符,终止符编码为101,分隔符编码为01010(没有为什么,官方规定的,如果哪天你发明了啥,你就是官方,你想咋规定就咋规定)

     

    三、可以数一下上面的两个条形码,一维条形码都是由13个数字(是1 2 3。。。这样的数字,不是二进制0 1 0 10这样的数)组成,分别代表如下的意思,:前三个数:制造码,接着四个数:制造商代码,接着五个数:商品标识代码,最后一个数:校验码

    比如第二张图片条形码是692 0152 46102 0,

    692(制造码),0152(制造商代码),46102商品标识代码,0(校验码)可以用来防伪以及识别校验

    而第一个数字(被称为前置码)是隐藏的,不占用黑条白条来表示(由后面数字的奇偶性来推断出,这个是官方规定的规则,后面我会进一步解释其原因),所以扣掉一个数字,总的只有12个数字(左侧数据符6个+右侧数据符6个),刚刚我说了一个数字由7个二进制位组成,每一个二进制位由一个黑条或者白条来表示,而每一个条的宽度为0.33mm,所以这里可以计算一下:

    (13-1)*7+11 = 95个黑色或者白色的单位宽度0.33mm的条,其中的11个二进制位是起始符,终止符编码为101,分隔符编码为01010,总共占掉11个黑色或者白色的条

    95*0.33 = 31.35mm = 3.135cm,你可以用尺子量一下你所看到的一维码,总的宽度是不是这么宽

    四、上面这个官方EAN-13编码表是最常用的一维码编码方式,我们认真观察一下会发现,同一个数字竟然有三种编码方式,而且每一个编码结果都对应唯一的一个数字(你在上面找不出重复的两个二进制串对应同一个数字),也就是编码是唯一的,只要随便给我一个二进制串0001011,对比上面的表就可以唯一确定对应的是左侧奇性字符A组的9,这个数字。但是你给我一个数字9,我却不能唯一确定他对应的是哪个二进制串,因为有三种编码方式,上表可以找出0001011,0010111,1110100三个二进制串与之对应。这个意思就是解码出数字是唯一的,但是逆回去却不是唯一的,不过没关系,我们条形码代表的就是一个二进制串,需要的仅仅是解码就行了,所以解码出来的每个数字一定是唯一的。

    五、刚刚说的第一个数字为啥是隐藏的,可以直接由后面数字的奇偶性推断出来,以及与刚刚那个解码表的三种编码方式有什么联系,为什么每个数字要规定三种二进制串的编码方式从而搞得这么麻烦,接下来揭开它的神秘面纱:

    再来看看这张图,图中用黑或者白条能表示的数字,真正的其实只有12个数字(左侧数据符6个,右侧数据符6个),第一个前置码6这个数字实际上是由 左侧数据符6个数的奇偶性推测出来的,这个具体什么意思呢

    比如刚刚上面图片条形码是692 0152 46102 0,

    692(制造码),0152(制造商代码),46102商品标识代码,0(校验码)可以用来防伪以及识别校验

    这里第一个6就是前置码,920152称为左侧数据符,461020称为右侧数据符。而你如果用扫描枪扫描这个条形码,实际上获得的只是92 0152 46102 0这12个数,那为啥就能得到前置码6,最后得到最终的一维码为692 0152 46102 0的呢,实际上这里的前置码6就是由左侧数据符920152的奇偶性推断出来的,首先指明一个误区,不是指9奇数,2偶数,0偶数...这样的奇偶性,而是指下面这个表1 EAN-13编码强制规定的奇偶性(其实不是啥奇偶性,就是官方搞了这么一个名字,我觉得有点误导人),来看看这个表,我们可以得出,左侧数据符分为奇性字符,偶性字符两种,而右侧数据符都被规定为偶性字符了。我们来看看扫码枪的执行过程吧:扫码枪一次性“滴”扫完了整个条形码,实际上是串行的,慢动作来看就是,从这边第一个黑条一个一个往右边扫描,直到扫完这95个条(指的是单位宽度0.33mm的条,很宽的黑色条是包含了好几个黑条)。那么扫到的这些条,按照组成规则,会自动去掉起始符,中间分隔符,终止符,剩下了真正有用的条。现在前7个条(黑条代表二进制1,白条代表0)就会根据下面这个表EAN-13查找出对应的字符,并记录其左右性和奇偶性,

    除开前置码,现在前7个条是 白,白,白,黑,白,黑,黑(注:这里所说的白,黑条指的是单位宽度0.33mm的条,你看到的很宽的黑条实际上是由好几个单位宽度的黑条组成的,也就是会解析出来好几个连着的二进制1)。

    也就是0001011,从上图中也能清清楚楚看出就是0001011,查下面的表发现对应数字9(当然条形码下面也直接标出了9,但是扫码枪不知道,他只能识别黑条,白条),那么再看他属于的类,发现它属于左侧数据符,而且是奇性字符(注:和9是奇数没有任何关系),我们再看看,因为我们的扫码枪是顺序扫描(从左往右扫描),那前六个扫到的当然就属于左侧字符啦,这里我们跟我们查表出来是左侧数据符相吻合了,就说明完全正确了,我们的扫码枪或者一维码没有拿反(其实官方这个表之所以这样规定,就是可以判断扫描正反,防止扫描错误)。同时从这个表我们记录下这个字符9属于奇性字符。接下来我们继续往右扫描,得到0011011,查表发现是左侧偶性字符2,仍然是左侧字符,吻合,而且记录下他的奇偶性为偶性,再继续向右扫描得到。。。。。。

     

    扫描完左侧字符的42个条码后(每个字符由7个条码组成,左侧字符总共有6个,总的就是42个条码),得到了六个字符920152后,同时得到了这六个字符的奇偶性(注:这里说的奇偶性不是指数字本身的奇偶性,而是上面官方表中强行规定的奇偶性),比如是,奇,偶,偶,偶,奇,奇,然后再查下面的表2,发现对应的前置码为6(o代表奇性,E代表偶性)。所以我们的扫码枪扫描得到6个数,然后又推导出了第一个前置码,所以就得到了7个数6920152,然后同理再扫描右侧数据符6个数就行了,只是不需要记录奇偶性了,因为我们已经不再需要推导啥数字了(而且从上面的表可以看出,右侧数据符都被强行规定为偶性字符了),扫描右侧字符得到461020,所以现在总的一维码就是6 920152 461020,ok总的一维码识别以及结束了,剩下了就是查数据库692(制造码,),0152(制造商代码),46102商品标识代码,0(校验码)可以用来防伪以及识别校验,跟数据库进行对比,得到到底属于哪的制造码,哪家制造商,属于哪个商品了呀。对了这里校验码的作用讲一下,是最后一个数,用于判断读取是不是正确的,就是判断这个一维码是否被人恶性破坏了,或者扫码枪自己坏了等等情况。

    注:从上面这个编码表可以看出,每个数字都是由0..1..0....1或者1..0..1.0这样子组成的(黑条代表1,白条代表0),

    也就是说明每个数字一定有两个交错黑条和两个交错排列的白条组成,这是官方规定的,没有为什么,可以仔细观察你所看到的一维码,一定是这样的规则

    总结:一维码读取过程如下

    1、扫码枪利用一维码上面白和黑条的不同反光率,射出的红色光线得到不同的反射强度,然后利用光电传感器转为电信号,滤波放大后转为数字信号0,1。每个数字由7个黑色或者白色单位宽度的条组成。当然你可以用摄像头拍摄然后图像处理方式进行一维码中0,1的提取也是可以的

    2、从左往右扫描得到左侧6个数字,同时根据编码表给出的奇偶性推导出第一个前置码为多少,再扫描右侧数据符6个,得到了总的13个数据符

    2、这13个数字里面包含了产品的重要信息,跟数据库进行对比得到产品的生产商,产品名称等信息

    我在写这篇文章之前也是参考了很多的文章,其实我觉得讲得都不直观,很多重要点都没能通俗表述出来,我也是参考那么多文章加上自己的理解,写出的这篇目前为止最为通俗易懂的文章了

    展开全文
  • 条形码的识别在日常生活中应用最广泛,本文提出来新的条形码识别方法,简单,方便,利用halcon实现。
  •  本设计研究EAN13条形码识别的译码技术,在基于机器视觉技术上,构建了一套条形码在线检测识别系统,系统将由以下几个部分构成:条形码图像定位与采集、计算机图像预处理、条形码图像中值滤波去噪、条码解析与识读...

    基于机器视觉技术的条形码在线识别系统设计

      本设计研究EAN13条形码识别的译码技术,在基于机器视觉技术上,构建了一套条形码在线检测识别系统,系统将由以下几个部分构成:条形码图像定位与采集、计算机图像预处理、条形码图像中值滤波去噪、条码解析与识读。经过实验,确定该系统可对绝大部分EAN13条形码进行快速并准确的识读。

    关键词: 机器视觉; 图像处理; 条码识别;在线检测;EAN13条形码;QT

    一:设计目标 

    1. 掌握条形码识别原理;
    2. 熟悉条形码识别的概念,发展现状;
    3. 熟悉机器视觉系统设计的一般流程;
    4. 掌握常用图像处理技术;

     设计内容与要求

    1.完成基于机器视觉技术的条形码在线识别系统算法设计;

    2.完成基于机器视觉技术的条形码在线识别系统上位机设计;

    3.EAN13条形码识别误差率≤2%;

    二:qt程序

     三:条形码定位算法

    #include <opencv2/opencv.hpp>
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include<iostream>
    #include<stdlib.h>
    using namespace cv;
    using namespace std;
    int main()
    {
        Mat Img,grayImg,gradx,blurgradx,gradAbsx,threshImg,close_threshImg,erode_threshImg,dilate_threshImg;
        Img=imread("E:\\txm1.jpg");
        imshow("0原图",Img);            
        cvtColor(Img,grayImg,COLOR_BGR2GRAY);
        imshow("1灰度图",grayImg);
        Scharr(grayImg,gradx,CV_16S,1,0);
        imshow("2边缘检测图",gradx);
        convertScaleAbs(gradx,gradAbsx);
        imshow("3Abs图",gradAbsx);
        blur(gradAbsx,blurgradx,Size(5,5));
        imshow("4滤波图",blurgradx);
        threshold(blurgradx,threshImg,150,255,CV_8UC1);
        imshow("4.5阈值分割图",threshImg);
        Mat kernal=getStructuringElement(MORPH_RECT,Size(25,5));
        morphologyEx(threshImg,close_threshImg,MORPH_CLOSE,kernal);
        imshow("5闭操作",close_threshImg);
        Mat edkl=getStructuringElement(MORPH_RECT,Size(3,3));
        erode(close_threshImg,erode_threshImg,edkl,Point(-1,-1),8);
        imshow("6腐蚀操作",erode_threshImg);
        dilate(erode_threshImg,dilate_threshImg,edkl,Point(-1,-1),15);
        imshow("7膨胀操作",dilate_threshImg);
        waitKey(0);
        return 0;
    
    }

     

    四:程序运行及条形码识别测试

     

     

     

     详细代码:https://github.com/hhhvvvddd/Bar-Code-Recognition-System

    定位算法:https://www.cnblogs.com/fpzs/p/9637795.html

     

    ——————

    浅谈则止,深入理解AI大道理

    扫描下方“AI大道理”,选择“关注”公众号

                  欢迎加入!

    转载于:https://www.cnblogs.com/fpzs/p/10513497.html

    展开全文
  • 条码图像处理过程  图像的大致处理流程如下:  1. 将彩色图转变成灰度图  2. 对灰度图均衡化  3. 将灰度图转换成二值图  4. 对二值图进行腐蚀  5. 识别边界检测轮廓  6. 对每个轮廓包围的...

    一. 条码图像处理过程

            图像的大致处理流程如下:

             1. 将彩色图转变成灰度图

             2. 对灰度图均衡化

             3. 将灰度图转换成二值图

             4. 对二值图进行腐蚀

             5. 识别边界检测轮廓

             6. 对每一个轮廓包围的区域进行特征识别,判断是否是条码区域。

             7. 对条码区域测量解码。

     

     

    二.代码解读

     

    bool TestBarCode()

    {

             InitCodeMap();

     

        IplImage* src = cvLoadImage(strPictureName,0);                  //装载图像                                                               

        if( !src )

             {

                       printf("打开文件失败,请重新打开");                  //读取失败返回

                       return false;

             }

            

             cvNamedWindow("src",1);

             cvShowImage("src",src);

     

            

        IplImage * dst = cvCreateImage( cvGetSize(src), 8, 1 );         //创建图像

        IplImage * dst1 = cvCreateImage( cvGetSize(src), 8, 1 );//创建图像

     

             //进行图像平滑,并转成灰度图像

             cvSmooth(src,dst1,CV_BLUR,3, 3);  

             Process(dst1);    //处理的核心在这

     

        cvWaitKey(0);                      //等待按键

     

             //释放图像分配的内存

             cvReleaseImage(&src);    

             cvReleaseImage(&dst);             

             cvReleaseImage(&dst1);

     

             cvDestroyWindow("src");

             cvDestroyWindow("dest");

             cvDestroyWindow("cpImg");

     

             return true;

    }

     

    这段代码是处理的主代码,对图片载入并平滑处理。然后调用了Process函数做进一步处理。

     

    //型体分割,获取感兴趣的区域

    void Process(IplImage * pImg)

    {

             //转换成二值图

             IplImage * dst = cvCreateImage( cvGetSize(pImg), 8, 1 );

             cvThreshold(pImg,dst,100,200,CV_THRESH_BINARY_INV);//将灰度图转成二值图

             cvNamedWindow("ThImage",1);

             cvShowImage("ThImage",dst);

     

             //膨胀

             IplImage * dst2 = cvCreateImage( cvGetSize(pImg), 8, 1 );

             IplConvKernel * element = cvCreateStructuringElementEx( 5, 5, 1, 1, CV_SHAPE_ELLIPSE, 0);

             cvDilate(dst,dst2,element,3);//图像膨胀

     

             cvNamedWindow("DilateImage",1);

             cvShowImage("DilateImage",dst2);

     

             //检测轮廓

             CvMemStorage * storage = cvCreateMemStorage(0);

        CvSeq * contour = 0;

        int n = cvFindContours( dst2, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);

            

             double maxArea = 20;

             IplImage* pContourImg = cvCreateImage(cvGetSize(dst2), IPL_DEPTH_8U, 3);

             //初始化为黑色

             cvZero(pContourImg);

     

             int k = 0;

             while(contour)

             {    

                       double area=fabs(cvContourArea(contour, CV_WHOLE_SEQ)); //求轮廓包含的面积   

                       if(area > 100) //当面积小于100时的忽略

                       {

                                if(k++ < 8)

                                {  

                                         cvDrawContours(pContourImg,contour,cvScalarAll(255),cvScalarAll(0),0,CV_FILLED);

                                         CvRect rect = cvBoundingRect(contour,1); //获取外接矩形

                                         cvRectangleR(pContourImg,rect,CV_RGB(0,255,0));  //绘制外接矩形

     

                                         CvBox2D box = cvMinAreaRect2(contour,NULL);  //求取轮廓最小的外接矩形

                                         IplImage * cpImg = CreateAndCopyBox2D(dst,box);

                                         if(cpImg)

                                         {

                                                   if(FutrueFind(cpImg))

                                                   {

                                                            string str = DecodeImage(cpImg);

                                                            cvNamedWindow("cpImg",1);

                                                            cvShowImage("cpImg",cpImg);

                                                   }

                                                   else cvReleaseImage(&cpImg);

                                                           

                                         }

                                }  

                       }

                       contour=contour->h_next;

             }

             cvReleaseMemStorage(&storage);

    }

     

    Process是核心处理代码,首先对图像进行了二值化,这样能去除更多的干扰。二值化是使用了CV_THRESH_BINARY_INV参数,对图像中黑白色反转。这样条码部分呈了白色。然后对其膨胀,膨胀的目的是将条码说在的整个区域编程白色,之后的轮廓识别能将其划分在一个轮廓里。

    cvFindContours查找了轮廓,将其保存在contour列表之中。之后就是遍历整个列表,遍历时,首先使用cvMinAreaRect2对每一个轮廓求取其最小外接矩形,他返回一个CvBox2D数据,其中包含有矩形的大小,中心点坐标,还有一个角度。利用这个角度可以可以知道条码型位信息,这个角度就是对裁剪后的感兴趣区域旋转的角度。

    CreateAndCopyBox2D对遍历的每个区域进行了裁剪和旋转。这样就得到了型位是正位的区域图片,之后要做的事情就是识别图片特征,判断是否是条码区域,若是就会对图片的解码。

     

    FutrueFind承担了图片特征识别的任务。

    //特征识别,找到条码区域

    bool FutrueFind(IplImage * pImg)

    {

             double max = 0;

             double min = 0;

     

             vector<double> ds;

             HistY(pImg,ds);

             double avgY = DataAvg(ds);

            

             ds.clear();

             HistX(pImg,ds);

             double avgX = DataAvg(ds);

     

             if(avgX/avgY > 5)return true;

     

             return false;

    }

     

    特征识别是一个图形处理系统的核心技术。这里使用了简单的特征识别,目前还不是很健壮。在一维条码的x,y方向上强度特征会有所不同,首先统计出X和Y方向的强度值,然后求取相邻强度值差值的绝对值,在对这些值求平均值。这样得到了avgY和avgX,经多个条码观察发现avgX都在avgY的5倍以上。

     

     

    string DecodeImage(IplImage * pImg)

    {

             vector<int> ds;

             double color = 0;

             int h = pImg->height/2;

             for(int i = 0; i<pImg->width; i++)

             {

                       double d = cvGet2D(pImg,h,i).val[0];

                       if(0 == i)color = d;

                       else

                       {

                                if(abs(color -d) > 100)

                                {

                                         ds.push_back(i);

                                }

     

                                color = d;

                       }

             }

     

             printf("decode size :%d\n",ds.size());

     

             //计算宽度系列

             vector<int> wids;

             double w = 0;

             for(int i = 0; i<ds.size(); i++)

             {

                       double d = ds[i];

                       if(0== i)w = d;

                       else

                       {

                                wids.push_back(d - w);

                                w = d;

                       }

             }

             wids.pop_back();

             printf("width size :%d\n",wids.size());

     

             int min = FindMin(wids);

             vector<int> tgs;

             DevTh(wids,tgs,min);

     

             string code = Getcode(tgs);

     

             printf("code :%s\n",code.c_str());

             return code;

    }

     

    DecodeImage函数解码条码,他基于像素为单位对条码宽度测量,再找出最小宽度,之后再将其转换成条码识别的标注序列,和编码表比较获得条码值。

    展开全文
  • 条形码识别图像算法

    2020-06-13 08:45:04
    基于数字图像处理的ENA-13条码识别
  • 然后通过运用数字图像处理算法实现了对商品条形码区域的定位。最后针对手机等设备拍摄的条形码图像因光线不足导致分辨率较低和大量的噪声、设备的抖动导致的图像模糊、拍摄角度的原因导致的视角倾斜等问题,我们提出...
  • 本设计为基于MATLAB的条形码识别系统,带有个GUI界面。 1.1.1 程序总体设计思路 在上节中我们简单的介绍了MATLAB的发展以及优点。在以后的章节中将阐述如何应用MATLAB编程实现对条形码的识别。在这一节中将主要介...

    源码:https://download.csdn.net/download/weixin_38719187/12135715
    1.1 应用MATLAB识别条形码总体设计
    本设计为基于MATLAB的条形码识别系统,带有一个GUI界面。
    GUI设计
    1.1.1 程序总体设计思路
    在上节中我们简单的介绍了MATLAB的发展以及优点。在以后的章节中将阐述如何应用MATLAB编程实现对条形码的识别。在这一节中将主要介绍编程的总体思路。
    首先将含有条形码信息的图片读入到MATLAB中去,这个图片将以矩阵的形式存储在MATLAB中。这样,我们就能通过对矩阵的运算来实现对图片的处理。由于条形码一般都是黑白的,这样我们的第一步就是要把图片行二值化处理,用于去除那些不需要的细节。然后就要确定条形码所在的位置。这一步至关重要,如果定位不准确,我们就不能获取条形码所有的信息,以至于不能准确的识别。找到条形码准确位置后。就要对条形码信息提取,然后在按照比例将提取到的条形码信息转换成标准模块组成的条形码。最后通过相应的译码得到条形码中的数字,判别是否正确后输出,这样就完成了条形码识别的整个过程。
    预处理
    图像处理的结果

    1.1.2 程序总体设计流程图

       主程序的流程图可以用图4-1来表示。
    

    流程图
    图4-1主程序流程图

    1.3 各部分子程序说明
    上一节中我们分析了条形码识别的主体设计思路,在本节中我们将介绍程序各部分的作用以及实现方法。
    1.3.1 读入图片并二值化处理
    在这个步骤中,我们的主要任务是把含有条形码信息的图片文件放到MATLAB的工作区中去。当图片经过imread命令后,MATLAB会给图片开辟一个存储空间,把图片各像素点的值储存到一个矩阵中。读入图片格式一般都是 .jpg, . bmp,等格式,这样格式的图片每一个点都有其相应的R、G、B值,这不仅增大了MATLAB的运算量,而且还大大降低了识别的准确性。
    这就要求我们先对图像进行二值化处理。因为条形码在正常情况下是黑白的。这种方法可以去除与条形码不相关的信息,这些信息对条形码的识别是不起作用的。这样既可以提高效率,又可以提高准确性。
    图4-2和图4-3表示了二值化前后两个图像的对比。通过对比我们发现,二值化后图像更加简洁,我们需要的条形码符号更加清晰,容易进行识别。这也为我们以后的识别工作做了很好的铺垫。

    1.3.2条形码的定位
    上一个过程结束后,存储在MATLAB中的信息只有‘0’和‘1’,其中图像中黑色的部分用‘0’表示,白色部分用‘1’表示。

    灰度二值图像处理
    图4-2 二值化前的图片 图4-3 二值化后的图片
    所谓条形码的定位就是找到条形码的确切位置,这样我们才能够到相应位置去提取条形码信息。由于条形码的前后都有9个模块的空白区,这些知识我们在第二章中我们已经做了详细的介绍。所以我们可以通过条形码前面的空白区来定位条形码,如果我们找到条形码前面空白区也就完成了对条形码的定位。
    假设我们定义条形码中每个模块所占的像素数为4,那么条形码空白区在水平方向上总共占的像素数为36。在竖直方向上每个条形码的长度都是不同的,但大约都是水平宽度的4~5倍。考虑到边缘的噪声问题。我们选取了一个120×30的单位矩阵作为空白区域的特征矩阵。接下来,对整幅图像进行逐点扫描。扫描到一点时,以这一点为原点与特征矩阵比较,如果相等,程序则返回该点的值,这一点就是条形码左上角的点,如果不相等,继续扫描下一点。其主要的程序流程图如图4-4所示。经过提取条形码如图4-5所示条形码被置于整个图片左上方。
    定位流程图
    提取到的条形码图4-5 提取后的条形码

    1.3.3条形码信息的提取
    找到条形码的起始坐标后,我们就能对条形码的信息进行提取了。首先以条形码的起始坐标为依据提取一行含有条形码信息的数据。通过对起始符,结束符,以及左右空白区的判断,我们可以准确的找到条形码中间的数据区域。接下来我们将对条形码的数据区域进行进一步的处理,把条形码转换成标准模块的条形码,也就是每个模块都是有‘0’或‘1’表示。
    1.3.4条形码单元的判断
    条形码的单元指的是我们看到的条形码中的条和空,每一个单元都是有1~4个模块组成的。本步的主要工作是判断条形码中每个单元的数据(0或1)和其所占的像素数。其主要程序的流程图如图4-6所示。
    1.3.5条形码模块的识别
    模块是组成条形码最基本的单位,在识别的过程中识别出每个模块的值我们就能对条形码进行判别了。上一步我们得到了条形码每个单元的数据以及宽度(所占像素数),把所有单元的像素数相加就可以得出整个条形码所占的总像素数了。在第二章中,我们在介绍了EAN-13码的基本构成,不包括条形码的左右空白区总空有95个模块组成。这样就可以知道每个模块所占的像素数了。进而可以计算出每个单元的模块数。主要程序如下:
    单元判别图
    完成上述两个步骤后我们已经将各个模块单元化了。也就是说每个模块都是由一个单位的0或1表示的,转换成了条形码的逻辑值。经过处理后条形码的图像如图4-7所示。我们可以把这幅图像与图4-5做一比较,条形码明显清晰。
    得到条形码区域
    图4-7 经过整形后单位模块的条形码

    1.3.6条形码数字判别
    到现在为止,我们已经将条形码的图片信息转换成了二进制的数组。按照条形码的编码规则,整个数组包括起始符,结束符,中间分隔符,数据信息总共95位,前3位是起始符(010),446位为左侧数据,4651位为中间分隔符(01010),5192位为右侧数据,9395位为结束符(010)。
    程序清单:
    j=1, k=1
    for i=4:51 %从第四位开始跳过了起始符
    evrybar(k ,j)=bar(i) %每7位数字存到一行里
    j=j+1
    if j8 %判断是否存储了7位数字
    k=k+1
    j=1
    end
    end
    j=1, k=7
    for i=51:92 %从第51位开始跳过了中间分隔符
    evrybar(k ,j)=bar(i)
    j=j+1
    if j
    8
    k=k+1
    j=1
    end
    end
    这样我们就能把每一个数字的逻辑值存到数组evrybar中。

       数组evrybar中每一行表示一位数字的逻辑值,例如第一位数字的逻辑值为1110100。接下来的任务就是判别数字了,取出数组evrybar中的一行,与数据库中的数据做比较,相同时返回相应的数字。注意在判别左侧数字时,因为左侧数字存在A、B两种编码方式,所以还要创建一个存储编码方式的数组barab。如果A类编码把数组barab相应的位置设置为1,B类编码则设置为0。这样我们就能通过数组barab来判断前置字符了。相应程序见附录。
    

    1.3.7校验输出结果
    从代码位置序号2开始,所有偶数位的数字代码求和为a。 将上步中的a乘以3为a。从代码位置序号3开始,所有奇数位的数字代码求和为b。将a和b相加为c。取c的个位数d。用10减去d即为校验位数值。
    例:234235654652的校验码的计算如表4-1。
    表4-1 校验码计算示意表
    代码位置序号 13 12 11 10 9 8 7 6 5 4 3 2 1
    数字码 2 3 4 2 3 5 6 5 4 6 5 2 ×
    步骤1:3+2+5+5+6+2=23
    步骤2:23*3=69
    步骤3:2+4+3+5+4+5=23
    步骤4:69+23=92
    步骤5:10-2=8
    步骤6:校验码为8
    1.4 主程序执行结果
    图4-9是程序运行后输出的结果,与条形码上的数字相同。准确判断出了条形码的数字,达到了预期的效果。运行效果图

    展开全文
  • 对倾斜的(没有严重形变)一维码的角度校正,可以根据其黑白相间、排列规则的特点,计算傅里叶频谱,通过傅里叶频谱中直线的倾斜角度计算空间域图像一维码需校正的角度。 校正步骤: 1. 计算图像X,Y方向上梯度图像...
  • 第16章 一维码识别_BarCode create_bar_code_model创建条形码模型。返回的句柄提供有关条形码结构的所有必要信息。 find_bar_code读取条形码。可以指定要搜索的模型和条形码类型。返回指定类型的所有条码区域和...
  • 条形码识别技术是比较成熟的技术,但是对于有些刚刚接触图像处理的同学来说,从头开始学还是挺麻烦的,前几天写的个作业,花了近两天的时间才了解原理并完成代码,程序比较简单,识别率也很高,对于其他有做这块...
  • 条形码图像识别技术

    2009-11-04 15:36:00
    论文:《一维条形码识别系统的设计与实现》钟书成 成都信息工程学院软件工程系 1 中值滤波去噪 中值滤波是一种非线形信号处理方法,在这里由于条码图片是列的形式,所以采用改进的5个点采样窗口,取一列上的5个点...
  • 条形码识别(1)——基础知识标签: 机器视觉 条形码识别 ...可惜时间不多,要是本科期间有现在学习的心思就好了……综合考虑了一下难易程度和实用性,最终选择了“条形码识别”这个目标,方面有图像处理的知识,
  • 通常,条形码识别处理区域中像素的计数以确定条形码符号中特定条的宽度和位置。因此,如果分辨率不高,此过程会受到影响。 通常,分辨率至少要达到200dpi,并且分辨率越高越好。大多数开发人员想通过最小化分辨率...
  • 本设计研究EAN13条形码识别的译码技术,在基于机器视觉技术上,构建了一套条形码在线检测识别系统,系统将由以下几个部分构成:条形码图像定位与采集、计算机图像预处理、条形码图像中值滤波去噪、条码解析与识读。...
  • 用于商品时,通常对于每一种物品,它的编码是唯一的,对于普通的一维条码来说,还要通过数据库建立条码与商品信息的对应关系,当条码的数据传到计算机上时,由计算机上的应用程序对数据进行操作和处理。一 维条形码...
  • Bar Code 条形码 1、clear_all_bar_code_models 清除所有条形码模型释放内存clear_all_bar_code_models( : : : )2、clear_bar_code_model 清除条形码模型释放内存clear_bar_code_model( : : BarCodeHandle : )3...
1 2 3 4 5 ... 20
收藏数 2,156
精华内容 862