Reputation: 58563
I need only 20 frames out of 60 frames per second for processing (CVPixelBuffer
).
How to capture every third ARFrame in ARKit session? I need approximately 20 fps for capture (I understand there may be a drop frame).
Here's a code's snippet:
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)
}
}
Upvotes: 1
Views: 963
Reputation: 1
You can either set custom frame rate, so you will get only 20 frames, or you can receive all frames but use only every third frame by taking a flag variable and incrementing it.
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
totalFrameCount += 1
if totalFrameCount % 3 != 0{ return }
}
or you can set custom frame rate by extending AVCaptureDevice
lockForConfiguration()
activeVideoMinFrameDuration = CMTimeMake(1, 20)
activeVideoMaxFrameDuration = CMTimeMake(1, 20)
unlockForConfiguration()
Upvotes: 0
Reputation: 4077
The simplest way known to me is to use RxARKit
and apply .throttle()
operator to session.rx.didUpdateFrame
. I believe it is not prudent to skip every so many events because frame rate is not guaranteed to be 60fps at all times, so it is best to use .throttle()
to get a frame at most every so many milliseconds, no matter what the actual framerate is. You can plug the result of it into RxVision
, which will take care that that very frame will be used by 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)
Upvotes: 1