iOS6.0以后,二维码识别便抛弃了ZBar和ZXing,而是使用扫描灵敏度和性能都最优的AVFoundation框架。如果需要兼容iOS7.0以下版本,可以使用ZBar和ZXing,但是在这里就不再对它们多做赘述了。直奔主题,说一说怎么通过对AVFoundation的优化,进一步提高二维码识别的灵敏度和速度。
1.设置 sessionPreset 属性
测试的时候,有些二维码非常小,有的时候距离二维码比较远,都会造成无法正常识别二维码。距离远的还可以将手机凑近点,以提高扫描的灵敏度。但是二维码本身就小的,凑近了无法聚焦,离远了又无法识别,必然需要通过相机的像素进行优化。
AVCaptureSession 可以设置 sessionPreset 属性,这个决定了视频输入每一帧图像质量的大小。
- AVCaptureSessionPreset320x240
- AVCaptureSessionPreset352x288
- AVCaptureSessionPreset640x480
- AVCaptureSessionPreset960x540
- AVCaptureSessionPreset1280x720
- AVCaptureSessionPreset1920x1080
以上列举了部分的属性值,分别代表输入图片质量大小,一般来说AVCaptureSessionPreset640x480就够使用,但是如果要保证较小的二维码图片能快速扫描,最好设置高些,如AVCaptureSessionPreset1920x1080(就是我们常说的1080p)。
- AVCaptureSessionPreset3840x2160
另外还有一个属性值,是iOS9.0以后的,适合3840x2160(UHD 4K)视频输出,建议慎用,用不好的话,程序会崩。
2.设置rectOfInterest属性
AVCaptureMetadataOutput可以设置rectOfInterest属性,这个属性是用来限制二维码扫描范围的,一般设定的范围都是我们给定好的正方形大小。
_output.rectOfInterest =[self rectOfInterestByScanViewRect:imageView.frame];
或者:
_output.rectOfInterest =[self rectOfInterestByScanViewRect:CGRectMake(0.1, 0, 0.9, 1)];
现在对rectOfInterest属性的大小,进行了一些修正。代码如下:
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 = self.view.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 = self.view.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);
}
这样以来,确实大大提高了扫描的灵敏度,哪怕是二维码距离稍远也能够轻松扫描出结果。亲测有效,欢迎尝试。