iOS Swift如何通过Vision框架AVCaptureVideoDataOutput仅扫描指定CGRect区域
基于Vision框架的限定区域条形码扫描实现代码
我正在参考教程学习使用Vision框架实现条形码扫描功能,需求为仅识别屏幕中央指定正方形区域内的条形码。
以下是我当前的捕获输出配置代码,完整代码如下:
import UIKit import Vision import AVFoundation class ViewController: UIViewController { // MARK: - 私有变量 var captureSession = AVCaptureSession() // TODO: 定义VNDetectBarcodesRequest变量 lazy var detectBarcodeRequest = VNDetectBarcodesRequest { request, error in guard error == nil else { print("条形码识别错误:\(error?.localizedDescription ?? "")") return } self.processClassification(request) } // MARK: - 生命周期重写方法 override func viewDidLoad() { super.viewDidLoad() checkPermissions() setupCameraLiveView() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // TODO: 停止捕获会话 captureSession.stopRunning() } }
处理输出
extension ViewController: AVCaptureVideoDataOutputSampleBufferDelegate { func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { // TODO: 实时调用Vision识别 guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return } let imageRequestHandler = VNImageRequestHandler( cvPixelBuffer: pixelBuffer, orientation: .right) do { try imageRequestHandler.perform([detectBarcodeRequest]) } catch { print(error) } } }
权限校验、输入输出添加逻辑
extension ViewController { // MARK: - 相机相关方法 private func checkPermissions() { // TODO: 校验相机权限 switch AVCaptureDevice.authorizationStatus(for: .video) { case .notDetermined: AVCaptureDevice.requestAccess(for: .video) { granted in if !granted { print("请前往设置页为当前应用授予相机使用权限") } } case .denied, .restricted: print("请前往设置页为当前应用授予相机使用权限") default: return } } private func setupCameraLiveView() { // TODO: 配置捕获会话 captureSession.sessionPreset = .hd1280x720 // TODO: 添加视频输入 let videoDevice = AVCaptureDevice .default(.builtInWideAngleCamera, for: .video, position: .back) guard let device = videoDevice, let videoDeviceInput = try? AVCaptureDeviceInput(device: device), captureSession.canAddInput(videoDeviceInput) else { print("当前设备相机存在异常,无法使用") return } captureSession.addInput(videoDeviceInput) // TODO: 添加视频输出 let captureOutput = AVCaptureVideoDataOutput() // TODO: 设置视频采样率 captureOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32BGRA)] captureOutput.setSampleBufferDelegate(self, queue: DispatchQueue.global(qos: DispatchQoS.QoSClass.default)) captureSession.addOutput(captureOutput) configurePreviewLayer() // TODO: 启动捕获会话 captureSession.startRunning() } // MARK: - Vision识别逻辑 func processClassification(_ request: VNRequest) { // TODO: 识别结果主处理逻辑 guard let barcodes = request.results else { return } DispatchQueue.main.async { [self] in if captureSession.isRunning { view.layer.sublayers?.removeSubrange(1...) for barcode in barcodes { guard // TODO: 校验二维码编码类型与置信度 let potentialQRCode = barcode as? VNBarcodeObservation, potentialQRCode.symbology == .QR else { return } print("识别到的二维码内容:\(potentialQRCode.payloadStringValue ?? "")") } } } } }
预览层配置逻辑
extension ViewController { private func configurePreviewLayer() { let cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession) cameraPreviewLayer.videoGravity = .resizeAspectFill cameraPreviewLayer.connection?.videoOrientation = .portrait cameraPreviewLayer.frame = view.frame view.layer.insertSublayer(cameraPreviewLayer, at: 0) } }
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

