二维码识别率优化实践

发表于 1年以前  | 总阅读数:436 次

概述

长按图片识别二维码在移动端是很常见的操作,长按后需要对图片进行识别,并且将二维码中所包含的数据解码出来。在我们的业务场景中,是通过点击图片进入大图预览页面。长按大图预览的图片,会识别图片中的二维码,并且显示有跳转按钮,提示用户可以跳转二维码对应的页面。

但是,在现有业务场景中,要求图片中二维码不能在视觉上占据太大的位置,所以只能以很小的尺寸显示在下面。为了更好的配合公司现有业务,保证对图片中二维码的识别率,所以需要对二维码识别进行优化。

优化方案

方案总体分为探测和识别两个核心流程,探测流程主要由图像处理算法,以及OpenCV来实现,识别流程主要由系统AVFoundation库的CIDetector来实现。先将二维码所在区域探测出来,随后对这个区域进行识别增强的处理,以实现模糊、较小的二维码的识别。

探测流程

因为不是每一张图片上都有二维码,探测的意义在于,查找图片中是否有二维码,以及二维码在图片中的位置。从而进行后续的针对性处理。以下,任何一步探测有结果,都将进入识别流程中,并且将探测到的位置传给识别方法。

  1. 第一次探测。转灰度图,通过OpenCVcvtColor函数,将四通道的RGBA图片,转换为单通道的灰度图。
  2. 第二次探测。通过算法进行直方图均衡化(非自适应,并且限制对比度),目的是让图片内轮廓清晰。
  3. 第三次探测。通过算法进行伽马变换,目的是增强图像对比度。
  4. 第四次探测。将原始灰度图的下面20%的右半部分,clone到一个新的Mat对象中,并且进行3.5倍的resize。将得到后的灰度大图调用detect进行探测。
  5. 第五次探测。将原始灰度图的下面20%的左半部分,clone到一个新的Mat对象中,并且进行3.5倍的resize。将得到后的灰度大图调用detect进行探测。
  6. 探测结束。在二维码的定位图形、码元等核心信息没有受损的前提下,这时候基本断定这张图片上没有二维码。

需要注意的是,在探测方案中,为什么选取下面左右两边的20%着重进行探测。是因为根据对公司实际业务的调研,绝大多数的二维码都是在图片的右下角位置,其次是左下角。以公司业务为例,目前没见过将二维码放在图片中间的场景。

识别流程

  1. 探测到二维码后,会将当时用来探测的图片,以及探测到的二维码区域传递给识别方法。传递过来的图片,可能是resize后的大图,对这些大图识别率会更高。
  2. 从传递过来的图片上,根据二维码所在区域的坐标系,将二维码所在的部分,重绘到一个新的位图对象上。为了保证识别效果,会在重绘时加上一个15的外边距,以保证二维码Quiet Zone的特性。
  3. 用重绘后的二维码,调用AVFoundationCIDetector进行识别,并获取识别后的字符串。

为什么不把探测和识别都交给OpenCV来做。这是因为经过我的测试,我发现OpenCV的识别率较低,远不如CIDetector的识别率。所以,只将探测部分交给OpenCV,但不让OpenCV去识别二维码。

根据OpenCVdetect函数的源码进行查看,发现OpenCV的探测是基于定位符号进行探测的,分为横向和纵向两个方向进行探测,使用OpenCV进行探测是不错的选择。但是OpenCV识别率并不高,所以用OpenCV进行探测,结合AVFoundation进行识别的方案,是一个比较不错的策略。

代码实现

方案总体代码量较大,这里列出了一些主要方法的代码实现。探测方法内部实现,会进行不同程度的增强扫描和识别。方案中使用了一些OpenCVAPI,可以通过OpenCV官方文档了解下API的定义和调用。

生成灰度图

把传入的图片转为OpenCV可以识别的Mat的灰度图,灰度图色彩通道只有一个,在进行后续计算上,会节省很多性能。随后进入后续的探测部分,探测到二维码后,会将二维码拼接业务参数,并在主线程中返回给调用方。

方法的核心逻辑有两部分,一是将UIImage转为OpenCV类型的Mat对象,二是将四个颜色通道的彩色图,转为单个颜色通道的灰度图。二值图和灰色图是不同的,灰色图是单个通道,每个单位占8位,表示范围是0~255。二值图只有0~1的展示,所以识别速度会相对快一些。

这里简要讲一下颜色通道的概念,CV_8UC4表示RGBA四颜色通道,占用32位空间。同样的,也有三颜色通道RGB,以及两个通道和单通道,两个通道的CV_8UC2我没用过,不知道什么场景下会需要。cvtColor函数是OpenCV中进行颜色空间转换的函数,可以将彩色图修改为灰度图。

CGFloat rows = sourceImage.size.height;
CGFloat cols = sourceImage.size.width;

cv::Mat cvMat(rows, cols, CV_8UC4);
CGColorSpaceRef colorSpace = CGImageGetColorSpace(sourceImage.CGImage);
CGContextRef context = CGBitmapContextCreate(cvMat.data,
                                             cols,
                                             rows,
                                             8,
                                             cvMat.step[0],
                                             colorSpace,
                                             kCGImageAlphaNoneSkipLast | kCGBitmapByteOrderDefault);
if (context == NULL) {
    return cvMat;
}
CGContextDrawImage(context, CGRectMake(0, 0, cols, rows), sourceImage.CGImage);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);

cv::Mat grayMat;
cv::cvtColor(cvMat, grayMat, cv::COLOR_BGR2GRAY);

return grayMat;

resize

下面代码是对左下和右下两个部分进行探测的逻辑,代码中scale代表局部放大的倍数。根据公司业务,先从右下角进行放大及探测。放大需要获取到像素的行数和列数,这些Mat提供了对应的API

下面是核心逻辑的梳理。

  1. 通过rowRangecolRange获取到需要增强扫描的像素,例如右下角区域的横排和竖排的像素。
  2. 调用clone将像素取出,并赋值给Mat
  3. 调用resize函数扩大到对应的倍数。

需要注意的是,在下面方法的第二段,对右下角进行了强制识别。是一个容错处理,属于“闭眼识别”。第一步无论是否有探测的结果,都会对右下角进行二维码的识别。因为在测试中,对于非常小的二维码,会出现对于resize后的灰度图,探测不到但是能识别到的情况。所以,增加了右下角没有探测到,但依然进行强制识别的逻辑。

CGFloat scale = 3.5f;

cv::Mat copyMat = grayMat.rowRange(grayMat.rows * 0.8, grayMat.rows).colRange(grayMat.cols * 0.5, grayMat.cols).clone();
cv::Mat resizeMat;
cv::resize(copyMat, resizeMat, cv::Size(grayMat.cols * scale * 0.5, grayMat.rows * 0.2 * scale));
NSString *result = [self qrcodeQRCodeForGrayMat:resizeMat];

/// 闭眼识别
if (!result.length) {
    UIImage *image = [self UIImageFromCVMat:resizeMat];
    result = [self readQRCodeWithImage:image
                      detectorAccuracy:CIDetectorAccuracyHigh];
}

if (!result.length) {
    copyMat = grayMat.rowRange(grayMat.rows * 0.8, grayMat.rows).colRange(grayMat.cols * 0.f, grayMat.cols * 0.5).clone();
    cv::resize(copyMat, resizeMat, cv::Size(grayMat.cols * scale * 0.5, grayMat.rows * 0.2 * scale));
    result = [self qrcodeQRCodeForGrayMat:resizeMat];
}

return result;

识别

识别方法会接收传入的二维码坐标系,裁剪出二维码的位置并做相应的处理,随后交给AVFoundation去识别。当探测不到时,不会进入识别的环节。

当探测到二维码时,可以通过output获取二维码的四个点,顺序是左上、右上、右下、左下,顺时针存储。在原有的四个点外面,加上15个单位的Quiet Zone,随后会将这部分图片裁剪出来,并交给AVFoundation去识别。加入Quiet Zone的原因在于,有Quiet Zone的二维码,识别率会比没有的好。

vector<cv::Point> output;
if (output.empty()) {
    return nil;
}

/// 左上
cv::Point point0 = output[0];
/// 右下
cv::Point point2 = output[2];

CGRect rect = CGRectMake(point0.x, point0.y, point2.x - point0.x, point2.y - point0.y);
CGRect insetRect = CGRectInset(rect, -15, -15);

/// rect合法性检查
if (insetRect.origin.x > 0 && insetRect.origin.y > 0 && insetRect.size.width > 0 && insetRect.size.height > 0) {
    rect = insetRect;
}

UIImage *image = [self UIImageFromCVMat:grayMat];
image = [self drawInRect:rect sourceImage:image];
NSString *result = [self readQRCodeWithImage:image
                            detectorAccuracy:CIDetectorAccuracyLow];
return result;

Mat转换

iOS中进行OpenCV开发的过程中,UIImageMat的相互转换是经常需要的。UIImageMat在生成灰度图的过程中已经涉及,下面的方法是将Mat转为UIImage。核心逻辑就是将Matdata数据,通过CGImageCreate函数创建CGImage完成的。

CGColorSpaceRef colorSpace;
CGBitmapInfo bitmapInfo;
size_t elemsize = cvMat.elemSize();
if (elemsize == 1) {
    colorSpace = CGColorSpaceCreateDeviceGray();
    bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrderDefault;
}
else {
    colorSpace = CGColorSpaceCreateDeviceRGB();
    bitmapInfo = kCGBitmapByteOrder32Host;
    bitmapInfo |= (elemsize == 4) ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNone;
}

NSData *data = [NSData dataWithBytes:cvMat.data length:elemsize * cvMat.total()];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);

/// 根据Mat创建CGImage
CGImageRef imageRef = CGImageCreate(cvMat.cols,           // width
                                    cvMat.rows,           // height
                                    8,                    // bits per component
                                    8 * cvMat.elemSize(), // bits per pixel
                                    cvMat.step[0],        // bytesPerRow
                                    colorSpace,           // colorspace
                                    bitmapInfo,           // bitmap info
                                    provider,             // CGDataProviderRef
                                    NULL,                 // decode
                                    false,                // should interpolate
                                    kCGRenderingIntentDefault // intent
                                    );
UIImage *finalImage = [UIImage imageWithCGImage:imageRef];

CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);

return finalImage;

收益

统计方案

二维码识别率的统计比较困难,因为场景是在长按图片识别二维码,但图片中是否有二维码,我们并不知道。并且,用户长按操作可能是为了保存图片,并非识别二维码。

所以,数据分析通过A/B测的方式进行,通过分桶方式实现,两个桶分别为50%的用户量。通过这种方式,可以得出一个基本准确的识别数据。

收益数据

数据从两个维度来统计,识别速度和识别率,数据如下。

  • 优化方案相对原有方案,识别速度提升6.8%
  • 优化方案相对原有方案,识别率提升12%

识别速度OpenCV表现并不是很明显,因为只是通过灰度图的方式提升了识别速度,但如果到了探测的阶段,对速度还是有一定影响的,收益为正数就很不错了。

识别率提升还是不错的,因为是A/B方案的对比,我们并不知道单个方案的真实识别率。但经过我们自测,运营常用的几个存在复杂二维码的账号中,挨个试二维码的识别,自测识别率为100%

展望

除了灰度图,也考虑过通过OTSU算法将灰度图转为二值图,但是发现二值图在图片清晰度不够的情况下,定位符号比较模糊的位置会被转换为白色。这样,定位符号就会缺一个角,不能构成特定比例,导致识别率出现明显下降。既然二值图的方案都不可行,那就别考虑识别轮廓了,所以就乖乖的用灰度图做识别了。

后续计划加入中值滤波后,再进行OTSU算法做二值化,这样转换后的二值图效果会好很多。

本文由哈喽比特于1年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/I9MpbxNvI4fMvbrlX5WhSw

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:7月以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:7月以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:7月以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:7月以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:7月以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:7月以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:7月以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:7月以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:7月以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:7月以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:7月以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:7月以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:7月以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:7月以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:7月以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:7月以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:7月以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:7月以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:7月以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:7月以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  236874次阅读
vscode超好用的代码书签插件Bookmarks 1年以前  |  6883次阅读
 目录