CVPixelBuffer - Как захватить каждый ТРЕТИЙ кадр из 60 кадров в секунду? - PullRequest
0 голосов
/ 02 декабря 2018

Мне нужно только 20 кадров из 60 кадров в секунду для обработки (CVPixelBuffer).

Как захватить каждый третий ARFrame в сеансе ARKit ?Мне нужно приблизительно 20 кадров в секунду для захвата (я понимаю, что может быть пропущенный кадр).

Вот фрагмент кода:

func updateCoreML() {

    let pixelBuffer: CVPixelBuffer? = (sceneView.session.currentFrame?.capturedImage)

    if pixelBuffer == nil { return }
    let ciImage = CIImage(cvPixelBuffer: pixelBuffer!)
    let imageRequestHandler = VNImageRequestHandler(ciImage: ciImage, options: [:])

    do {
        try imageRequestHandler.perform(self.visionRequests)
    } catch {
        print(error)
    }
}

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

Вы можете либо установить пользовательскую частоту кадров, чтобы получить только 20 кадров, либо получить все кадры, но использовать только каждый третий кадр, взяв переменную flag и увеличивая ее.

  func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
       totalFrameCount += 1
       if totalFrameCount % 3 != 0{ return }
}

илиВы можете установить пользовательскую частоту кадров, расширив AVCaptureDevice

 lockForConfiguration()
 activeVideoMinFrameDuration = CMTimeMake(1, 20)
 activeVideoMaxFrameDuration = CMTimeMake(1, 20)
 unlockForConfiguration()
0 голосов
/ 03 декабря 2018

Самый простой известный мне способ - использовать RxARKit и применять оператор .throttle() к session.rx.didUpdateFrame.Я полагаю, что не стоит пропускать столько событий, потому что частота кадров не всегда гарантируется равной 60 кадр / с, поэтому лучше использовать .throttle(), чтобы получить кадр не чаще, чем через столько же миллисекунд, независимо от того, что на самом делечастота кадров есть.Вы можете вставить результат этого в RxVision, который позаботится о том, чтобы этот самый кадр был использован CoreML.

import RxSwift
import RxARKit
import RxVision


let disposeBag = DisposeBag()
let mlRequest: RxVNCoreMLRequest<CVPixelBuffer> = VNCoreMLRequest.rx.request(model: model, imageCropAndScaleOption: .scaleFit)

mlRequest
    .observable
    .subscribe { [unowned self] (event) in
        switch event {
            case .next(let completion):       
                let cvPixelBuffer = completion.value
                if let result = completion.request.results?[0] as? VNClassificationObservation {
                    os_log("results: %@", type: .debug, result.identifier)
                }
            default:
                break
        }
    }
    .disposed(by: disposeBag)

session
    .rx
    .didUpdateFrame
    .throttle(1/20)
    .subscribe { event in
        switch event {
        case .next(let didUpdateFrame):
        let frame: ARFrame = didUpdateFrame.frame        
        let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: frame.capturedImage, orientation: .up, options: requestOptions)
        do {
            try imageRequestHandler.rx.perform([mlRequest], with: frame.capturedImage) } catch {
            print(error)
        }            
        break
        default:
            break
        }
    }
    .disposed(by: disposeBag)
...