iOS二维码扫描,你需要注意的两件事

在 iOS7 以前,在iOS中实现二维码和条形码扫描,我们所知的有,两大开源组件ZBar与ZXing. 这两大组件我们都有用过,这里总结下各自的缺点:

  • ZBar

ZBar在扫描的灵敏度上,和内存的使用上相对于ZXing上都是较优的,但是对于 “圆角二维码” 的扫描确很困难。如:

  • ZXing

ZXing 是 Google Code上的一个开源的条形码扫描库,是用java设计的,连Google Glass 都在使用的。但有人为了追求更高效率以及可移植性,出现了c++ port. Github上的Objectivc-C port,其实就是用OC代码封装了一下而已,而且已经停止维护。这样效率非常低,在instrument下面可以看到CPU和内存疯涨,在内存小的机器上很容易崩溃。

  • AVFoundation

AVFoundation无论在扫描灵敏度和性能上来说都是最优的,所以毫无疑问我们应该切换到AVFoundation,需要兼容iOS 6或之前的版本可以用zbar或zxing代替。

下面介绍本文的重点,无论你是用以上哪一种或其他的解决方案,都需要知道下面两点。

1. 图片很小的二维码

以前测试提了一个bug,说有二维码扫不了,拿到二维码一看,是个很小的二维码,边长不到1cm,于是就修改了 sessionPreset 为 1080p 的,当时用的是ZXing, 当把图片质量改清楚时,也造成了性能的下降,基本打开扫描界面就会报memoryWarning,但是也确实解决了小二维码扫描的问题。

AVCaptureSession 可以设置 sessionPreset 属性,这个决定了视频输入每一帧图像质量的大小。

  • AVCaptureSessionPreset320x240
  • AVCaptureSessionPreset352x288
  • AVCaptureSessionPreset640x480
  • AVCaptureSessionPreset960x540
  • AVCaptureSessionPreset1280x720
  • AVCaptureSessionPreset1920x1080

以上列举了部分的属性值,分别代表输入图片质量大小,一般来说AVCaptureSessionPreset640x480就够使用,但是如果要保证较小的二维码图片能快速扫描,最好设置高些,如AVCaptureSessionPreset1920x1080(就是我们常说的1080p).

2. scanCrop

另一个提升扫描速度和性能的就是设置解析的范围,在zbar和zxing中就是scanCrop, AVFoundation中设置 AVCaptureMetadataOutput 的 rectOfInterest 属性来配置解析范围。

最开始我按照文档说的按照比例值来设置这个属性,如下:


1

2

3

4

5

6

CGSize size = self.view.bounds.size;

CGRect cropRect = CGRectMake(40, 100, 240, 240);

captureOutput.rectOfInterest = CGRectMake(cropRect.origin.x/size.width,

                                         cropRect.origin.y/size.height,

                                         cropRect.size.width/size.width,

                                         cropRect.size.height/size.height);

但是发现, Ops, 好像不对啊,扫不到了,明显不正确呢,于是猜想: AVCapture输出的图片大小都是横着的,而iPhone的屏幕是竖着的,那么我把它旋转90°呢:


1

2

3

4

5

6

CGSize size = self.view.bounds.size;

CGRect cropRect = CGRectMake(40, 100, 240, 240);

captureOutput.rectOfInterest = CGRectMake(cropRect.origin.y/size.height,

                                         cropRect.origin.x/size.width,

                                         cropRect.size.height/size.height,

                                         cropRect.size.width/size.width);

OK,貌似对了,在iPhone5上一切工作良好,但是在4s上,或者换了sessionPreset的大小之后,这个框貌似就不那么准确了, 可能发现超出框上下一些也是可以扫描出来的。 再次猜想: 图片的长宽比和手机屏幕不是一样的,这个rectOfInterest是相对于图片大小的比例。比如iPhone4s屏幕大小是 640x960, 而图片输出大小是 1920x1080. 实际的情况可能就是下图中的效果:

上图中下面的代表iPhone4s屏幕,大小640x960, 上面代表AVCaptureVideoPreviewLayer中预览到的图片位置,在图片输入为1920x1080大小时,实际大小上下会被截取一点的,因为我们AVCaptureVideoPreviewLayer设置的videoGravity是AVLayerVideoGravityResizeAspectFill, 类似于UIView的UIViewContentModeScaleAspectFill效果。

于是我对大小做了一下修正:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

CGSize size = self.view.bounds.size;

CGRect cropRect = CGRectMake(40, 100, 240, 240);

CGFloat p1 = size.height/size.width;

CGFloat p2 = 1920./1080.;  //使用了1080p的图像输出

if (p1 < p2) {

  CGFloat fixHeight = bounds.size.width * 1920. / 1080.;

  CGFloat fixPadding = (fixHeight - size.height)/2;

  captureOutput.rectOfInterest = CGRectMake((cropRect.origin.y + fixPadding)/fixHeight,

                                              cropRect.origin.x/size.width,

                                              cropRect.size.height/fixHeight,

                                              cropRect.size.width/size.width);

else {

    CGFloat fixWidth = bounds.size.height * 1080. / 1920.;

    CGFloat fixPadding = (fixWidth - size.width)/2;

    captureOutput.rectOfInterest = CGRectMake(cropRect.origin.y/size.height,

                                              (cropRect.origin.x + fixPadding)/fixWidth,

                                              cropRect.size.height/size.height,

                                              cropRect.size.width/fixWidth);

}

经过上面的验证,证实了猜想rectOfInterest是基于图像的大小裁剪的。

3. 小结

scanCrop对于扫描来说是比较重要的,试想图片截小点来解析是不是理论上就会更快了呢。网络上貌似很难搜到关于scanCrop的详解,希望对看到的人有帮助。

时间: 2024-09-30 04:30:37

iOS二维码扫描,你需要注意的两件事的相关文章

Ios二维码扫描(系统自带的二维码扫描)

Ios二维码扫描 这里给大家介绍的时如何使用系统自带的二维码扫描方法和一些简单的动画! 操作步骤: 1).首先你需要搭建UI界面如图:下图我用了俩个imageview和一个label 2).你需要在你当前的控制器中导入 #import <AVFoundation/AVFoundation.h> <AVCaptureMetadataOutputObjectsDelegate>代理 3).在@interface中定义 @property (nonatomic,strong)AVCapt

IOS二维码扫描IOS7系统实现

扫描相关类 二维码扫描需要获取摄像头并读取照片信息,因此我们需要导入系统的AVFoundation框架,创建视频会话.我们需要用到一下几个类: AVCaptureSession 会话对象.此类作为硬件设备输入输出信息的桥梁,承担实时获取设备数据的责任 AVCaptureDeviceInput 设备输入类.这个类用来表示输入数据的硬件设备,配置抽象设备的port AVCaptureMetadataOutput 输出类.这个支持二维码.条形码等图像数据的识别 AVCaptureVideoPrevie

iOS 二维码扫描报错问题之一

iOS 开发中在导入第三方的二维码扫描 ZBarSDK在模拟器能正常运行,但真机调试的过程中可能会报错,报错的信息如下目前的找到的一种解决办法如下图所示:在Build Settings里面搜bit  在BuildOptions里面修改Enable Bitcode为No,这样真机就可以正常运行了,如下图所示: 修改之后目前真机上可以正常运行

ios 二维码扫描

https://github.com/bmorton/ZBarSDK 我是用ZBar做的二维码扫描 其他的SDK也可以 首先是导入库文件: 1.AVFoundation.framework 2.CoreMedia.framework 3.CoreVideo.framework 4.QuartzCore.framework 5.libiconv.dylib 这个5个库文件 在ViewController.h 导入#import "ZBarSDK.h" 并且 继承 <ZBarRead

iOS二维码扫描的实现(Swift)

随着二维码的普遍使用,二维码扫描也成为了很多app的一个基本功能,本篇主要来介绍一下如何实现一个简单的二维码扫描功能.本文使用了XCode自带的AVFoundation 库,利用Swfit语言实现. 实现的步骤如下: 1.获取视频设备(Video) 在二维码扫描中,我们的输入流是视频.我们需要enable视频设备来获取相应的元数据. 2. 创建Session来处理视频的输入输出流 3. 创建输入输出流,并添加至Session中 4. 处理二维码数据 该方法是AVCaptureMetadataOu

iOS二维码扫描

测试环境:iPhone 5s  iOS7.1 首先添加框架AVFoundation.framework,然后导入自定义类CMCaptureViewController.h.CMCaptureViewController.m,以及用到的图片资源:[email protected].[email protected]. 用的时候只需要切换到二维码视图控制器CMCaptureViewController即可,会跳到二维码扫描界面 如: 1 [self presentViewController:cap

iOS 二维码扫描 zBarsdk 不支持64位 missing required architecture x86_64 in file

闲话少讲,实际上ios7以上是支持原生api扫描二维码的,所以我觉得这就是为什么zbarsdk没有继续更新的原因. 百度一下,说修改架构什么的还是有的,但貌似没说到点子上,还是老外的解决方法牛逼. 第一:问题的提出,给了很多解决方法: http://stackoverflow.com/questions/12506671/zbar-sdk-is-not-working-in-ios6/12753812#12753812 stackoverflow的方法还是不错的. 这个也不错:http://ww

iOS AV Foundation 二维码扫描 02 扫码

AVFoundation支持以下一维和二维码的扫描: QR code Aztec EAN13 EAN8 UPC-E PDF417 Code 93 Code 39 Code 39 mode 41 QR code就是我们所熟知的二维码. 打开ViewController.m,添加以下实例变量: AVCaptureMetadataOutput *_metadataOutput; 当从视频帧中检测到元数据时,AVCaptureMetadataOutput会调用应用程序的回调函数.AV Foundatio

iOS开发-二维码扫描和应用跳转

iOS开发-二维码扫描和应用跳转 序言 前面我们已经调到过怎么制作二维码,在我们能够生成二维码之后,如何对二维码进行扫描呢? 在iOS7之前,大部分应用中使用的二维码扫描是第三方的扫描框架,例如ZXing或者ZBar.使用时集成麻烦,出错也不方便调试.在iOS7之后,苹果自身提供了二维码的扫描功能,从效率上来说,原生的二维码远高于这些第三方框架.本文讲解如何使用原生框架实现二维码扫描功能,并且进行扫描后的项目跳转.ps:本期的源代码会在文章结尾给出链接 扫描相关类 二维码扫描需要获取摄像头并读取