现今我们的生活已经离不开了二维码了,无论是出行、购物、吃饭、娱乐等等都伴随着二维码的身影,二维码让我们的生活更便利,品质更高。人们出行只需要带上一部手机就可以完成几乎所有的需求,这就要提到关于二维码的扫描识别了。
通过swift学习后,写了一个小demo,以本文来记录一下原生二维码的扫描识别。
效果图如下:
demo地址在:https://github.com/ZZtimegoesby/ZZScanQRcode
1. 原生二维码扫描
iOS7之后AVFoundation提供了原生二维码扫描的功能,无论是在扫描灵敏度上还是性能上来说与之前的zbar和zxing等三方库相比都是最优的,所以对二维码的扫描识别开发用苹果原生是最好的,但是只限于是iOS7+系统。
1.1 二维码扫描需要的类:
二维码扫描需要导入AVFoundation框架import AVFoundation
。需要用到一下5个类:
- AVCaptureDevice 获取设备类
- AVCuptureSession 绘画对象类,承担实时获取设备数据的任务。
- AVCuptureDeviceInput 设备输入类。
- AVCaptureMetadataOutput 设备输出类,支持二维码、条形码等图像数据的识别。
- AVCaptureVideoPreviewLayer 图层类,可以快速呈现摄像头采集的原始数据。
通过以上5个类可以实现摄像头对二维码的扫描识别。
1.2 二维码扫描:
1)创建设备会话对象,用来配置设备的输入输出。
//创建会话对象 承担实时获取设备数据的责任
session = AVCaptureSession.init()
session.sessionPreset = AVCaptureSessionPresetHigh //设置高质量采集
2)遵守AVCaptureMetadataOutputObjectsDelegate
协议,获取手机摄像头设备作为输入设备,创建输出类,设置代理delegate
、有效的扫描区域和可识别的图像类型metadataObjectTypes
,将其添加到会话对象session
中。
//获取手机摄像头
device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
//设备输入类
let input = try! AVCaptureDeviceInput.init(device: device)
//设备输出类 支持二维码、条形码的扫描识别
output = AVCaptureMetadataOutput.init()
//设置
output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
//将输入、输出对象加入到会话中
session.addInput(input)
session.addOutput(output)
//只能在执行完上一步之后才能执行设置可识别数据的格式
output.metadataObjectTypes = [AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code]
//设置有效的扫描区域 注意:坐标系原点为右顶点,横为y,竖为x
output.rectOfInterest = CGRect(x: (height - scanWidth - 64)/2/height, y: (width - scanWidth)/2/width, width: scanWidth, height: scanWidth)
*注意:rectOfInterest(有效扫描范围)的坐标系有所不同,屏幕右上角为坐标原点,左上角位(0,1),左下角为(1,1),右下角为(1,0)。
3)创建图层类previewlayer
,实时获取摄像头数据并显示在屏幕上。
//创建图层类 可以快速呈现摄像头的原始数据
previewlayer = AVCaptureVideoPreviewLayer.init(session: session)
previewlayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
previewlayer?.frame = self.view.frame
self.view.layer.insertSublayer(previewlayer!, at: 0)
4)设置协议回调方法,当扫描到二维码/条形码时会触发代理方法,对得到的数据进行处理。
//扫描到二维码时调用
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
if metadataObjects.count > 0 {
//获取二维码数据对象
let metadata: AVMetadataMachineReadableCodeObject = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
}
}
以上就是关于手机相机二维码图像扫描的相关配置。
2. 相册中图片二维码的识别
1)需要用到UIImagePickerController
类得到手机相册控制器,所以首先需要导入imageIO框架import imageIO
,遵守两个协议UIImagePickerControllerDelegate
和UINavigationControllerDelegate
,模态跳转到手机相册。
//创建相册控制器
let imagepicker = UIImagePickerController()
imagepicker.delegate = self
self.present(imagepicker, animated: true, completion: nil)
2)配置协议回调方法,一个是当选择相册图片后会触发,一个是当点击取消后会触发。
//点击图片时触发该方法
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
//获取点击图片
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
//.....获取采集的二维码数据....//
self.dismiss(animated: true) {
//数据处理
}
}
//点击取消时调用该方法
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
self.dismiss(animated: true, completion: nil)
}
3)得到相册的图片后,利用扫描仪CIDetector
类对图片上的二维码进行识别,获取二维码上的数据message
。
//创建图片扫描仪
let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
//获取到二维码数据
let featureArr = detector?.features(in: CIImage.init(cgImage: image.cgImage!))
let feature = featureArr?.first as! CIQRCodeFeature //二维码图像特征
let message = feature.messageString!
以上完成了对手机相册图片二维码的识别。
3. 添加闪光灯及添加提示音
在demo中我还添加了开关闪光灯及添加提示音的功能。提示音需要用到AudioToolbox框架`import AudioToolbox。
var soundID: SystemSoundID = 0
let soundFile = Bundle.main.path(forResource: "scanSound", ofType: "wav")
//生成系统声音
AudioServicesCreateSystemSoundID(NSURL.fileURL(withPath: soundFile!) as CFURL, &soundID)
//播放提示音 带有震动
// AudioServicesPlayAlertSound(soundID)
//播放系统提示
AudioServicesPlaySystemSound(soundID)
闪光灯用上文的device
就可以了,实现较简单在这里就不一一写出来了。如果需要可以去下载demo来学习,我还没有封装成库,之后会改进,也欢迎给我提出一些demo的问题,我会去一一解决。能star一下最好了,谢谢了!!
二维码扫描识别集成demo地址:https://github.com/ZZtimegoesby/ZZScanQRcode
参考文章:http://www.jianshu.com/p/4772d3cb6a43