问题概述
目前开发的App中涉及到以下场景:基于纸质发票的二维码扫描结果,调用国税总局的查询接口,获取发票的票面信息并自动构建对应的报销单
发票二维码中包含以下信息:
01,04,3200172320,39603420,110.68,20180526,07094405910702570327,9AE7,
国税总局接口中需要以下信息进行查询:
发票代码:3200172320
发票号:39603420开票日期:20180526(普票)校验码后六位:570327(专票)不含税金额:110.68目前App的二维码扫描一般采用Zbar或者Zxing的解决方案,我们目前使用的是Zbar的扫描方案。该方案在扫描电子发票的二维码以及打印清晰的二维码时扫描迅速、准确。
但是在扫描纸质发票上的二维码时基本无能为力,只有极少部分打印清晰,点阵整齐的发票可以扫描出来。那我们首先来分析一下为什么无法扫描二维码
二维码生成规则简析
二维码生成原理:
原文比较长,捡重要的部分说一下
版本
二维码分为40个版本(Version),第一个版本行、列格子数量为21 * 21,每增加一个版本,行、列各自数量各增加4,即版本为7的二维码,行列格子数量都为 21 + 4*4= 37
区域
二维码图像从功能上分为以下区域:
定位区域:
用于帮助二维码扫描器定位整体图像以及切割数据信息的定位图形,分为以下三种:
1.Position Detection Pattern:二维码左上、左下、右上的定位正方形,正方形分为三部分:黑色外框,白色内框,黑色内正方形,其中宽度比例为:1:1:3,整体图形宽度为 72.Alignment Pattern:二维码内部用于辅助定位的正方形结构,分为三部分:黑色内框,白色内框,黑色内正方形,其中宽度比例为1:1:3,整体图形宽度为5,该定位图形在版本2以上的二维码中存在3.Timing Pattern:二维码内部定义行列基准的辅助线,帮助扫描器识别每个行列的基准位置元数据区域:
用于描述二维码的本身的格式以及版本信息的数据区域,分为以下两部分:
1.Format Information:存在于所有的尺寸中,用于存放一些格式化数据,包括:Error Correction Level(错误纠正等级)、Mask(掩码类型)2.Version Information:Version 7以上,需要预留两块3 x 6的区域存放一些版本信息
数据以及纠错码区域:
除了上述的那些地方,剩下的地方存放 Data Code 数据码 和 Error Correction Code 纠错码。最终编码的填充方式如下:从左下角开始沿着红线填我们的各个bits,1是黑色,0是白色。如果遇到了上面的非数据区,则绕开或跳过。
发票二维码解析问题简析
二维码扫描器列举以及原理分析
目前市面上有很多App自带了二维码扫描,经过测试,我们得出以下结论:
二维码扫描能力:阿里系(支付宝、钉钉) > 腾迅系(微信、QQ)> 第三方收费插件 > 苹果相机自带二维码扫描 > ZBar方案 > Zxing方案
阿里的扫描器基本可以扫描出所有的发票二维码,很多残缺的二维码图像也可以扫描出来,而且扫描的速度非常快。腾讯的扫描器可以扫描出完整的二维码,即使出现图像偏色、部分模糊的问题,扫描速度稍逊于阿里。第三方收费插件对偏色和部分模糊的处理稍微差一些。苹果自带的二维码扫描可以扫描出打印清晰、整齐的二维码,编码部分出现线段粗细不一致和部分空白也可以扫描。Zbar和Zxing对发票二维码基本无能为力。
Tips:手淘对发票二维码的扫描率远低于钉钉,应该是钉钉对企业的应用场景做了更深入层次的优化
我们对二维码扫描器的工作原理进行分析,扫描器应当是对一张图片进行二维码的特征提取,例如Position Detection Pattern和Alignment Pattern,检索出整体图形大致形状,然后通过Timing Pattern建立扫描坐标体系,再扫描元数据区域,确认解码方案,然后根据坐标体系对数据以及纠错码区域进行扫描和数据分割,获取已编码数据,最后根据解码方案反向解码获得二维码的实际信息。
根据对zxing和zbar的测试,扫描器对结构清晰、整齐的二维码扫描很快,说明当来源图片清晰的时候,扫描器可以顺利的构建特征和坐标,并最终解码。当扫描发票时,由于发票的特征和坐标存在缺陷,导致扫描器无法正确识别。
由于整体二维码解码过程比较复杂,且已经有很好的开源库支持,所以我们的目标不是重新写一个解码器,而是通过一些算法将发票上不明确的二维码特征值提取出来,重新构建一个标准的二维码图形,并输送给zxing或者zbar进行解码。
发票二维码实例分析
1.清晰二维码:可识别扫描器:全部
2.偏色二维码:可识别扫描器:支付宝
3.差色二维码:可识别扫描器:支付宝、微信,当手机处于静态状态的时候,支付宝和微信对这个二维码扫描识别率都很低,但是当手机摄像头整体晃动的时候,支付宝和微信对这个二维码都可以迅速识别。无法理解的黑科技
4.干扰二维码:可识别扫描器:支付宝、微信、苹果相机自带、第三方插件
5.部分糊化二维码:可识别扫描器:支付宝、微信、苹果相机自带、第三方插件、Zbar
6.整体糊化二维码:可识别扫描器:支付宝、微信
7.线条宽度残缺:可识别扫描器:支付宝
8.定位图形缺损:可识别扫描器:支付宝,从实际收集到的发票来看,这种问题的发票数量比较多,迫切需要解决
从测试结果来看,支付宝对偏色、差色、线条干扰、糊化、残缺的二维码图片都有很好的识别率。微信对图形完整的二维码有很好的识别率,当图片出现残损的时候没有对应的策略。
苹果自带相机的扫描效果要好于Zbar方案,如果做二维码扫描的同学在IOS端可以考虑直接调用苹果相机自带的扫描。
该篇主要是对二维码的原理进行了简介,对目前发票二维码扫描的问题点进行了简要分析,后续对改进的方案进行介绍。