ARあるある言いたい

VR・ARについて書いていきます

HoloLensでARToolKitを使ってみた

Oculus Rift Advent Calendar 2017の8日目の記事です。

qiita.com

ARToolKitとは、カメラに映るマーカーや任意画像の位置や角度を認識してくれるライブラリで、類似のVuforiaなどと異なる点はオープンソースであることです。無料で利用できます。

今回はこれをHoloLensで使ってみます。

HoloLensARToolKit

HoloLensARToolKitというライブラリを使います。

github.com

「releases」のリンクから最新のv0.2(HoloLensARToolKit-v0.2.zip)をダウンロードしましょう。

ちなみに対応しているUnityバージョンは5.6.xとのことですが、今回僕は2017.1.0f3でやりました。

とりあえず動かす

まずはサンプルプロジェクトを動かしてみましょう。

Unityを起動し、ダウンロードした「HoloLensARToolKit-v0.2.zip」内の「HoloLensARSample」プロジェクトを開きます。次にUnityメニューのAssets/Import Package/Custom Package...から、同じく「HoloLensARToolKit-v0.2.zip」内のARToolKitUWP.unitypackageを選択し、インポートします。 色々警告が出ますが、特に問題ないので無視します。

Sampleフォルダ内にサンプルシーンが複数あります。HoloLensARToolKitCoordsシーンを動かしてみましょう。 シーンを読み込むと、カメラやplayer settings、quality settingsも準備されているので、そのままビルドできます。

f:id:mojo_nobu:20171208185821p:plain

ビルドしてHoloLensで起動したら、以下の本家ARToolKitgithubリポジトリから以下の画像を取ってきて見てみましょう。

github.com

f:id:mojo_nobu:20171208190553j:plain

はい。少しずれたり、不思議な挙動したりしてますが、現時点では細かいことは考えず先に進みましょう。

動作を見ていく

HoloLensARToolKitCoordsシーンをいじりながら動作を見ていきましょう。 主な働きをするのはARUWP Controllerオブジェクトです。

f:id:mojo_nobu:20171208062727p:plain

ARUWPControllerコンポーネント

名前が同じで紛らわしいですが、ARUWPControllerオブジェクトに含まれるARUWPControllerコンポーネントが、このライブラリのコアになります。このコンポーネントはHoloLensARToolKitを使用するプロジェクトに一つ以上含んではいけないことになっています。

f:id:mojo_nobu:20171208064509p:plain

Pattern Detection Modeは、認識対象となる画像の種類を指定します。 「AR_TEMPLATE_MATCHING_COLOR(MONO)」は任意画像のマーカー、「AR_MATRIX_CODE_DETECTION」はARマーカー(後述)を認識したいときに指定します。

今回は両方を認識したいので「AR_TEMPLATE_MATCHING_MONO_AND_MATRIX」を指定します。

Matrix Code Typeは認識するARマーカーのサイズ(粒度)を指定します。今回はAR_MATRIX_CODE_3x3です。

オプションの詳しい説明は以下をご参照ください。

longqian.me

ARUWPMarkerコンポーネント

ARUWPMarkerコンポーネントは、ARToolKitが認識する画像と、認識後に表示するオブジェクトを管理します。

ARMarkerを認識する

まずARマーカーの認識するようにしてみましょう。

ARToolKitは、最初から特定のデータセット(ARマーカー)が認識できるようになっています。

(ARマーカーについてはこちらを参照)

まず、typeを「Single_barcode」にセットします。 f:id:mojo_nobu:20171208191328p:plain

「Barcode ID」を指定することで、単一のARマーカーを認識できるようになります。前述の本家ARToolKitgithubリポジトリ内のここ)から、ID別のARマーカー画像を取得することができます。

「Size in mm」で実際に認識するマーカーサイズをミリ指定し、「Visualization Target」で表示するオブジェクトを指定します。

基本的にはこれでOKですが、実はHoloLensでこのまま動かすと、IDが異なるARマーカーを区別できない、という結果になると思います。最初のサンプルシーンでも一つ画像を認識すると複数のオブジェクトが追従してきたかと思いますが、これらは「マーカーっぽいのは認識できているが詳細に区別できていない」ことが原因です。

この対策として、「Advanced Options」以下の「Confidence Cutoff」の値を変更します。

デフォルトは0.5ですが、大体0.8くらいにすればマーカーの区別ができるようになるかと思います。大きすぎると今度は正しいマーカーも認識されなくなるので注意してください。

任意マーカーを作って認識する(ただし制限あり)

次に、任意の画像を使って認識します。ARToolKitで任意画像を認識するには、対応したパターンファイルを生成する必要があります。パターンファイルは以下を使って生成します。

ARToolKit Marker Generator Online

このページ、chromeでは正常に動作せず、Edgeで動作確認できました。

で、実際やってみるとわかるんですけど、ARToolKitで読み込むマーカーって4辺が指定の比率の枠線で囲まれた四角形じゃないといけないっぽいんですよね~(参考)なので、そういう画像を用意します。

f:id:mojo_nobu:20171208192430p:plain

patファイルを取得したら、Unityに戻って取得したpatファイルをStreamingAssetsフォルダ以下にインポートします。

ファイルが準備できたら、ARUWPControllerオブジェクトのARUWPMarkerコンポーネントに戻って、typeを「Single」にします。

f:id:mojo_nobu:20171208192133p:plain

「File」に先ほどインポートしたpatファイルを拡張子まで書き、「Size in mm」、「Visualization Target」、「Advanced Options」以下の「Confidence Cutoff」を指定します。

これでビルドしてみましょう。

f:id:mojo_nobu:20171208193047j:plain

これで任意画像の認識ができました。

なんかずれてない?

はい、実はコレずれています。どうやらHoloLensのカメラと装着した人間の目の位置のずれが十分に補正されていないようです。

この件に関して、githubリポジトリの以下で解説がされています。

github.com

github.com

どうやらARUWPMarker.csの844行目以降にあるMagicMatrixの値を変更し、各自の目の位置に正確に表示してくれ、とのことです。

    private void InitMagicFunction() {
        magicMatrix1.SetRow(0, new Vector4(0.912590966818f, 0.00264415233376f, -0.0128817795355f, 0.000747730441087f));
        magicMatrix1.SetRow(1, new Vector4(-0.00522566480145f, 0.906864775491f, -0.0896724176439f, 0.0177872745822f));
        magicMatrix1.SetRow(2, new Vector4(-0.0232595319748f, 0.00845030987907f, 0.887221375125f, 0.0730807968318f));
        magicMatrix2.SetRow(0, new Vector4(0.999970522935f, 0.00515075228031f, 0.00569412074919f, 0.0f));
        magicMatrix2.SetRow(1, new Vector4(-0.00483183598788f, 0.998492806032f, -0.0546696411472f, 0.0f));
        magicMatrix2.SetRow(2, new Vector4(-0.00596712838354f, 0.0546405165891f, 0.998488260985f, 0.0f));
    }

    /// <summary>
    /// Perform the magic function, add distortion to the tracking result matrix. [internal use]
    /// </summary>
    private void MagicFunction() {
        if (performMagicFunction) {
            Vector4 vp = magicMatrix1 * latestTransMatrix.GetColumn(3);
            latestTransMatrix = magicMatrix2 * latestTransMatrix;
            latestTransMatrix.SetColumn(3, vp);
        }
    }

変更後は、ARUWPMarkerコンポーネントの「Apply Undistortion Function」を有効にすればよいとのことです。

f:id:mojo_nobu:20171208194431p:plain

今回はここまでです!MagicFunctionの設定方法はまたいつか。

明日は...

Oculus Rift Advent Calendar2017、明日はm2wasabiさんによる記事です!

qiita.com