SwiftUI - 在 macOS 应用中扫描二维码

3
我正在开发一款Mac应用程序,它可以从相机中读取QR码,并从中读取文本。不幸的是,CodeScanner包仅适用于iOS,没有叫做的方法:
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection)

当然,要使用它,必须包含AVCaptureMetadataOutputObjectsDelegate - 不幸的是,这个协议在macOS上不可用。
有没有办法使用SwiftUI创建macOS二维码扫描器?
我目前已经内置了MacBook相机预览,但我缺少捕获QR码的功能:
final class PlayerContainerView: NSViewRepresentable {
    typealias NSViewType = PlayerView
    
    let captureSession: AVCaptureSession
    
    init(captureSession: AVCaptureSession) {
        self.captureSession = captureSession
    }
    
    func makeNSView(context: Context) -> PlayerView {
        return PlayerView(captureSession: captureSession)
    }
    
    func updateNSView(_ nsView: PlayerView, context: Context) {}
}

class PlayerView: NSView {
    var previewLayer: AVCaptureVideoPreviewLayer?
    
    init(captureSession: AVCaptureSession) {
        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        super.init(frame: .zero)
        
        setupLayer()
    }
    
    func setupLayer() {
        previewLayer?.frame = self.frame
        previewLayer?.contentsGravity = .resizeAspectFill
        previewLayer?.videoGravity = .resizeAspectFill
        previewLayer?.connection?.automaticallyAdjustsVideoMirroring = false
        
        if let mirroringSupported = previewLayer?.connection?.isVideoMirroringSupported {
            if mirroringSupported {
                previewLayer?.connection?.automaticallyAdjustsVideoMirroring = false
                previewLayer?.connection?.isVideoMirrored = true
            }
        }

        
        layer = previewLayer
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

我找不到任何与AVCaptureMetadataOutputObjectsDelegate类似并允许我捕获元数据对象的委托协议。

1个回答

3

我也很惊讶macOS的AVFoundation不支持AVCaptureMetadataOutput,但是CoreImage支持QR码,这对我有用:

let qrDetector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: nil)!

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
    
    let ciImage = CIImage(cvImageBuffer: imageBuffer)
    let features = qrDetector.features(in: ciImage)

    for feature in features {
        let qrCodeFeature = feature as! CIQRCodeFeature
        print("messageString \(qrCodeFeature.messageString!)")
    }
}

可能有更高效的方法来完成这个任务。


1
非常感谢您的回答!我一直在寻找VNDetectBarcodesRequest的替代方案(因为它似乎存在内存泄漏问题?!),而您提出的这个方案使用的内存要少得多(大约是使用Vision框架时的三分之一)。为了使其更加高效,我只是设置了一个迭代器来跳过一些帧,这样分析只在每X帧进行。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接