ARKitのPeople Occlusion
オクルージョンとは
ARKit 3(iOS 13)から、People Occlusionと呼ばれる機能が追加されました。
オクルージョンとは、手前にある物体が背後にある物体を隠して見えないようにする状態のことです。
たとえば下図の左の画像のようにカメラに映っている状態で、ARKitでワールドトラッキングを行い、検出したテーブルの平面に仮想オブジェクトを設置するとします。すると、従来は下図の右の画像のように描画されていました。
手前の人物より奥にあるテーブルの平面に設置されているはずの物体が、手前の人物の上に描画されているので、違和感があります。
これを、前後関係を考慮して次のように描画するのが「オクルージョン」です。
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」によると屋内環境で最も理想的に動作するとのことです。
People Occlusionの実装方法
People Occlusionの実装は、ARSCNView
やRealityKitのARView
を使用している場合は非常に簡単です。ARConfiguration
クラスにframeSemantics
というARConfiguration.FrameSemantics
型のプロパティがiOS 13で追加されたので、
var frameSemantics: ARConfiguration.FrameSemantics
ここに、personSegmentation
またはpersonSegmentationWithDepth
を指定します。
configuration.frameSemantics = [.personSegmentation]
たったこれだけの追加実装で、人物のオクルージョンが実現できてしまいます。
personSegmentationとpersonSegmentationWithDepthの違い
personSegmentation
とpersonSegmentationWithDepth
の違いは、深度を考慮するかどうかです。personSegmentation
を指定した場合は深度を考慮しないため、次のように映っている人物すべてを仮想オブジェクトの手前に描画します。
後ろの人物がテーブル平面上の仮想オブジェクトより手前に描画されている
利用可能なコンフィギュレーション
前述の通りpersonSegmentation
とpersonSegmentationWithDepth
はARConfiguration
のframeSemantics
プロパティにセットするわけですが、どのコンフィギュレーションクラスに対しても適用できるわけではありません。サポートしていない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を用いて、各コンフィギュレーションクラスにおけるpersonSegmentation
、personSegmentationWithDepth
それぞれのサポート有無を調べた結果が次の表です(表内の「WithDepth」はpersonSegmentationWithDepth
を示します)。
Configuration | personSegmentation | WithDepth |
---|---|---|
ARWorldTrackingConfiguration | ◯ | ◯ |
AROrientationTrackingConfiguration | ◯ | ◯ |
ARFaceTrackingConfiguration | ◯ | - |
ARImageTrackingConfiguration | ◯ | ◯ |
ARObjectScanningConfiguration | - | - |
ARBodyTrackingConfiguration | - | - |
ARPositionalTrackingConfiguration | - | - |
この表によると、以下のコンフィギュレーションクラスでPeople Occlusionを利用可能であることがわかります。
ARWorldTrackingConfiguration
AROrientationTrackingConfiguration
-
ARFaceTrackingConfiguration
(※デプスありは利用不可) ARImageTrackingConfiguration
segmentationBufferとestimatedDepthData
ARFrame
に、segmentationBuffer
、estimatedDepthData
というプロパティがiOS 13で追加されました。どちらも型はCVPixelBuffer
で、get
のみ可能です。
var segmentationBuffer: CVPixelBuffer? { get }
var estimatedDepthData: CVPixelBuffer? { get }
personSegmentation
またはpersonSegmentationWithDepth
利用時、segmentationBuffer
には対象物体(ここでは人物)をセグメンテーションするためのピクセルデータが入ってきます。このバッファにおけるピクセル値は0.0
または1.0
の二値で、対象物体と背景を完全に分離するものであることがわかります。
またpersonSegmentationWithDepth
利用時には、estimatedDepthData
に対象物体(ここでは人物)の推定深度データが入ってきます。深度なので、近い領域ほどピクセル値は小さくなります。
左から、カメラ画像、segmentationBuffer(拡大)、estimatedDepthData(拡大)
なお、実機(iPhone XS)で取得してみたところどちらのデータもサイズは192 x 256
ピクセルでした。カメラフレームのサイズが1440 x 1920
なので、ちょうど幅・高さ方向にそれぞれ1/7.5倍縮小したサイズということになります。
「つくりながら学ぶ」ARKitの入門書
ARKitの本を書いて個人で出版しました。
はじめの一歩として3行で書ける最小実装のARから始めて、平面を検出する方法、その平面に仮想オブジェクトを設置する方法、そしてその仮想オブジェクトとインタラクションできるようにする方法・・・と、読み進めるにつれて「作りながら」引き出しが増えていき、最終的にはARKitを用いたメジャーや、空間に絵や文字を描くといった、ARKitならではのアプリケーションの実装ができるよう構成しています。
全146ページ。サンプルコードはGitHubよりダウンロード可能です。BOOTHにて販売中。
Discussion