【问题标题】:Swift, Firebase - Use CMSampleBufferRef with live feed of cameraSwift,Firebase - 将 CMSampleBufferRef 与相机的实时供稿一起使用
【发布时间】:2019-04-23 20:36:05
【问题描述】:

我目前正在尝试从 Firebase to use text recognition 实现 MLKit。

到目前为止,我已经获得了相机的代码,它在 UIView 中显示了它的实时源。我现在的意图是识别这个实时提要中的文本,我认为这可以在 CMSampleBufferRef (let image = VisionImage(buffer: bufferRef) - see linked Firebase tutorial, Step 2) 的帮助下实现。
我怎样才能创建这样的CMSampleBufferRef 并让它保持相机的实时馈送(UIView)?

我的相机代码:

@IBOutlet weak var cameraView: UIView!
    var session: AVCaptureSession?
    var device: AVCaptureDevice?
    var input: AVCaptureDeviceInput?
    var output: AVCaptureMetadataOutput?
    var prevLayer: AVCaptureVideoPreviewLayer?

    override func viewDidLoad() {
        super.viewDidLoad()
        prevLayer?.frame.size = cameraView.frame.size
    }

    func createSession() {
        session = AVCaptureSession()
        device = AVCaptureDevice.default(for: AVMediaType.video)

        do{
            input = try AVCaptureDeviceInput(device: device!)
        }
        catch{
            print(error)
        }

        if let input = input{
            session?.addInput(input)
        }

        prevLayer = AVCaptureVideoPreviewLayer(session: session!)
        prevLayer?.frame.size = cameraView.frame.size
        prevLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill

        prevLayer?.connection?.videoOrientation = transformOrientation(orientation: UIInterfaceOrientation(rawValue: UIApplication.shared.statusBarOrientation.rawValue)!)

        cameraView.layer.addSublayer(prevLayer!)

        session?.startRunning()
    }

    func cameraWithPosition(position: AVCaptureDevice.Position) -> AVCaptureDevice? {
        let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDualCamera, .builtInTelephotoCamera, .builtInTrueDepthCamera, .builtInWideAngleCamera, ], mediaType: .video, position: position)

        if let device = deviceDiscoverySession.devices.first {
            return device
        }
        return nil
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        coordinator.animate(alongsideTransition: { (context) -> Void in
            self.prevLayer?.connection?.videoOrientation = self.transformOrientation(orientation: UIInterfaceOrientation(rawValue: UIApplication.shared.statusBarOrientation.rawValue)!)
            self.prevLayer?.frame.size = self.cameraView.frame.size
        }, completion: { (context) -> Void in

        })
        super.viewWillTransition(to: size, with: coordinator)
    }

    func transformOrientation(orientation: UIInterfaceOrientation) -> AVCaptureVideoOrientation {
        switch orientation {
        case .landscapeLeft:
            return .landscapeLeft
        case .landscapeRight:
            return .landscapeRight
        case .portraitUpsideDown:
            return .portraitUpsideDown
        default:
            return .portrait
        }
    }

【问题讨论】:

    标签: ios swift firebase firebase-mlkit text-recognition


    【解决方案1】:

    编辑:我添加了一个符合您的语言要求的功能性 Swift 示例:

    import UIKit
    import AVFoundation
    
    class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
        @IBOutlet weak var cameraView: UIView!
        var session: AVCaptureSession!
        var device: AVCaptureDevice?
        var input: AVCaptureDeviceInput?
        var videoOutput: AVCaptureVideoDataOutput!
        var output: AVCaptureMetadataOutput?
        var prevLayer: AVCaptureVideoPreviewLayer!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            session = AVCaptureSession()
            device = AVCaptureDevice.default(for: AVMediaType.video)
            
            do{
                input = try AVCaptureDeviceInput(device: device!)
            }
            catch{
                print(error)
                return
            }
            
            if let input = input {
                if session.canAddInput(input) {
                    session.addInput(input)
                }
            }
            
            videoOutput = AVCaptureVideoDataOutput()
            videoOutput.videoSettings = [
                String(kCVPixelBufferPixelFormatTypeKey): NSNumber(value: kCVPixelFormatType_32BGRA)
            ]
            videoOutput.alwaysDiscardsLateVideoFrames = true
            
            let queue = DispatchQueue(label: "video-frame-sampler")
            videoOutput!.setSampleBufferDelegate(self, queue: queue)
            if session.canAddOutput(videoOutput) {
                session.addOutput(videoOutput)
                
                if let connection = videoOutput.connection(with: .video) {
                    connection.videoOrientation = videoOrientationFromInterfaceOrientation()
                    
                    if connection.isVideoStabilizationSupported {
                        connection.preferredVideoStabilizationMode = .auto
                    }
                }
            }
            
            prevLayer = AVCaptureVideoPreviewLayer(session: session)
            prevLayer.frame.size = cameraView.frame.size
            prevLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
            cameraView.layer.addSublayer(prevLayer!)
            
            session.startRunning()
        }
        
        func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
            //pass your sampleBuffer to vision API
            //I recommend not to pass every frame however, skip some frames until camera is steady and focused
            print("frame received")
        }
        
        func videoOrientationFromInterfaceOrientation() -> AVCaptureVideoOrientation {
            return AVCaptureVideoOrientation(rawValue: UIApplication.shared.statusBarOrientation.rawValue)!
        }
    }
    

    我看到您已经设置了输入和预览层,但您还需要设置视频捕获输出,以捕获您的 CMSampleBufferRef 帧。

    为此,请按照以下步骤设置AVCaptureVideoDataOutput 类型的对象:

    1. 创建AVCaptureVideoDataOutput 的实例并配置

       AVCaptureVideoDataOutput* videoOutput = [[AVCaptureVideoDataOutput new] autorelease];
       videoOutput.videoSettings = @{(id)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_32BGRA)};
       videoOutput.alwaysDiscardsLateVideoFrames = YES;
      
    2. 设置已配置输出的帧捕获(样本缓冲区)委托并将其添加到会话中

       dispatch_queue_t queue = dispatch_queue_create("video-frame-sampler", 0);
       [videoOutput setSampleBufferDelegate:self queue:queue];
       if ([self.session canAddOutput:videoOutput]) {
           [self.session addOutput:videoOutput];
      
           AVCaptureConnection* connection = [videoOutput connectionWithMediaType:AVMediaTypeVideo];
           connection.videoOrientation = [self videoOrientationFromDeviceOrientation];
           if (connection.supportsVideoStabilization) {
               connection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
           }
       }
      
    3. 实现captureOutput:didOutputSampleBuffer:fromConnection: 方法,您将在其中获得所需的CMSampleBufferRef

       -(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
           //pass your sampleBuffer to vision API
           //I recommend not to pass every frame however, skip some frames until camera is steady and focused
       }
      

    我是一名普通的 Objective-C 开发人员,但您可以根据需要轻松地将代码转换为 Swift。

    另外,这里是videoOrientationFromDeviceOrientation方法的代码:

    -(AVCaptureVideoOrientation)videoOrientationFromDeviceOrientation {
        UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
        AVCaptureVideoOrientation result = (AVCaptureVideoOrientation)orientation;
        if ( orientation == UIDeviceOrientationLandscapeLeft )
            result = AVCaptureVideoOrientationLandscapeRight;
        else if ( orientation == UIDeviceOrientationLandscapeRight )
            result = AVCaptureVideoOrientationLandscapeLeft;
        return result;
    }
    

    【讨论】:

    • 感谢您的努力!我会尝试转换代码,但由于我是 Swift 新手,我可能会遇到困难并且需要更长的时间。收到后我会尽快回复您。
    • @Tim 为你添加了一些 Swift。
    • 感谢您的帮助,但似乎代码没有正确转换,或者我在实现它时出错了,因为我遇到了很多错误。
    • 是的,我最近有这种感觉。所以我在编辑中添加了一个功能性 Swift 代码 sn-p。
    猜你喜欢
    • 2022-01-03
    • 1970-01-01
    • 2018-05-07
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 2017-01-02
    • 1970-01-01
    相关资源
    最近更新 更多