👨‍👩‍👦

ARKitのPeople Occlusion

2023/12/27に公開

オクルージョンとは

ARKit 3(iOS 13)から、People Occlusionと呼ばれる機能が追加されました。
オクルージョンとは、手前にある物体が背後にある物体を隠して見えないようにする状態のことです。

たとえば下図の左の画像のようにカメラに映っている状態で、ARKitでワールドトラッキングを行い、検出したテーブルの平面に仮想オブジェクトを設置するとします。すると、従来は下図の右の画像のように描画されていました。

scale=0.8

手前の人物より奥にあるテーブルの平面に設置されているはずの物体が、手前の人物の上に描画されているので、違和感があります。

これを、前後関係を考慮して次のように描画するのが「オクルージョン」です。

scale=0.4

People Occlusionは、人物についてオクルージョン処理を行う機能です。
本機能はA12以降のデバイスで利用可能です。

WWDC 2019のセッション「Introducing ARKit 3」によると、本機能は人体の全体、または一部だけでも、複数人が映っていても動作します。

It works also for multiple people in the scene, and it even works if people are only partially visible like in the example before the woman behind the table actually was not visible with the full body but it still is working.

またWWDC 2019のセッション「Bringing People into AR」によると屋内環境で最も理想的に動作するとのことです。

It also works best in indoor environments.

People Occlusionの実装方法

People Occlusionの実装は、ARSCNViewやRealityKitのARViewを使用している場合は非常に簡単です。ARConfigurationクラスにframeSemanticsというARConfiguration.FrameSemantics型のプロパティがiOS 13で追加されたので、

var frameSemantics: ARConfiguration.FrameSemantics

ここに、personSegmentationまたはpersonSegmentationWithDepthを指定します。

configuration.frameSemantics = [.personSegmentation]

たったこれだけの追加実装で、人物のオクルージョンが実現できてしまいます。

personSegmentationとpersonSegmentationWithDepthの違い

personSegmentationpersonSegmentationWithDepthの違いは、深度を考慮するかどうかです。personSegmentationを指定した場合は深度を考慮しないため、次のように映っている人物すべてを仮想オブジェクトの手前に描画します。

scale=0.7
後ろの人物がテーブル平面上の仮想オブジェクトより手前に描画されている

利用可能なコンフィギュレーション

前述の通りpersonSegmentationpersonSegmentationWithDepthARConfigurationframeSemanticsプロパティにセットするわけですが、どのコンフィギュレーションクラスに対しても適用できるわけではありません。サポートしていないARConfiguration.FrameSemanticsの型プロパティをセットすると、実行時に以下のエラーによりアプリが停止します。

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'This set of frame semantics is not supported on this configuration'

しかし、リファレンスには2019年9月現在、どのコンフィギュレーションでどのframe semanticをサポートしているかという情報は記載されていません。代わりに、ARConfigurationに次のようなクラスメソッドがiOS 13で追加されており、引数に利用したいARConfiguration.FrameSemanticsの型プロパティを指定することで、サポート状況を調べることができます。

class func supportsFrameSemantics(
    _ frameSemantics: ARConfiguration.FrameSemantics) -> Bool

iOS 13.1をインストールしたiPhone XSを用いて、各コンフィギュレーションクラスにおけるpersonSegmentationpersonSegmentationWithDepthそれぞれのサポート有無を調べた結果が次の表です(表内の「WithDepth」はpersonSegmentationWithDepthを示します)。

Configuration personSegmentation WithDepth
ARWorldTrackingConfiguration
AROrientationTrackingConfiguration
ARFaceTrackingConfiguration -
ARImageTrackingConfiguration
ARObjectScanningConfiguration - -
ARBodyTrackingConfiguration - -
ARPositionalTrackingConfiguration - -

この表によると、以下のコンフィギュレーションクラスでPeople Occlusionを利用可能であることがわかります。

  • ARWorldTrackingConfiguration
  • AROrientationTrackingConfiguration
  • ARFaceTrackingConfiguration (※デプスありは利用不可
  • ARImageTrackingConfiguration

segmentationBufferとestimatedDepthData

ARFrameに、segmentationBufferestimatedDepthDataというプロパティがiOS 13で追加されました。どちらも型はCVPixelBufferで、getのみ可能です。

var segmentationBuffer: CVPixelBuffer? { get }
var estimatedDepthData: CVPixelBuffer? { get }

personSegmentationまたはpersonSegmentationWithDepth利用時、segmentationBufferには対象物体(ここでは人物)をセグメンテーションするためのピクセルデータが入ってきます。このバッファにおけるピクセル値は0.0または1.0の二値で、対象物体と背景を完全に分離するものであることがわかります。

またpersonSegmentationWithDepth利用時には、estimatedDepthDataに対象物体(ここでは人物)の推定深度データが入ってきます。深度なので、近い領域ほどピクセル値は小さくなります。

scale=0.7
左から、カメラ画像、segmentationBuffer(拡大)、estimatedDepthData(拡大)

なお、実機(iPhone XS)で取得してみたところどちらのデータもサイズは192 x 256ピクセルでした。カメラフレームのサイズが1440 x 1920なので、ちょうど幅・高さ方向にそれぞれ1/7.5倍縮小したサイズということになります。

「つくりながら学ぶ」ARKitの入門書

ARKitの本を書いて個人で出版しました。

はじめの一歩として3行で書ける最小実装のARから始めて、平面を検出する方法、その平面に仮想オブジェクトを設置する方法、そしてその仮想オブジェクトとインタラクションできるようにする方法・・・と、読み進めるにつれて「作りながら」引き出しが増えていき、最終的にはARKitを用いたメジャーや、空間に絵や文字を描くといった、ARKitならではのアプリケーションの実装ができるよう構成しています。

全146ページ。サンプルコードはGitHubよりダウンロード可能です。BOOTHにて販売中。

https://booth.pm/ja/items/1038241

Discussion