技术选型
为了解决二维码无法扫描的问题,必须选择合适的技术手段。由于我们的App引用的是别人开发的基于Zbar的图像识别插件,在没有能力修改图像识别插件的前提下,我决定在服务端解决这个问题,考虑到算法的通用型,在服务端验证通过的程序后期也可以考虑移植到App端,提高本地扫描速度,降低服务器性能消耗。IOS和Android的插件都存在相机对焦完成的事件,在该事件中可以拿到图像信息,我计划在拿到对焦完成的图片后,进行简单压缩后传输至服务器进行解析处理,再将服务器返回的解析结果作为解码结果传递给前台应用。
对图片的分析与操作属于计算机图形处理的范畴,OpenCV是一个非常强大的图形处理库,比较适合当前这个需求。因为之前也没接触过图形处理这一块,基本上也是边学边做,主要是从处理思想去找对应的图形处理工具。
OpenCV支持多种语言,例如C++、Python,目前网络上比较多的参考文档都是基于C++,考虑到编程语言的简易程度,决定采用Python进行开发。考虑到需要发布HTTP服务给App端调用,最终Python程序需要集成到Django项目中。
所以最后采用的技术栈为:Python3.6 + opencv-python + numpy(用于支持矩阵运算),使用pip安装两个库:
pip install numpy
pip install opencv-python
思路分析
我们首先拿一张真实拍摄的二维码进行分析:
这张图片从肉眼来看,基本是一个正方形,用户基本是摄像头垂直于二维码上方拍摄,而不是倾斜拍摄,比较符合我们对客户的扫描结果预期。
如果我们可以拿到一张正方形的二维码图片,根据定位点和坐标点可以很容易构建坐标系去分割图像,获取每个点内的0/1值,从而构建一个新的二维码图像。
但是从该图片去建立坐标系时,可以发现该图片其实不是一个真正的正方形,并且连一个矩形都算不上,无法使用缩放的方式恢复正方形,从截图的二维码左右边长和红色框的长度比较可以看出来,左侧线段长度要比右侧线段短一些,所以连一个平行四边形都不算,这在后面我们选择图形变换算法时也是一个非常重要的决定项。
我们梳理一下解决思路,对于一张正常拍摄的完整二维码图像,我们需要进行以下步骤的处理来解析图像内容:
1.将图像转换成一个正方形
2.根据定位图形和坐标点信息建立坐标系
3.根据坐标系切割图像,并提取每一个单元格中的数据信息
4.根据提取的数据信息,重构一个标准的二维码图像
按照以上思路,我将程序主体拆分为以下三个部分,将在后续章节对每一个部分详细介绍
1.图像预处理
2.图像坐标系构建
3.数据读取和重构