识别条形码\二维码
-
创建Session
let captureSession = AVCaptureSession() -
获取Device
let captureDevice = AVCaptureDevice.default(for: .video) -
创建DeviceInput
let deviceInput = AVCaptureDeviceInput(device: captureDevice) captureSession.addInput(deviceInput) -
创建CaputreOutput
let metaOutput = AVCaptureMetadataOutput.init() metaOutput.setMetadataObjectsDelegate(self, queue: captureQueue) metaOutput.metadataObjectTypes = [AVMetadataObject.ObjectType.code128] captureSession.addOutput(metaOutput) -
实现代理方法
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { // 这里处理识别结果逻辑 }
识别条形码\二维码并拍照
方案一 AVCapturePhotoOutput
let photoOutput = AVCapturePhotoOutput()
captureSession.addOutput(photoOutput)
在识别到运单号\二维码结果的回调中,调用拍照方法
func metadataOutput(_ output: AVCaptureMetadataOutput,
didOutput metadataObjects: [AVMetadataObject],
from connection: AVCaptureConnection) {
// 这里处理识别结果逻辑
let setting = {
let setting = AVCapturePhotoSettings()
// 启用自动静止图像稳定功能
setting.photoQualityPrioritization = .balanced
return setting
}()
photoOutput?.capturePhoto(with: setting, delegate: self)
}
/// 拍照回调
func photoOutput(_ output: AVCapturePhotoOutput,
didFinishProcessingPhoto photo: AVCapturePhoto,
error: Error?) {
guard let imageData = photo.fileDataRepresentation(),
let image = UIImage(data: imageData) else {
// 获取到图片
}
}
方案二 AVCaptureVideoDataOutput
let videoDataOutput = AVCaptureVideoDataOutput()
videoDataOutput.setSampleBufferDelegate(self, queue: captureQueue)
将条形码识别和视频流获取的代理方法设置在同一个串行队列中回调
这样只需要在获取到识别结果后,通过标记位标记,需要保存当前视频流的帧即可
func metadataOutput(_ output: AVCaptureMetadataOutput,
didOutput metadataObjects: [AVMetadataObject],
from connection: AVCaptureConnection) {
// 这里处理识别结果逻辑
// 设置标记位
captureFlag = true
}
/// 实现视频流回调方法
func captureOutput(_ output: AVCaptureOutput,
didOutput sampleBuffer: CMSampleBuffer,
from connection: AVCaptureConnection) {
// flag
guard captureFlag else { return }
guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
return
}
let ciImage = CIImage(cvPixelBuffer: pixelBuffer)
let image = UIImage(ciImage: ciImage)
}
两种方案对比
方案一,因为是可以配置拍照的参数,所以在呈像方面,会比较稳定。但是会有快门声
方案二,因为直接获取的是视频流,所以防抖方面没那么好,但是在连续获取视频帧的时候,会比拍照快很多,或者说方案一不适合这种连续获取视频帧的场景
注意点
- AVCapturePhotoSettings 需要每次都创建对象,只能用一次,否则会crash