ARKitとAVFoundationは何秒で切り替えられるのか


ARKitとAVFoundation両方の恩恵を受けたい

Gif:ARKitを中断してAVFoundationでキャプチャ、すぐARに戻る

ARKitの世界・顔認識のトラッキングを使いながら、高画質の画像をキャプチャしたいこともあるかもしれません。
ARKitでは1920*1440が最高サイズなので、「AVFoundationでキャプチャすればいいんじゃね?」「ARKitとAVFoundation同時に使えるのかな?」と僕はなりました。

調べたところ、
ARKitとAVFoundationのセッションは、同時には立ち上げられません。
では、素早く切り替えれば、何秒かかるのか。

やってみました。
*iPhone11 iOS14で実験。

実験手順

トラッキング状態を保存して、ARセッションを一時停止し、AVCaptureSessionをスタート。

sceneView.session.getCurrentWorldMap { [self] worldMap, error in
    time = 0.0 // 裏でTimerでtimeを加算しています。0に戻してここからスタート。
    sceneView.session.pause() 
    map = worldMap
    avCaptureSession.startRunning() //AVFoundationスタート
}

実験1、AVCaptureVideoDataOutputで画像を取得する

captureOutputデリゲートメソッド内で画像を取得し、一枚撮ったらすぐにAVCaptureSessionを止めて、ARセッションを再開。

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
    let image = UIImage(ciImage: CIImage(cvImageBuffer: pixelBuffer!))
    print(time)
    avCaptureSession.stopRunning()
    let configuration = ARWorldTrackingConfiguration()
    configuration.initialWorldMap = map
    sceneView.session.run(configuration, options: [])
}

0.15秒でキャプチュア。

しかし、AVFoundationでキャプチャした画像は、セッション立ち上げ直後なので暗い。
最初5フレーム落としてキャプチャしたところ、
綺麗に3840*2160で撮れて0.29秒でした。
画面の停止は0.5秒程度(シャッターを切るくらい)の体感でした。

実験2、AVCapturePhotoCaptureで画像を取得する

写真用のアウトプットで撮ってみました。

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
    if let imageData = photo.fileDataRepresentation() {
        let uiImage = UIImage(data: imageData)
        print(time)
        // 0.50
        self.captureSession.stopRunning()
        let configuration = ARWorldTrackingConfiguration()
        configuration.initialWorldMap = map
        sceneView.session.run(configuration, options: [])
}

こちらは綺麗に写真が撮れてキャプチャまで0.5秒でした。
しかし、写真のシャッターを切ってしまうと、ARKitの復帰が遅く、7秒程度画面が止まったままでした。

結果

キャプチャの仕方 キャプチャまでの秒数 画面停止秒数
AVCaptureVideoDataOutput 0.3 0.5
AVCapturePhotoCapture 0.5 7.0

結論

実用には、VideoDataOutputで最初の数コマ落として撮るのがギリギリ、普通のシャッターぐらい中断感覚で使えるかなあ、という意見です。

ちなみに、ARWorldTrackingでデバイスの傾きデータをとったところ、セッション切り替え以前と以後で0.05ラジアン程度ずれていました。デバイス固定したらズレなかったので、キャプチャしている間の0.3秒の僕の手ブレがそれくらいということですね。

追記:ARPositionalTrackingConfigurationというデバイス位置をとるだけの構成があって、ワンチャンAVFoundationと併用できんじゃね?とやってみたら無理でした。


お仕事のご相談こちらまで
[email protected]

Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

Twitter
MLBoysチャンネル
Medium

相棒
note