本文引用自“蚂蚁金服科技”公众号,原文由支付宝技术团队原创分享。 本次收录时有改动。

1、引言

最早接触2维码扫码功能,是在2011年,那会移动互联网正是起步阶段,大家都感觉智能手机可以更强大,但到底要做些什么功能,都是在探索和创新。2维码扫描功能就是这些创新功能之一。

当然,2维码扫描说到底还是图像识别,这种技术不是一般的公司能搞定的,所以大家用的最多的2维码扫描库就是ZXing。这个库,很多人应该非常熟悉,用过这个库的人,基本都记住了下面这个图片(ZXing的logo)。

▲ ZXing工程的logo

这个库的使用前题就是需要手机摄像头有自动对焦功能,那会手机成本还没现在这么低,所以自动对焦功能不是所有手机都具备,也就限制了2维码扫码功能在一些较低端的手机上的使用,同时也制约了扫码功能的普及。

后来的事情大家都知道了,微信这种社交IM越来越受欢迎,微信里可以用来扫码加好友的“扫一扫”功能,让2维码扫描功能几乎变成了IM软件的标配。

▲ 早期微信里的“扫一扫”功能

现在的微信,不仅可以扫2维友加好友,还可以扫码支付以及各种图像识别方面的功能,越做越丰富。2维码扫码功能从一个单一的图像识别技术,逐渐演变成了移动线联网的入口功能。

从去年开始,微信对2维码扫描功能进行了升级,不仅可以在UI上让用户知道被扫描2维码的中心点,还能同时识别最多3个2维码,相当强大。

▲ 现在的微信可以同时识别最多3个2维码(注意绿点)

如上图所示,原本大家都习以为常的2维码扫描功能,原来还可以做的这么友好。

正好看到支付宝分享的这篇2维码扫描优化文章,市面上真正分享这方面的技术的文章几乎没有,而2维码扫码加友作为IM中最常见的功能之一,对于即时通讯网的开发者来说,虽然不需要自已从底层开发,但了解这方面的知识,还是很有必要的。

本文要分享的是支付宝针对2维码扫描功能,在2维码残缺、变形、变色等等恶劣条件下,是如何提升扫码识别率、识别速度的技术实践总结。希望能带给你启发。

学习交流:

- 即时通讯/推送技术开发交流5群:215477170[推荐]

- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》

- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK

(本文同步发布于:http://www.52im.net/thread-3150-1-1.html)

2、技术背景

随着支付宝的线下场景不断扩大,收钱码、口碑、共享单车、充电宝、停车缴费等产品让我们的生活越来越便利。

二维码因为成本低、兼容性好成为了线上线上最主要的连接工具,也因此面临更多新的挑战。

因为二维码是一种点阵式信息编码方式,任何视觉上的缺损、弯曲以及光线作用都会极大的影响识别成功率,如果识别困难也就意味着用户可能选择放弃,影响支付体验也影响用户心智。

用户扫码体验的最关键的主要有以下几个因素:

  • 1)识别率:这是扫码服务的基础指标,识别率能直接体现识别能力,识别率如果无法提高意味着大量的用户将无法使用更便捷的服务;
  • 2)识别耗时:包括 app 启动耗时以及图像识别耗时,这是衡量一个用户从点击 app 到正确识别到内容耗时,每增加 1s,将有相当大量的用户放弃等待并离开;
  • 3)精准反馈:识别结果不仅需要及时反馈给用户,还需要非常精准,特别是在目前线下有多个二维码的场景下,需要避免用户二次操作。

本文将从以上三个方面,分享支付宝扫码技术团队是如何为用户打造一个又准又快又稳的极致扫码体验。

我们对用户反馈进行了大量统计分析,发现绝大部分识别失败都是因为二维码并不标准,并且很遗憾的是在使用我们早期的扫码版本进行识别率测试时发现识别率只有 60%。下面的文字,将首先从提高识别率的方向着手。

3、提高识别率策略1:优化桩点查找算法长宽比耐受

以往的扫码算法,检查长宽比例时允许差异 40%,但是由于使用前向误差,判断结果跟长宽的先后顺序相关,这会导致有些长宽比失调的码,横着扫不出来,但是旋转 90 度竖着却能扫出来了(^OMG^)。

优化策略总结:

  • 1)通过修改长宽比的判定规则,长宽比将不再受先后顺序影响;
  • 2)对于已知长度,修改规则将可接受的宽度范围扩大,增强长宽比的耐受。

在我们对比测试集中,识别率提高了 1% 左右。

4、提高识别率策略2:新增1:5:1桩点识别模式模式

在一张图片中,要找到二维码,关键在找二维码特征定位点: 

三个角的回字型图案,这就是二维码特征定位点。

中间区域的黑白色块比例是1:1:3:1:1:

以往的扫码算法,桩点识别是通过状态机 查找11311模式后 取中间位置确定x位置(此时扫描线在第一行11311比例处)在x位置纵向搜索11311模式, 确定y位置再以 (x,y) 位置横向搜索11311比例,修正x位置。

这种模式在桩点污损的情况下,识别能力较差只要在任何一次11311模式搜索中遇到干扰点,哪怕是一个像素的椒盐噪声也能使桩点查找失败。(支付宝蓝的桩点,会在蓝色区域产生大量噪点,导致识别率低下)

为此,我们新增了一种桩点识别方式。在状态机达到151模式的时候,开始尝试确认桩点。(此时扫描线在第一行151比例处)。

优化效果:

  • 1)新的查找方法将不再受桩点中心或边缘部分被污损的影响,支付宝蓝色桩点码识别率明显提升;
  • 2)修改后识别率整体提升了接近 1%,但识别失败的耗时有所提升。

5、提高识别率策略3:添加一种对角线过滤规则

在枚举所有可能桩点组合 O(N^3) 之前,对所有可疑桩点进行一次对角线检查过滤。由于桩点对角线也应该满足 11311模式 ,用这个规则做一次过滤可疑有效减少运算量,也就有效降低了识别成功和失败的耗时。

6、提高识别率策略4:基于 Logistic Regression 的二维码分类器

在以往的扫码算法中在拿到三个桩点后,基于夹角,长度偏差,单位长度查三个数值,用简单公式计算得到阈值,判断是否为可能的二维码,误判概率较大。

为此,我们引入机器学习中的逻辑回归算法模型。

基于支付宝丰富的二维码数据集,训练出逻辑回归模型,作为二维码分类器,明显降低了误判概率,也将明显降低无二维码时识别失败的耗时。

7、提高识别率策略5:修改跳行扫描的间隔数

由于输入的相机帧分辨率高,像素点多,运算量大,以往的扫码算法在水平跟垂直方向跳行采样进行计算。但在实际运算中,由于跳过了太多列,错过了11311模式中某些1位置的点,导致桩点查找失败。

我们通过将跳行计算行数修改为可配置项,通过线上 AB 灰度测试得到最合适的跳行策略,整体配置此跳行策略后,识别率得到明显提升。

上述优化在测试集的表现: 

综上优化:扫码核心识别能力,在7744张图片测试集上提高了6.95个百分点。

8、特殊策略优化

除此上述通用扫码优化之外,我们还对特殊场景扫码能力进行提高。

8.1 畸变?不怕不怕!

线下场景复杂多变。饮料瓶身上变形的二维码、超市小票卷起边角弯曲的二维码、路边小贩凹凸不平甚至折叠的二维码......这些畸变的二维码容易增加识别难度,甚至导致识别失败。

以往的扫码算法抗畸变策略中,先用透视变换关系建立映射关系。

优点是:适应性好,满足大多数应用场景。

不足也明显:对 Version 1 的码,因为映射关系退化为仿射变换,效果较差,手机必须和码平面平行才能方便识别。当物料表面不是平面的时候,效果较差。

优化策略:

  • 1)假设采样坐标系到二维码坐标系遵守一个更复杂的映射关系,并且假设物料表面的卷曲较小,通过使用二次函数可以较好的拟合这个映射关系;
  • 2)实际发票上的二维码版本普遍大于等于 7,高版本二维码具有多个辅助定位点,更利于构造二次映射表;
  • 3)基于以上推论,使用新的映射代替旧的透视变换,进行更精准的采样。

用新的策略,发票码这个场景的二维码识别能力提升明显。

▲注意:由于采用了增强算法,请对准二维码稍作等待

样本测试结果:

8.2 容错识别能力提升

商户或者供应商生成二维码后,通常会在二维码的中间部分贴上 Logo,这部分有可能会使二维码 Decode 时出错。

优化策略:

对于采样后拿到的 BitMatrix,对于中间部分一块矩形区域内的点,采用某些策略来改变中间点的值,使它能够通过容错边界的检查。目前采用两种策略,第一种是反转,第二种是每一个点随机取值。目前所取的矩形区域是长、宽的四分之一。

通过此项优化后,扫码的容错能力也得到明显提升。

9、更小的识别耗时

针对识别效率,我们使用了GPU计算二值化,降低识别单帧耗时。

所谓图像二值化就是将图像上的像素点的灰度值设置为 0 或 255,也就是将整个图像呈现出明显的只有黑和白的视觉效果。下图左边为原图,右边是二值化处理过的图。

在扫码算法解码前,有二值化计算,图像的二值化计算能使图像中数据量大为减少,并弱化图像模糊、颜色对比度不强、光线过强/太弱、图像污损等情况下其他信息的干扰,更利于检测识别。

传统算法是在 CPU 上进行二值化运算,非常消耗 CPU 资源,但其实 GPU 更擅长大规模并行计算,所以我们选择使用 GPU 来做二值化计算。在安卓平台上使用 RenderScript,iOS 平台上使用 Metal,都是很底层的框架。

1)iOS优化结果:统一电池、角度、光线等环境变量, 在iPhone6上测试扫码核心5种摄像头二值化算法。

表现如下: 

可以看出,在图像二值化方面 Metal 有相当高的优势,相比原来的单纯 CPU 处理快了接近 150%, 同时降低了近50个百分点的CPU资源。

2)Andriod优化结果:由于Android机型众多,我们抽取了线上数据,可以看到GPU 在二值化处理中显著降低了单帧耗时30%以上。

10、算法分级、场景分类、科学调度

线下物料千奇百怪,扫码算法为了解决一些不理想的场景,如二维码有遮挡、污损、模糊或角度很不好的特殊情况,需要使用一些比较耗时但比较强大的算法,但普通情况不需要这些算法。

所以,我们对识码算法定了优先级,通过时间推移、跳帧触发等方式调度。

优先级:

  • 1)高优先级:每帧执行;
  • 2)中优先级:降帧率执行;
  • 3)低优先级:低帧率执行。

不同优先级的功能执行时机可配置。不同功能属于哪个优先级可配置

特殊场景算法能力:

  • 1)反色码识别能力;
  • 2)容错边界码识别能力;
  • 3)污损桩点识别能力等;
  • 4)条码识别能力。

附录:更多阿里团队分享的文章

《社交软件红包技术解密(七):支付宝红包的海量高并发技术实践》

《阿里钉钉技术分享:企业级IM王者——钉钉在后端架构上的过人之处》

《来自阿里OpenIM:打造安全可靠即时通讯服务的技术实践分享》

《淘宝技术分享:手淘亿级移动端接入层网关的技术演进之路》

《阿里技术分享:深度揭秘阿里数据库技术方案的10年变迁史》

《阿里技术分享:阿里自研金融级数据库OceanBase的艰辛成长之路》

《作者谈《阿里巴巴Java开发手册(规约)》背后的故事》

《淘宝技术分享:手淘亿级移动端接入层网关的技术演进之路》

《《阿里巴巴Android开发手册(规约)》背后的故事》

《手机淘宝消息推送系统的架构与实践(音频+PPT) [附件下载]》

《重磅发布:《阿里巴巴Android开发手册(规约)》[附件下载]》

《阿里技术结晶:《阿里巴巴Java开发手册-v1.6.0-泰山版》[附件下载]》

(本文同步发布于:http://www.52im.net/thread-3150-1-1.html)

难得干货,揭秘支付宝的2维码扫码技术优化实践之路相关推荐

  1. 【Redis版】spring boot高性能实现二维码扫码登录(中)

    作者: 刘冬 来源:http://www.cnblogs.com/GoodHelper/p/8643071.html 前言 本打算用CountDownLatch来实现,但有个问题我没有考虑,就是当用户 ...

  2. spring boot高性能实现二维码扫码登录(中)——Redis版

    前言 本打算用CountDownLatch来实现,但有个问题我没有考虑,就是当用户APP没有扫二维码的时候,线程会阻塞5分钟,这反而造成性能的下降.好吧,现在回归传统方式:前端ajax每隔1秒或2秒发 ...

  3. spring boot高性能实现二维码扫码登录(上)——单服务器版

    前言 目前网页的主流登录方式是通过手机扫码二维码登录.我看了网上很多关于扫码登录博客后,发现基本思路大致是:打开网页,生成uuid,然后长连接请求后端并等待登录认证相应结果,而后端每个几百毫秒会循环查 ...

  4. 支付宝支付-当面付之扫码支付「扫码支付」

    前言 支付宝支付-沙箱环境使用 支付宝支付-支付宝PC端扫码支付 支付宝支付-手机浏览器H5支付 支付宝支付-当面付之扫码支付「本文」 当面付包含两种支付方式:商品条形码支付 + 扫码支付 经过前面两 ...

  5. 对支付宝微信们来说,扫码支付限额 500 元新规意味着什么?

    点击上方"CSDN",选择"置顶公众号" 关键时刻,第一时间送达! 12月27日下午,据中国人民银行(下称央行)网站消息,将于近日发布关于印发<条码支付业 ...

  6. 移动二维码支付 推进二维码扫码智能POS

    现如今:银币.再到纸币,演变到"钱"变得越来越轻薄.在现在这个移动支付市场中,互联网技术的支撑下,刷手机乘公交.刷支付宝买菜购物.缴水电费--日常生活中使用"现金&quo ...

  7. PHP实现二维码扫码登录

    实现客户端扫码登录分为下列四步: 1.    Web页面生成二维码 生成的二维码中必须要包含一个用于唯一标识用户的数据,这个唯一标识是为了确保将客户端(手机)与web网页绑定,避免其他人登录了你的账号 ...

  8. C++实现二维码扫码登录

    实现客户端扫码登录分为下列四步: 1.    Web页面生成二维码 生成的二维码中必须要包含一个用于唯一标识用户的数据,这个唯一标识是为了确保将客户端(手机)与web网页绑定,避免其他人登录了你的账号 ...

  9. thinkphp5+php微信公众号二维码扫码关注推广二维码事件实现

    thinkphp5微信公众号二维码扫码关注推广二维码事件实现, 给出实现的全部方法: 获取二维码,让微信公众号跳转到以下代码的code方法即可,用户点击二维码后,通过二维码获取关注用户信息及二维码推广 ...

  10. 应用宝ysdk微信二维码扫码登录没有回调问题

    在更新ysdk版本的时候,发现新版本ysdk增加了微信二维码扫码登录,但是打包测试发现并没有登录回调. 接下来就开始排查了,检查了生命周期都没有问题,那问题出现在哪里呢?用ysdk提供的demo换上我 ...

最新文章

  1. 【c语言】转义字符的使用
  2. 传道、授业、解惑:俞士纶院长参加数据科学研究院第五届“院长接待日”
  3. SaltStack 学习笔记 - 第四篇: SaltStack常用模块
  4. DPDK vhost-user研究(十三)
  5. cuda版本的word2vec
  6. sql 某列数据全部为0则不显示该列_数据产品经理养成记(五):汇总分析
  7. 哈希表添加哈希表(Hash Table,也叫散列表),是根据键(Key)而直接访问在内存存储位置的数据结构。typedef enum{ HASH_OK, -icoding
  8. 高校教师职称制度将迎重大改革,教师怎么看?
  9. mysql 5.6.21不能选择安装路径_mysql5.6.21服务器安装图解(选择安装和数据目录)
  10. php mysql设计中验证码的实现_php如何实现验证码功能
  11. Java线程池关闭1-shutdown和isTerminated
  12. MacOS Big Sur 11.4 (20F71) OC 0.7.0 / Cl 5135 / PE 三分区原版黑苹果镜像
  13. RabbitMQ消息队列之RPC调用
  14. 多层陶瓷电容器用处_陶瓷电容器作用详解
  15. spreadsheet php,关于 PhpSpreadsheet 简单教程
  16. 全景制作平台,krpano全景图下载并快速关联漫游
  17. 文件系统 fsck和e2fsck使用-小白实操记录
  18. 【CTF资料-0x0002】PWN简易Linux堆利用入门教程by arttnba3
  19. 【Docker】谷粒商城笔记记录:P104运行ElasticSearch容器
  20. mysql的binlog太大太多占用大量磁盘的解决

热门文章

  1. Android开源项目及库汇总
  2. 【原型设计】第一节:Axure RP9 下载安装、汉化和激活使用的方法教程
  3. 群体智能算法之蝙蝠算法
  4. PilotEdit 破解版下载|PilotEdit(文本编辑器) 中文破解版 v11.8下载(含注册机)
  5. 只需2行代码,1分钟教你实现微信多开
  6. 打开英伟达控制面板超时打不开解决办法
  7. [20141216]sqlplus的set appinfo.txt
  8. C# .NET 如何修改代码字体
  9. Ubuntu20.10 安装RedNotebook,一款不错的日记本
  10. 【深度学习】PyCorrector中文文本纠错实战