【ArchSummit架构师峰会】探讨数据与人工智能相互驱动的关系>>> 了解详情
写点什么

AOE 工程实践:银行卡 OCR 里的图像处理

  • 2019-09-04
  • 本文字数:2407 字

    阅读完需:约 8 分钟

AOE工程实践:银行卡OCR里的图像处理

近期我们开发了一个银行卡 OCR 项目。需求是用手机对着银行卡拍摄以后,通过推理,可以识别出卡片上的卡号。


工程开发过程中,我们发现手机拍摄以后的图像,并不能满足模型的输入要求。以 Android 为例,从摄像头获取到的预览图像是带 90 度旋转的 NV21 格式的图片,而我们的模型要求的输入,只需要卡片区域这一块的图像,并且需要转成固定尺寸的 BGR 格式。所以在图像输入到模型之前,我们需要对采集到的图像做图像处理,如下图所示:



在开发的过程中,我们对 YUV 图像格式和 libyuv 进行了研究,也积累了一些经验。下文我们结合银行卡 OCR 项目,讲一讲里面涉及到的一些基础知识:


  • 什么是 YUV 格式

  • 如何对 YUV 图像进行裁剪

  • 如何对 YUV 图像进行旋转

  • 图像处理中的 Stride

  • 如何进行缩放和格式转换

  • libyuv 的使用


想要对采集到的 YUV 格式的图像进行处理,首先我们需要了解什么是 YUV 格式。

什么是 YUV 格式

YUV 是一种颜色编码方法,YUV,分为三个分量:“Y” 表示明亮度(Luminance 或 Luma),也就是灰度值;“U”和“V” 表示的则是色度(Chrominance 或 Chroma)。主流的采样方式有三种,YUV4:4:4,YUV4:2:2,YUV4:2:0。


这部分专业的知识,网络上有详细的解释。我们简单理解一下,RGB 和 YUV 都使用三个值来描述一个像素点,只是这三个值的意义不同。通过固定的公式,我们可以对 RGB 和 YUV 进行相互转换。


工程里常见的 I420,NV21,NV12,都是属于 YUV420,每四个 Y 共用一组 UV 分量。YUV420 主要包含两种格式,YUV420SP 和 YUV420P。


  • YUV420SP,先排列 Y 分量,UV 分量交替排列,例如:NV12: YYYYYYYY UVUV 和 NV21: YYYYYYYY VUVU (上文中我们在安卓上采集到的图像就是这种格式)。

  • YUV420P,先排列 U(或者 V)分量,再排列 V(或者 U)分量。例如:I420: YYYYYYYY UU VV 和 YV12: YYYYYYYY VV UU。



YUV420SP 



YUV420P


了解了 YUV 的图像格式以后,我们就可以尝试对图片进行裁剪和旋转了。我们的想法是先在图片上裁剪出银行卡的区域,再进行一次旋转。


如何对 YUV 图像进行裁剪

YUV420SP 和 YUV420P 裁剪的过程类似,以 YUV420SP 为例,我们要裁剪图中的这块区域:



在图上看起来就非常明显了,只要找到裁剪区域对应的 Y 分量和 UV 分量,按行拷贝到目标空间里就可以了。



我们再来看一张图,是否可以用上面的方法来裁剪图中的这块区域呢?



答案是否定的,如果按照上面说的方法来操作,最后你会发现你保存出来的图,颜色基本是不对的,甚至会有内存错误。原因很简单,仔细观察一下,当 ClipLeft 或者 ClipTop 是奇数的时候,会导致拷贝的时候 UV 分量错乱。如果把错误的图像数据输入到模型里面,肯定是得不到我们期望的结果的。所以我们在做裁剪的时候,需要规避掉奇数的场景,否则你会遇到意想不到的结果。

如何对 YUV 图像进行旋转

对上文裁剪后的图像做顺时针 90 度旋转,相比裁剪,转换要稍微复杂一些。



基本方法是一样的,拷贝对应的 Y 分量和 UV 分量到目标空间里。



在了解了裁剪和旋转的方法以后,我们发现在学习的过程中不可避免地遇到了 Stride 这个词。那么,它在图像中的作用是什么呢?

图像处理中的 Stride

Stride 是非常重要的一个概念,Stride 指在内存中每行像素所占的空间,它是一个大于等于图像宽度的内存对齐的长度。如下图所示:



回过头来看我们上面说到的裁剪和旋转,是否有什么问题? 以 Android 上的 YV12 为例,Google Doc 里是这样描述的:



所以在不同的平台和设备上,需要按照文档和 stride 来进行计算。例如计算 Buffer 的大小,很多文章都是简单的 “*3/2” ,仔细考虑一下,这其实是有问题的。


如果不考虑 stride ,会有带来什么后果?如果 “运气” 足够好,一切看起来很正常。“运气”不够好,你会发现很多奇怪的问题,例如花屏,绿条纹,内存错误等等。这和我们平常工作中遇到的很多的奇怪问题一样,实际上背后都是有深层次的原因的。


经过裁剪和旋转,我们只需要把图像缩放成模型需要的尺寸,转成模型需要的 BGR 格式就可以了。

如何进行缩放和格式转换

以缩放为例,有临近插值,线性插值,立方插值,兰索斯插值等算法。YUV 和 RGB 之间的转换,转换的公式也有很多种,例如量化和非量化。这些涉及到专业的知识,需要大量的时间去学习和理解。


这么多的转换,我们是否都要自己去实现?


很多优秀的开源项目已经提供了完善的 API 给我们调用,例如 OpenCV,libyuv 等。我们需要做的是理解基本的原理,站在别人的肩膀上,做到心里有数,这样即使遇到问题,也能很快地定位解决。


经过调查和比较,我们选择了 libyuv 来做图像处理的库。libyuv 是 Google 开源的实现各种 YUV 与 RGB 之间相互转换、旋转、缩放的库。它是跨平台的,可在 Windows、Linux、Mac、Android 等操作系统,x86、x64、arm 架构上进行编译运行,支持 SSE、AVX、NEON 等 SIMD 指令加速。

libyuv 的使用

引入 libyuv 以后,我们只需要调用 libyuv 提供的相关 API 就可以了。 在银行卡 OCR 工程使用的过程中,我们主要遇到了 2 个问题:


1.在 Android 开发的初期,我们发现识别率和我们的期望存在一定的差距。我们怀疑是模型的输入数据有问题,通过排查发现是使用 libyuv 的时候,没注意到它是 little endian。例如这个方法:int BGRAToARGB(…),BGRA little endian,在内存里顺序实际是 ARGB。所以在使用的时候需要弄清楚你的数据在内存里是什么顺序的,修改这个问题后识别率达到了我们的预期。


2.在大部分机型上运行正常,但在部分机型上出现了 Native 层的内存异常。通过多次定位,最后发现是 stride 和 buffersize 的计算错误引起的。


通过银行卡 OCR 项目,我们积累了相关的经验。另外,由于 libyuv 是 C/C++ 实现的,使用的时候不是那么的便捷。为了提高开发效率,我们提取了一个 Vision 组件,对 libyuv 封装了一层 JNI 接口,包括了一些基础的转换和一些 sample,这样使用起来更加简单方便了。作为 AOE SDK 里的图像处理组件,还在不断开发和完善中。


欢迎大家来使用和提建议: https://github.com/didi/aoe


2019-09-04 18:312851

评论

发布
暂无评论
发现更多内容

干货 | 测试人职场晋升“潜规则”:15 年经验资深测试经理的职场忠告

霍格沃兹测试开发学社

干货 | 背熟这些 Docker 命令,面试再也不怕啦~

霍格沃兹测试开发学社

软件测试 | 测试开发 | 测试人生 | 年薪50w+ 并入职名企大厂,这是双非学历小哥哥给自己30岁的礼物

测吧(北京)科技有限公司

测试人生

LG稳居高地再布新棋 顺应需求领跑高端家电市场布局新生态

Geek_2d6073

解读《Benchmarking Hybrid OLTP&OLAP Database Systems》| StoneDB学术分享会

StoneDB

数据库 国产数据库 StoneDB 企业号九月金秋榜 9月月更

干货| app自动化测试之Andriod微信小程序的自动化测试

霍格沃兹测试开发学社

干货|APP自动化Android特殊控件Toast识别

霍格沃兹测试开发学社

软件测试 | 测试开发 | 测试人生 | 拿到多个 offer 从了一线互联网公司并涨薪70%,90后小哥哥免费分享面试经验~

测吧(北京)科技有限公司

测试人生

干货 | 读懂 Appium 日志,让测试效率翻倍!

霍格沃兹测试开发学社

TDengine 如何进行 SQL 写入?官方最全教程来了

TDengine

数据库 时序数据库 企业号九月金秋榜

WAIC|九章云极DataCanvas公司携因果学习技术成果精彩亮相!

九章云极DataCanvas

人工智能 开源 因果学习

软件测试 | 测试开发 | MockServer 服务框架设计

测吧(北京)科技有限公司

MockServer

软件测试 | 测试开发 | 项目倒排,跟工期不足say byebye~

测吧(北京)科技有限公司

测试人生

「九章云极DataCanvas」完成C+轮融资,用云中云战略引领数据智能基础软件升级

九章云极DataCanvas

机器学习 数据智能

DevSecOps 落地三部曲|小孩子才做选择,极狐GitLab 安全、高效全都要

极狐GitLab

DevOps 运维 安全 DevSecOps 极狐GitLab

干货 | 环境问题还是测试的老大难?两个步骤轻松搞定

霍格沃兹测试开发学社

2022 世界人工智能大会|人工智能与开源技术先锋论坛成功举办

Kyligence

人工智能大会 先锋科技论坛

Kyligence 联合创始人兼 CEO 韩卿荣获金融科技风云人物奖

Kyligence

金融科技大会

手把手教你如何进行拆解竞品

产品海豚湾

产品经理 需求分析 竞品分析 9月月更 市场调研

软件测试 | 测试开发 | 测试人生 | 从传统行业到名企大厂,薪资翻倍,我做到了

测吧(北京)科技有限公司

面试

软件测试 | 测试开发 | 测试人生 | 从外行到外包,从手工测试到知名互联大厂测开 这个90后小姐姐是怎么腾飞的?

测吧(北京)科技有限公司

测试人生

干货 | 解决 App 自动化测试的常见痛点(弹框及首页启动加载完成判断处理)

霍格沃兹测试开发学社

软件测试 | 测试开发 | 测试人生 | 疫情之下,1个月内涨薪50%拿下亿级流量金融上市公司新 offer,我柠檬了~

测吧(北京)科技有限公司

测试

软件测试 | 测试开发 | 专项测试技术初识Hook

测吧(北京)科技有限公司

测试

同频共振数据时代,AntDB数据库与永洪科技完成产品互认证

亚信AntDB数据库

数据库 AntDB 国产数据库 AntDB数据库

跟我一起学mybatis

楠羽

mybatis 笔记 9月月更

干货 | 谁懂这篇文,玩游戏还会卡顿?

霍格沃兹测试开发学社

字节前端必会面试题

夏天的味道123

JavaScript 前端

软件测试 | 测试开发 | 测试人生 | 毕业2年,拒绝独角兽入职名企大厂涨薪10万+,这个95后小姐姐好飒

测吧(北京)科技有限公司

测试人生

干货 | 移动端App自动化之App控件定位

霍格沃兹测试开发学社

CeresDB 技术架构简介

TRaaS

#开源项目

AOE工程实践:银行卡OCR里的图像处理_文化 & 方法_杨科_InfoQ精选文章