二维码识别与解析软件测试_二维码 解析 识别 接口 - CSDN
  • 首先看看二维码识别原理: 一.我们都是使用二维码生成工具制码,原理对于我们意义并不是很大,这里就不浪费地方复制黏贴了。二维码编码原理请google。 二.下面是本次问题相关的一些经验。 1. 同一尺寸...

    首先看看二维码识别原理:

    一.我们都是使用二维码生成工具制码,原理对于我们意义并不是很大,这里就不浪费地方复制黏贴了。二维码编码原理请google。

    二.下面是与本次问题相关的一些经验。

    1.   同一尺寸同一纠错等级下:二维码的点阵密度和包含的字串长度成正比。即信息含量越大,点阵越密。第2张码点阵就密集的多。

    2.   同一尺寸同一URL:二维码的点阵密度,和纠错等级成正比。(即纠错等级越高,点阵越密。)采用目前的低端机C8650测试,(后置摄像头300W像素,支持自动对焦)

    测试发现,相同尺寸下,点阵密度到达一定程度将无法识别。纠错等级是用来当二维码不完整时,也可以正确识别而产生的。

    简单的可以理解为,只要纠错等级高,即使只有半张二维码,也可以扫描识别正确。由于我们的二维码是放在店内的,二维码不易损坏。

    因此我们完全可以尝试用最低等级,以降低点阵密度,提高识别率。

    3.更悲剧的是有的门店的二维码只有这么点小:

    4.周围环境,如拍摄距离,角度,光线等因素都会造成识别以后图像信息缺失,导致失败。比如一茶一坐的二维码是放在会反光的桌牌里,相比较来看,它的二维码识别率就低很多。

    各种证明+推测得出以下结论,主要问题点:

    1.   由于我们的URL长度较长,导致生成的二维码,在小尺寸下,点阵过密,导致无法识别。不考虑环境因素。

    2.二维码物料大部分是放在桌牌里的,餐厅光线条件差,很多机型识别以后图像损失严重。亲们想一想,用个低端机在昏暗的光线下自拍,能看清楚自己的脸不???就是iphone这种机型也会经常识别失真。

     各种机型的识别程度估计:

     

    机型

    摄像头

    识别成功率毛估

     

    高端机

    支持自动对焦,像素高,芯片好

     80%

     

    中端机 

    支持自动对焦,像素低,芯片一般

     60%

     

     低端机

     不支持自动对焦

     。。。。

     


    建议改进方法如下,供参考:

      

    方法编号

    方法

    优点

    缺点

    1

    1.将URL改短

    2.重新印刷二维码

    可以继续张贴小尺寸的二维码

    1.  需要修改我们的系统

    2.  重新印刷二维码

    2

    将二维码纠错等级降低,重新印刷二维码。

    可以继续张贴小尺寸的二维码

    重新印刷二维码

    3

    只改动APP,

    对低端机提示不支持二维码扫描。

    用户体验会好

    低端机无法使用。

    是否要对低端机区别对待,要看产品的定位,和用户机型的了解。

    后续的监测与测试方法:

    建议使用UserTrack + 低端机检测包配合使用,

    统计出无法扫描成功的低端机占总扫描设备的百分比,再来做方案2 和3 的选择。

     

    目前:

    2.6.3扫码更换成淘宝主客户端扫码控件,这样改进点为:

    1扫码时自动打开闪光灯,补偿光线,并且自动对焦。降低环境影响。

    2将URL改为短连接,重新制码,降低点阵密度。

    3.首先识别机型,如果机型不支持自动对焦则提示用户淘宝点点暂时不支持这种机型(未实现)

    4.用UserTrack + 低端机检测包,监测失败机型(未实现)


    展开全文
  • 火车票二维码识别

    2019-07-07 03:59:27
    现在的火车票都有二维码了,办公室里面又有几张不知谁留下的火车票,正好,手头有一台扫描仪,自己又是做图像方面的,可以测试测试火车票二维码内容。 其实测试没有什么难点,用的是第三方的软件Pystec,关键是降...

    现在的火车票都有二维码了,办公室里面又有几张不知谁留下的火车票,正好,手头有一台扫描仪,自己又是做图像方面的,可以测试测试火车票二维码内容。

     

    其实测试没有什么难点,用的是第三方的软件Pystec,关键是降背景色去掉。

     

    去除背景色的原理也很简单,只是将RGB作为三维坐标球看待,然后在指定半径内的值设置为黑色或白色,那么黑白二色就非常明显了,也就是去除了背景色,下面是处理后的图片,处理的不是很好,但已经够用了。

     

     

    然后就可以用Pystec软件读取出来了,数据是一串数字:

     

    260437920452551526158897477630334857226488293091077961990434914943200000000000000000000053897628805389762880538976288053897628805389762881447000

     

    什么意思,不要问我,问铁路部吧!

     

    blog:

    http://www.cnblogs.com/ubunoon/

     

     

     

     

    转载于:https://www.cnblogs.com/ubunoon/archive/2010/02/08/1666007.html

    展开全文
  • 0 前言 今天分享一个之前做过的二维码识别,参考:https://www.pyimagesearch.com/2018/05/21/an-opencv-barcode-and-qr-code-scanner-with-zbar/ 上面那个只有Python版本,再推荐一个C++版本的: ...

    0 前言

    今天分享一个之前做过的二维码识别,参考:https://www.pyimagesearch.com/2018/05/21/an-opencv-barcode-and-qr-code-scanner-with-zbar/

    上面那个只有Python版本,再推荐一个C++版本的:
    https://www.learnopencv.com/opencv-qr-code-scanner-c-and-python/

    如果对你有帮助,请点赞+关注,有问题请留言。

    1 介绍

    1.1 二维码

    二维码又称二维条码,常见的二维码为QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型。

    二维码是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的;在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理:它具有条码技术的一些共性:每种码制有其特定的字符集;每个字符占有一定的宽度;具有一定的校验功能等。同时还具有对不同行的信息自动识别功能、及处理图形旋转变化点。
    在这里插入图片描述

    1.2 二维码在智能物流中的应用场景

    如今,人们在寄快递时,只需要用手机扫描一个二维码,然后在打开的界面中填入姓名、联系电话和收获地址等信息,所填信息就存储在了二维码里面。在仓储分拣和智能配送时,只需用专用的扫面设备扫描二维码,就可获取里面存储的信息,不仅提高了效率,还降低了客户隐私泄露的风险,因此在智能物流领域具有很大的应用价值。
    在这里插入图片描述

    2 设备

    2.1 硬件环境

    • NVIDIA Jetson TX2开发板
    • USB网络摄像机

    2.2 软件环境

    • Ubuntu 16.04
    • OpenCV
    • ZBar

    3 步骤

    3.1 安装OpenCV

    OpenCV是一个图像处理和计算机视觉库。
    (1)下载OpenCV
    在OpenCV官网(http://opencv.org)下载OpenCV 2.4.11的source版本到本地,然后解压。
    (2)编译并安装

    $ cd ~/opencv
    $ mkdir build
    $ cd build
    $ cmake -D CMAKE_BUILD_TYPE=Release –D \ CMAKE_INSTALL_PREFIX=/usr/local ..
    $ make –j
    $ sudo make install	
    

    注:这里只在OpenCV 2.4.11上进行了测试,OpenCV 3系列的版本也适用。

    3.2 安装ZBar

    ZBar是一个开源软件套件,用于从各种来源读取条形码,例如视频流,图像文件和原始强度传感器(raw intensity sensors)。它支持许多流行的符号(条形码类型),包括EAN-13 / UPC-A,UPC-E,EAN-8,Code 128,Code 39,Interleaved 2 of 5和QR Code。

    $ sudo apt-get install libzbar0
    $ sudo pip install pyzbar	
    

    3.3 获取视频流并对二维码进行检测和解码

    (1)导入所需的工具包

    # 导入所需工具包
    from imutils.video import VideoStream
    from pyzbar import pyzbar
    import argparse
    import datetime
    import imutils
    import time
    import cv2
    
    # 创建参数解析器,解析参数
    ap = argparse.ArgumentParser()
    ap.add_argument("-o", "--output", type=str, default="barcodes.csv",
        help="path to output CSV file containing barcodes")
    args = vars(ap.parse_args())
    

    (2)初始化视频流

    # 初始化视频流
    print("[INFO] starting video stream...")
    vs = VideoStream(src=0).start()
    time.sleep(2.0)
    
    # 打开输出CSV文件,用来写入和初始化迄今发现的所有条形码
    csv = open(args[""output"], "w")
    found = set()
    

    (3)获取和处理视频帧,然后使用ZBar检测并解码二维码

    # 循环来自视频流的帧
    while True:
    # 抓取视频流的帧
        # 将大小重新调整为最大宽度400像素
    frame = vs.read()
        frame=imutils.resize(frame,width=400)
    
         # 找到视频中的条形码,并解析所有条形码
         barcodes = pyzbar.decode(frame)
    

    (4)获取二维码边界框位置,并转换解码数据的格式

    # 循环检测到的条形码
        for barcode in barcodes:
            # 提取条形码的边界框位置
            # 绘出围绕图像上条形码的边界框
            (x, y, w, h) = barcode.rect
            cv2.rectangle(frame,(x, y),(x+ w, y + h),(0,0,255), 2)
    
            # 条形码数据为字节对象,所以如果我们想把它画出来
            # 需要先把它转换成字符串
            barcodeData = barcode.data.decode("utf-8")
            barcodeType = barcode.type
    
            # 绘出图像上的条形码数据和类型
            text = "{} ({})".format(barcodeData, barcodeType)
            cv2.putText(frame, text, (x, y - 10),
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
    

    (5)把扫描结果存储到CSV数据库

            # 如果条形码文本目前不在CSV文件中, 
            # 就将时间戳+条形码 写入硬盘并更新集合
            if barcodeData not in found:
                csv.write("{},{}\n".format(datetime.datetime.now(),
                    barcodeData))
                csv.flush()
                found.add(barcodeData)
    

    (5)显示结果

    	# 展示输出帧
    	cv2.imshow("Barcode Scanner", frame)
    	key = cv2.waitKey(1) & 0xFF
    
        # 如果按下”q”键就停止循环
        if key == ord("q"):
            break
    
    # 关闭输出CSV文件进行清除
    print("[INFO] cleaning up...")
    csv.close()
    cv2.destroyAllWindows()
    vs.stop()
    

    4 测试

    4.1 准备一张二维码

    最简单的方法是使用二维码生成工具,网上有很多,任意选择一款即可。这里,我使用草料二维码工具,生成了一个内容为“xucheng”的二维码:
    在这里插入图片描述

    4.2 运行

    将以上代码整合成python脚本后执行,然后将摄像头对准上一步中生成的二维码。

    如下图所示,可以看出,打开了一个显示摄像头采集的图像的窗口,其中,二维码被红色矩形框框出,二维码的内容“xucheng”显示在二维码上面。
    在这里插入图片描述

    5 Bug

    ZBar是日本人开发的,由于编码格式的问题,识别中文会乱码,网上也有很多解决这个问题的方案,但是比较繁琐,也不一定能成功。

    针对这个问题,我也咨询了博主,以下是对话截图,提供一个类似问题的链接,可以参考。
    在这里插入图片描述
    所以,如果必须识别中文,建议换其他的二维码识别库,比如ZXing。

    好了,就到这里吧。

    展开全文
  • 于是就开始各种搜索,最终自己也利用Google的ZXing工具完成了一个生成二维码解析二维码的简单程序。 一、 二维码生成原理(即工作原理) 二维码官方叫版本Version。Version 1是21 x 21的矩阵,Version 2是 25 x ...

    今天突然想到二维码是如何存储信息的。于是就开始各种搜索,最终自己也利用Google的ZXing工具完成了一个生成二维码和解析二维码的简单程序。

    一、 二维码生成原理(即工作原理)

    二维码官方叫版本Version。Version 1是21 x 21的矩阵,Version 2是 25 x 25的矩阵,Version 3是29的尺寸,每增加一个version,就会增加4的尺寸,公式是:(V-1)*4 + 21(V是版本号) 最高Version 40,(40-1)*4+21 = 177,所以最高是177 x 177 的正方形。

    下面是一个二维码的样例:

    1、定位图案

    Position Detection Pattern是定位图案,用于标记二维码的矩形大小。这三个定位图案有白边叫Separators for Postion Detection Patterns。之所以三个而不是四个意思就是三个就可以标识一个矩形了。

    Timing Patterns也是用于定位的。原因是二维码有40种尺寸,尺寸过大了后需要有根标准线,不然扫描的时候可能会扫歪了。

    Alignment Patterns 只有Version 2以上(包括Version2)的二维码需要这个东东,同样是为了定位用的。

    2、功能性数据

    Format Information 存在于所有的尺寸中,用于存放一些格式化数据的。

    Version Information 在 >= Version 7以上,需要预留两块3 x 6的区域存放一些版本信息。

    数据码和纠错码

    除了上述的那些地方,剩下的地方存放 Data Code 数据码 和 Error Correction Code 纠错码。

    3、数据编码

    QR码支持如下的编码:

    Numeric mode 数字编码,从0到9。如果需要编码的数字的个数不是3的倍数,那么,最后剩下的1或2位数会被转成4或7bits,则其它的每3位数字会被编成 10,12,14bits,编成多长还要看二维码的尺寸(下面有一个表Table 3说明了这点)

    Alphanumeric mode 字符编码。包括 0-9,大写的A到Z(没有小写),以及符号$ % * + – . / : 包括空格。这些字符会映射成一个字符索引表。如下所示:(其中的SP是空格,Char是字符,Value是其索引值) 编码的过程是把字符两两分组,然后转成下表的45进制,然后转成11bits的二进制,如果最后有一个落单的,那就转成6bits的二进制。而编码模式和 字符的个数需要根据不同的Version尺寸编成9, 11或13个二进制(如下表中Table 3)

    Byte mode, 字节编码,可以是0-255的ISO-8859-1字符。有些二维码的扫描器可以自动检测是否是UTF-8的编码。

    Kanji mode 这是日文编码,也是双字节编码。同样,也可以用于中文编码。日文和汉字的编码会减去一个 值。如:在0X8140 to 0X9FFC中的字符会减去8140,在0XE040到0XEBBF中的字符要减去0XC140,然后把前两位拿出来乘以0XC0,然后再加上后两位,最 后转成13bit的编码。如下图示例:

    Extended Channel Interpretation (ECI) mode 主要用于特殊的字符集。并不是所有的扫描器都支持这种编码。

    Structured Append mode 用于混合编码,也就是说,这个二维码中包含了多种编码格式。

    FNC1 mode 这种编码方式主要是给一些特殊的工业或行业用的。比如GS1条形码之类的。

    简单起见,后面三种不会在本文 中讨论。

    下面两张表中,

    Table 2 是各个编码格式的“编号”,这个东西要写在Format Information中。注:中文是1101

    Table 3 表示了,不同版本(尺寸)的二维码,对于,数字,字符,字节和Kanji模式下,对于单个编码的2进制的位数。(在二维码的规格说明书中,有各种各样的编码规范表,后面还会提到)

    示例一:数字编码

    在Version 1的尺寸下,纠错级别为H的情况下,编码: 01234567

    把上述数字分成三组: 012 345 67

    把他们转成二进制: 012 转成 0000001100; 345 转成 0101011001; 67 转成 1000011。

    把这三个二进制串起来: 0000001100 0101011001 1000011

    把数字的个数转成二进制 (version 1-H是10 bits ): 8个数字的二进制是 0000001000

    把数字编码的标志0001和第4步的编码加到前面: 0001 0000001000 0000001100 0101011001 1000011

    示例二:字符编码

    在Version 1的尺寸下,纠错级别为H的情况下,编码: AC-42

    1. 从字符索引表中找到 AC-42 这五个字条的索引 (10,12,41,4,2)

    2. 两两分组: (10,12) (41,4) (2)

    3.把每一组转成11bits的二进制:

    (10,12) 10*45+12 等于 462 转成 00111001110

    (41,4) 41*45+4 等于 1849 转成 11100111001

    (2) 等于 2 转成 000010

    1. 把这些二进制连接起来:00111001110 11100111001 000010

    2. 把字符的个数转成二进制 (Version 1-H为9 bits ): 5个字符,5转成 000000101

    3. 在头上加上编码标识 0010 和第5步的个数编码: 0010 000000101 00111001110 11100111001 000010

    结束符和补齐符

    假如我们有个HELLO WORLD的字符串要编码,根据上面的示例二,我们可以得到下面的编码,

    编码

    字符数

    HELLO WORLD的编码

    0010 000001011 01100001011 01111000110 10001011100 10110111000 10011010100 001101

    我们还要加上结束符:

    编码

    字符数

    HELLO WORLD的编码

    结束

    0010 000001011 01100001011 01111000110 10001011100 10110111000 10011010100 001101 0000

    按8bits重排

    如果所有的编码加起来不是8个倍数我们还要在后面加上足够的0,比如上面一共有78个bits,所以,我们还要加上2个0,然后按8个bits分好组:

    00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 01000000

    补齐码(Padding Bytes)

    最后,如果如果还没有达到我们最大的bits数的限制,我们还要加一些补齐码(Padding Bytes),Padding Bytes就是重复下面的两个bytes:11101100 00010001 (这两个二进制转成十进制是236和17,我也不知道为什么,只知道Spec上是这么写的)关于每一个Version的每一种纠错级别的最大Bits限 制,可以参看QR Code Spec的第28页到32页的Table-7一表。

    假设我们需要编码的是Version 1的Q纠错级,那么,其最大需要104个bits,而我们上面只有80个bits,所以,还需要24个bits,也就是需要3个Padding Bytes,我们就添加三个,于是得到下面的编码:

    00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 01000000 11101100 00010001 11101100

    纠错码

    上面我们说到了一些纠错级别,Error Correction Code Level,二维码中有四种级别的纠错,这就是为什么二维码有残缺还能扫出来,也就是为什么有人在二维码的中心位置加入图标。

    错误修正容量

    L水平 7%的字码可被修正

    M水平 15%的字码可被修正

    Q水平 25%的字码可被修正

    H水平 30%的字码可被修正

    那么,QR是怎么对数据码加上纠错码的?首先,我们需要对数据码进行分组,也就是分成不同的Block,然后对各个Block进行纠错编码,对于如何分组,我们可以查看QR Code Spec的第33页到44页的Table-13到Table-22的定义表。注意最后两列:

    Number of Error Code Correction Blocks :需要分多少个块。

    Error Correction Code Per Blocks:每一个块中的code个数,所谓的code的个数,也就是有多少个8bits的字节。

    举个例子:上述的Version 5 + Q纠错级:需要4个Blocks(2个Blocks为一组,共两组),头一组的两个Blocks中各15个bits数据 + 各 9个bits的纠错码(注:表中的codewords就是一个8bits的byte)(再注:最后一例中的(c, k, r )的公式为:c = k + 2 * r,因为后脚注解释了:纠错码的容量小于纠错码的一半)

    对每个块的纠错码

    1 1 67 85 70 134 87 38 85 194 119 50 6 18 6 103 38 213 199 11 45 115 247 241 223 229 248 154 117 154 111 86 161 111 39

    2 246 246 66 7 118 134 242 7 38 86 22 198 199 146 6 87 204 96 60 202 182 124 157 200 134 27 129 209 17 163 163 120 133

    2 1 182 230 247 119 50 7 118 134 87 38 82 6 134 151 50 7 148 116 177 212 76 133 75 242 238 76 195 230 189 10 108 240 192 141

    2 70 247 118 86 194 6 151 50 16 236 17 236 17 236 17 236 235 159 5 173 24 147 59 33 106 40 255 172 82 2 131 32 178 236

    注:二维码的纠错码主要是通过Reed-Solomon error correction(里 德-所罗门纠错算法)来实现的。对于这个算法,对于我来说是相当的复杂,里面有很多的数学计算,最终编码。

    穿插放置

    二维码的混乱技术还没有玩完,它还要把数据码和纠错码的各个codewords交替放在一起。如何交替呢,规则如下:

    对于数据码:把每个块的第一个codewords先拿出来按顺度排列好,然后再取第一块的第二个,如此类推。如:上述示例中的Data Codewords如下:

    块 1 67 85 70 134 87 38 85 194 119 50 6 18 6 103 38

    块 2 246 246 66 7 118 134 242 7 38 86 22 198 199 146 6

    块 3 182 230 247 119 50 7 118 134 87 38 82 6 134 151 50 7

    块 4 70 247 118 86 194 6 151 50 16 236 17 236 17 236 17 236

    我们先取第一列的:67, 246, 182, 70

    然后再取第二列的:67, 246, 182, 70, 85,246,230 ,247

    如此类推:67, 246, 182, 70, 85,246,230 ,247 ……… ……… ,38,6,50,17,7,236

    对于纠错码,也是一样:

    块 1 213 199 11 45 115 247 241 223 229 248 154 117 154 111 86 161 111 39

    块 2 87 204 96 60 202 182 124 157 200 134 27 129 209 17 163 163 120 133

    块 3 148 116 177 212 76 133 75 242 238 76 195 230 189 10 108 240 192 141

    块 4 235 159 5 173 24 147 59 33 106 40 255 172 82 2 131 32 178 236

    和数据码取的一样,得到:213,87,148,235,199,204,116,159,…… …… 39,133,141,236

    然后,再把这两组放在一起(纠错码放在数据码之后)得到:

    67, 246, 182, 70, 85, 246, 230, 247, 70, 66, 247, 118, 134, 7, 119, 86, 87, 118, 50, 194, 38, 134, 7, 6, 85, 242, 118, 151, 194, 7, 134, 50, 119, 38, 87, 16, 50, 86, 38, 236, 6, 22, 82, 17, 18, 198, 6, 236, 6, 199, 134, 17, 103, 146, 151, 236, 38, 6, 50, 17, 7, 236, 213, 87, 148, 235, 199, 204, 116, 159, 11, 96, 177, 5, 45, 60, 212, 173, 115, 202, 76, 24, 247, 182, 133, 147, 241, 124, 75, 59, 223, 157, 242, 33, 229, 200, 238, 106, 248, 134, 76, 40, 154, 27, 195, 255, 117, 129, 230, 172, 154, 209, 189, 82, 111, 17, 10, 2, 86, 163, 108, 131, 161, 163, 240, 32, 111, 120, 192, 178, 39, 133, 141, 236

    Remainder Bits

    最后再加上Reminder Bits,对于某些Version的QR,上面的还不够长度,还要加上Remainder Bits,比如:上述的5Q版的二维码,还要加上7个bits,Remainder Bits加零就好了。关于哪些Version需要多少个Remainder bit,可以参看QR Code Spec的第15页的Table-1的定义表。

    4、画二维码图

    Position Detection Pattern

    首先,先把Position Detection图案画在三个角上。

    Alignment Pattern

    然后,再把Alignment图案画上

    关于Alignment的位置,可以查看QR Code Spec的第81页的Table-E.1的定义表(下表是不完全表格)

    下图是根据上述表格中的Version8的一个例子(6,24,42)

    Timing Pattern

    接下来是Timing Pattern的线(这个不用多说了)

    Format Information

    再接下来是Formation Information,下图中的蓝色部分。

    Format Information是一个15个bits的信息,每一个bit的位置如下图所示:(注意图中的Dark Module,那是永远出现的)

    这15个bits中包括:

    5个数据bits:其中,2个bits用于表示使用什么样的Error Correction Level, 3个bits表示使用什么样的Mask

    10个纠错bits。主要通过BCH Code来计算

    然后15个bits还要与101010000010010做XOR操作。这样就保证不会因为我们选用了00的纠错级别,以及000的Mask,从重造成全部为白色,这会增加我们的扫描器的图像识别的困难。

    下面是一个示例:

    关于Error Correction Level如下表所示:

    关于Mask图案如后面的Table 23所示。

    Version Information

    再接下来是Version Information(版本7以后需要这个编码),下图中的蓝色部分。

    Version Information一共是18个bits,其中包括6个bits的版本号以及12个bits的纠错码,下面是一个示例:

    而其填充位置如下:

    数据和数据纠错码

    然后是填接我们的最终编码,最终编码的填充方式如下:从左下角开始沿着红线填我们的各个bits,1是黑色,0是白色。如果遇到了上面的非数据区,则绕开或跳过。

    5、掩码图案

    这样下来,图就填好了,但是,也许那些点并不均衡,所以还要做Masking操作QR的Spec中说了,QR有8个 Mask可以使用,如下所示:其中,各个mask的公式在各个图下面。所谓mask,说白了,就是和上面生成的图做XOR操作。Mask只会和数据区进 行XOR,不会影响功能区。

    其Mask的标识码如下所示:(其中的i,j分别对应于上图的x,y)

    Mask过后的二维码就成最终的图了。

    (以上内容来源于网络)

    二、 编码实现

    首先,我们需要下载Google的ZXing库。
    下载地址:https://github.com/zxing/zxing

    根据内容创建二维码

    	/**
         * TODO 根据给定的内容生成二维码
         *
         * @param content        二维码内容
         * @param logoImagePath  logo图标的路径
         * @param needCompressed 是否需要压缩logo
         * @return 生成的二维码
         * @throws IOException
         * @throws WriterException
         */
    	private static BufferedImage createImage(String content, String logoImagePath, boolean needCompressed) 
                throws IOException, WriterException {
            HashMap hints = new HashMap<EncodeHintType, Object>();
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);  // 纠错等级
            hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
            hints.put(EncodeHintType.MARGIN, 1);  // 二维码两边空白区域大小
            BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
            int height = bitMatrix.getHeight();
            int width = bitMatrix.getWidth();
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            for (int x = 0; x < width; x++)
                for (int y = 0; y < height; y++)
                    image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
    
            if (logoImagePath == null || "".equals(logoImagePath))
                return image;
    
            // 如果有logo,则插入logo图片
            QRCode.InsertImage(image, logoImagePath, needCompressed);
            return image;
        }
    

    如果有logo则将logo插入到二维码中

    	/**
         * TODO 插入logo图片
         * @param sourceImage 原图片
         * @param logoImagePath logo图片所在的路径
         * @param needCompressed 是否需要压缩
         * @throws IOException
         */
        private static void InsertImage(BufferedImage sourceImage, String logoImagePath, boolean needCompressed) throws IOException {
            File file = new File(logoImagePath);
            if (!file.exists()){
                System.out.println("logo文件不存在!\n");
                return;
            }
    
            Image src = ImageIO.read(file);
            int width = src.getWidth(null);
            int height = src.getHeight(null);
    
            // 压缩二维码图片
            if (needCompressed) {
                if (width > LOGO_WIDTH)
                    width = LOGO_WIDTH;
                if (height > LOGO_HEIGHT)
                    height = LOGO_HEIGHT;
    
                Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
                BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                Graphics g = tag.getGraphics();
                g.drawImage(image, 0, 0, null);
                g.dispose();  // 释放占有的资源
                src = image;
                // 直观的理解:Graphics2D 就相当于画笔,而BufferedImage 就是画笔绘制的结果。
            }
    
            // 插入logo
            Graphics2D graph = sourceImage.createGraphics();
            int x = (QRCODE_SIZE - width) / 2;
            int y = (QRCODE_SIZE - height) / 2;
            graph.drawImage(src, x, y, width, height, null);
            Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
            graph.setStroke(new BasicStroke(3f));
            graph.draw(shape);
            graph.dispose();
        }
    

    解码过程

    	/**
         * TODO 解析二维码内容
         * @param file 二维码
         * @return 二维码包含的信息
         * @throws Exception
         */
        public static String decode(File file) throws Exception {
            BufferedImage image;
            image = ImageIO.read(file);
            if (image == null) {
                return null;
            }
            BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            HashMap hints = new HashMap<DecodeHintType, Object>();
            hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
            Result result = new MultiFormatReader().decode(bitmap, hints);
            String resultStr = result.getText();
            return resultStr;
        }
    

    测试结果

    源码下载地址:https://github.com/Liyzy/ZXing-QRCode
    开发环境:idea 2018.2

    展开全文
  • 它是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的,在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个二进制相对应的几何形体...
    二维条形码最早发明于日本,它是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的,在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理。
    

    所需要的jar包
    QRcode.jar

    二维码图片类 QrcodeImg.java

    package qrcode;
    
    import jp.sourceforge.qrcode.data.QRCodeImage;
    
    import java.awt.image.BufferedImage;
    
    /**
     * Created by zf on 2017/6/12.
     */
    public class QrcodeImg implements QRCodeImage {
    
        private BufferedImage bufImg = null;
    
        public QrcodeImg(BufferedImage bufImg) {
            this.bufImg = bufImg;
        }
    
        public int getWidth() {
            return bufImg.getWidth();
        }
    
        public int getHeight() {
            return bufImg.getHeight();
        }
    
        public int getPixel(int i, int i1) {
            return bufImg.getRGB(i, i1);
        }
    }

    二维码生成类 ImgEncoder.java

    package qrcode;
    
    import com.swetake.util.Qrcode;
    
    import javax.imageio.ImageIO;
    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.File;
    
    /**
     * Created by zf on 2017/6/12.
     */
    public class ImgEncoder {
    
        private int width = 140;//图片宽
        private int height = 140;//图片长
        private String imgPath = "D:\\qrcode.png";//图片保存位置
    
        public ImgEncoder() {
        }
    
        public ImgEncoder(int width, int height, String imgPath) {
            this.width = width;
            this.height = height;
            this.imgPath = imgPath;
        }
    
        public boolean generate(String content) {
            try {
                Qrcode qrcode = new Qrcode();
                // 设置二维码排错率,可选L(7%)、M(15%)、Q(25%)、H(30%),排错率越高可存储的信息越少,但对二维码清晰度的要求越小
                qrcode.setQrcodeErrorCorrect('Q');
                qrcode.setQrcodeEncodeMode('B');
                // 设置设置二维码尺寸,取值范围1-40,值越大尺寸越大,可存储的信息越大
                qrcode.setQrcodeVersion(7);
                //设置图片尺寸
                BufferedImage bufImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                //绘制二维码图片
                Graphics2D gs=bufImg.createGraphics();
                //设置二维码背景颜色
                gs.setBackground(Color.WHITE);
                //创建一个矩形区域
                gs.clearRect(0, 0, width, height);
                //设置二维码的图片颜色值 黑色
                gs.setColor(Color.BLACK);
                // 获得内容的字节数组,设置编码格式
                byte[] contentBytes = content.getBytes("utf-8");
                // 设置偏移量,不设置可能导致解析出错
                int pixoff = 2;
                //输出二维码
                if (contentBytes.length > 0 && contentBytes.length < 400) {
                    boolean[][] codeOut = qrcode.calQrcode(contentBytes);
                    for (int i = 0; i < codeOut.length; i++) {
                        for (int j = 0; j < codeOut.length; j++) {
                            if (codeOut[j][i]) {
                                gs.fillRect(j*3+pixoff, i*3+pixoff, 3, 3);
                            }
                        }
                    }
                }
                gs.dispose();
                bufImg.flush();
                //生成二维码图片
                File img = new File(imgPath);
                if (img.exists()) {
                    img.delete();
                }
                ImageIO.write(bufImg, "png", img);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }
    
    }

    二维码识别类 ImgDecoder.java

    package qrcode;
    
    import jp.sourceforge.qrcode.QRCodeDecoder;
    
    import javax.imageio.ImageIO;
    import java.awt.image.BufferedImage;
    import java.io.File;
    
    /**
     * Created by zf on 2017/6/12.
     */
    public class ImgDecoder {
        public static String decode(String imgPath) {
            String content = "error";
            try {
                File img = new File(imgPath);
                BufferedImage bufImg = ImageIO.read(img);
                QRCodeDecoder qrCodeDecoder = new QRCodeDecoder();
                content = new String(qrCodeDecoder.decode(new QrcodeImg(bufImg)), "utf-8");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return content;
        }
    }

    测试:
    这里写图片描述

    展开全文
  • 若该文为原创文章,未经允许不得转载 原博主博客地址:https://blog.csdn.net/qq21497936 ... 目录 前话 Demo Demo测试下载地址 ...二维码 ...一维条形码与二维码 二维码种类 堆叠式/行排式 矩阵式二...
  • 二维码 生成和解析

    2015-12-09 14:50:47
    涉及到的一些主要类库,方便大家下载: 编码lib:Qrcode_swetake.jar (官网介绍-- http://www.swetake.com/qr/index-e.html)  解码lib:qrcode.jar (官网介绍-- ... ...
  • ZBar是一个开源软件套件,用于从各种来源读取条形码,例如视频流,图像文件和原始强度传感器。它支持许多流行的符号体系 (条形码的类型),包括EAN-13 / UPC-A,UPC-E,EAN-8,Code 128,Code 39,Interleaved 2 of...
  • JDK版本为1.8 zxing-3.3.3 jar包下载 注意: 1、二维码扫描出来的网址显示的是文本而不是链接网站的原因:没有在网址前面加http://或https:// ...2、实现二维码扫描下载安装软件(以安卓为...
  • halcon二维码识别

    2019-12-20 10:15:14
    一维条码:由一组规则排列的条、空以及对应的字符组成的标记,“条”指对光线反射率较低的部分,“空”指对光线反射率较高的部分,这些条和空组成的数据表达一定的信息,并能够用特定的设备识读,转换成计算机兼容...
  • 现在大街小巷、各大网站都有二维码的踪迹,不管是IOS、Android、WP都有相关支持的软件。之前我就想了解二维码是如何工作,最近因为工作需要使用相关技术,所以做了初步了解。今天主要是讲解如何使用ZXing库,生成和...
  • 二维码现在越来越流行,可以使用手机上或其它移动终端上的二维码扫描器软件对着二维码一扫,就可以得到相关信息。在互联网站上,可以找到很多二维码的工具,甚至还有不少在线生成、解析二维码的网站。在业务系统当中...
  • 实现两个功能 ...2.仿淘宝海报保存图片到本地打开app时解析图片中的二维码得到消息(同上,如果不是可直接使用的则需要二次请求获取) 实现思路 1.文字分享信息(仿淘口令):打开app时会回调o...
  • 二维码PDF417简介及其解码实现(zxing-cpp)
  • ZXing是一个开源Java类库用于解析多种格式的条形码和二维码 2014年05月07日 17:30:37 shine4j 阅读数 5677 blog迁移至:http://www.micmiu.com 继前面介绍的一个日本开源软件(该软件只能实现QRCode)原文: ...
  • * 2D Code generated by Image Acquisition 01 * QR Code dev_close_window () dev_open_window (0, 0, 400, 400, 'black', WindowHandle) *先关闭活动图形窗口,再打开这个窗口,标识符为WindowHandle;...
1 2 3 4 5 ... 20
收藏数 2,951
精华内容 1,180
关键字:

二维码识别与解析软件测试