Blog

[Unity] ARやってみよう!その2「水平面検知」

執筆: K.I
執筆バージョン: Unity2020.1.6f1, Vuforia 9.4

はじめに

前回 [Unity]ARやってみよう!の続編として今回はVuforiaを使って「マーカー」ではなく、「平面検出」をやってみました。

前回使用したUnityProjectをを使って、今回も実装をやってみております。

水平面検知とは

ARKitでは、Visual Inertial Odometry(VIO)と呼ばれる技術が採用されています。
これはデバイスのモーションセンサーから得られる情報を、デバイスのカメラで捉えたシーンのコンピュータビジョン解析と組み合わせ、シーン画像に含まれている注目すべきフィーチャ(特徴点)を認識し、それらのフィーチャについて、ビデオフレーム間での位置の違いをトラッキングし、その情報をモーションセンサーのデータと比較し、結果としてデバイスの位置とモーションに関する高精度の情報から、シーンの内容の解析と認識も行われ、レイキャスティングメソッドを使って、カメラ画像内の点に対応するリアルワールドの面を探して平面と検出する技術のものとなります。
ARKitによってカメラ画像内の平面が検出され、その平面の位置とサイズが判定できるのです!

Vuforia の GrandPlane で水平面検知をやってみた

Vuforiaには GrandPlane というARKitやARCoreで実現できるような水平面を検知する機能が搭載されているので、今回はこちらを使って、水平面検知でAR表示を実装します!

水平面検知は、すべての端末でつかえるというわけではなく、iOSのバージョンや端末を限定する技術となります。
※Vuforia での推奨デバイス情報に関しては、バージョンなどにより変わるため、公式の推奨デバイスを確認してください。

  1. Hierarchy上で右クリックし、Vuforia>Ground Plane>Ground Plane Stageで水平面を検知したときに表示される Anchorの役割を果たすオブジェクトを作成します。

    キャラなどを配置する際にここが基点となるので、表示したい任意のオブジェクトを、作成したGround Plane Stageの子供として作成しつつ位置合わせをします。
  2. 次にVuforia>Ground Plane>Plane Finderで水平面を検知するオブジェクトを作成し、このPlane FinderについているContent Positioning BehaviourのAnchor Stageに対して、先程作成したGround Plane Stageを指定してやります。

これでとりあえず水平面を検知して、任意のオブジェクトを表示するという準備が整いました。

Unityエディタで実行してみる

水平面検知の機能確認でもUnityエディタで実行確認ができます。
iPhoneと繋いだりする必要もありません!適当なWebCamera、つまりMacにデフォルトでついてるカメラでも大丈夫です!
とはいえ適当なカメラで実機同様に水平面検知できるわけではなく、このときだけマーカーが必要になります。
Assets>Editor>Vuforia>ImageTargetTextures>VuforiaEmulator>emulator_ground_plane_scaled.jpgがあるので、これを印刷するなりスマホで開くなりします。

※Vuforiaのバージョンなどにより、Assets>Editor>Vuforia>ForPrint>Emulatorの中にEmulator Ground Plane.pdf などになっています。

検知されると

水平面認識された箇所にオブジェクトが表示されます!

ちなみに複数のカメラが接続されている場合、Assets>Resources にある VuforiaConfiguration の Webcam という項目の Camera Device から利用するカメラを選択できます。

あとは通常通りビルドして実機にいれて試してみよう!

認識状態を検知して処理実行してみた

「マーカー」「水平面検知」それぞれ実装してみて、それぞれ検知したタイミングで、「音をならしたい!」とか「画面をフラッシュさせたい!」とかがでてきたので、トラッキング状態(認識状態)が切り替わったタイミングの検知を試してみました。
方法はかんたんで、今回追加した Ground Plane Stage などにアタッチされている 「Default Trackble Event Handler」があります。

トラッキング状態が切り替わったときに、このスクリプトの「見つけたとき:On Target Fount()」「見失ったとき:On Target Lost()」が呼び出されるので、それぞれの箇所に「+」ボタンを押して、実行したい処理を登録するだけで

関数を呼び出すことができました!

もっと細かな状況判断、「追跡状況に関する情報」「追跡の問題に関する主な理由」により、警告ダイアログを表示させたりしたい場合、「Default Trackable Event Handler」を継承した、「Custom Trackble Event Handler」などを作成すれば、それぞれの状態時に処理をさせることができます。

using UnityEngine;
 
public class CustomTrackbleEventHandler : DefaultTrackableEventHandler
{
    protected override void HandleTrackableStatusChanged()
    {
        // 状態で処理を別ける
        switch(mTrackableBehaviour.CurrentStatus)
        {
            case Vuforia.TrackableBehaviour.Status.NO_POSE: // 追跡可能なポーズを配信できませんでした。
                break;
            case Vuforia.TrackableBehaviour.Status.DETECTED: // 追跡は制限されています。
                break;
            case Vuforia.TrackableBehaviour.Status.EXTENDED_TRACKED: // 追跡可能が検出されました。
                break;
            case Vuforia.TrackableBehaviour.Status.LIMITED: // 追跡可能が追跡されました。
                break;
            case Vuforia.TrackableBehaviour.Status.TRACKED: // 追跡可能は拡張追跡されました。
                break;
        }
 
        switch (mTrackableBehaviour.CurrentStatusInfo)
        {
            case Vuforia.TrackableBehaviour.StatusInfo.NORMAL: //ステータスは正常です
                break;
            case Vuforia.TrackableBehaviour.StatusInfo.UNKNOWN: // ステータスが制限されている理由は不明です。
                break;
            case Vuforia.TrackableBehaviour.StatusInfo.INITIALIZING: // 正確な追跡のための十分な情報はまだありません。
                break;
            case Vuforia.TrackableBehaviour.StatusInfo.RELOCALIZING: // 追跡システムは現在再ローカライズ中です。
                break;
            case Vuforia.TrackableBehaviour.StatusInfo.EXCESSIVE_MOTION: // 動きが速すぎて正確に追跡できません。
                break;
            case Vuforia.TrackableBehaviour.StatusInfo.INSUFFICIENT_FEATURES: // 正確な追跡には十分な機能がありません。
                break;
            case Vuforia.TrackableBehaviour.StatusInfo.INSUFFICIENT_LIGHT:// 正確な追跡には十分な光がありません。
                break;
            case Vuforia.TrackableBehaviour.StatusInfo.NO_DETECTION_RECOMMENDING_GUIDANCE: // ターゲットをスナップできませんでした
                break;
        }
    }
}

作成した Handle に入れ替える!

まとめ

水平面検知をやってみて。

光源が不足しているところ(暗いところ)や、床と壁の境目がはっきりしないところだと、水平面検知がうまく行かないことが多々ありました。

また実用として使う場合、実行している端末で、水平面検知が対応していないものもあるので、Vuforiaの初期化時に、使用可能デバイスがVuforiaの初期化結果より判定し、対応していないのは「マーカー」で、対応しているのは「水平面検知」でを自動で混在にすると使っている側は意識することなくARを試せると思うので、今後はそのへんも試していこうと思います。
また執筆時点で、Vuforiaのバージョンが9.6に上がっていたのもあるので、バージョンアップして対応もやってこうとおもいます。

関連記事