HoloLens (第 1 世代) と Azure 302 - コンピューター ビジョン


Note

Mixed Reality Academy のチュートリアルは、HoloLens (第 1 世代) と Mixed Reality イマーシブ ヘッドセットを念頭に置いて編成されています。 そのため、それらのデバイスの開発に関するガイダンスを引き続き探している開発者のために、これらのチュートリアルをそのまま残しておくことが重要だと考えています。 これらのチュートリアルが、HoloLens 2 に使用されている最新のツールセットや操作に更新されることは "ありません"。 これらは、サポートされているデバイス上で継続して動作するように、保守されます。 今後、HoloLens 2 向けに開発する方法を示す新しいチュートリアル シリーズが投稿される予定です。 投稿されたときに、この注記事項が更新されてそのチュートリアルへのリンクが追加されます。


このコースでは、Azure Computer Vision の機能を Mixed Reality アプリケーションで使用して画像の中にあるビジュアル コンテンツを認識する方法を学習します。

認識結果は、説明のタグとして表示されます。 このサービスを使うために、機械学習モデルをトレーニングする必要はありません。 機械学習モデルのトレーニングを必要とする実装の場合は、「MR と Azure 302b」をご覧ください。

ラボの結果

Microsoft Computer Vision は、開発者が画像の処理と分析 (返された情報を使用) を行うための API の集合です。高度なアルゴリズムが使用され、すべてクラウドから行うことができます。 開発者が画像または画像の URL をアップロードすると、Microsoft Computer Vision API のアルゴリズムによってビジュアル コンテンツが分析され (ユーザーが選んだ入力に基づいて)、情報が返されます。たとえば、画像の種類と質を特定することや、人間の顔の検出 (顔の座標が返されます)、タグ付け、画像の分類などを行うことができます。 詳しくは、Azure Computer Vision API に関するページを参照してください。

このコースを修了すると、新しい Mixed Reality HoloLens アプリケーションが完成し、このアプリケーションで次のことができるようになります。

  1. タップ ジェスチャを使って、HoloLens のカメラで画像をキャプチャします。
  2. この画像が Azure Computer Vision API サービスに送信されます。
  3. 認識されたオブジェクトは、Unity シーンの中に配置される単純な UI グループの中に一覧表示されます。

開発するアプリケーションの中で、認識結果をどのようにアプリケーションの設計と統合するかは、開発者の自由です。 このコースは、Azure のサービスをお客様の Unity プロジェクトに統合する方法を説明することを目的としています。 このコースで得られた知識を使用して、ご自分の Mixed Reality アプリケーションを強化しましょう。

デバイス サポート

コース HoloLens イマーシブ ヘッドセット
MR と Azure 302:コンピューター ビジョン ✔️ ✔️

注意

このコースでは主に HoloLens に焦点を当てていますが、このコースで学習した内容を Windows Mixed Reality イマーシブ (VR) ヘッドセットにも適用できます。 イマーシブ (VR) ヘッドセットにはアクセス可能なカメラがないため、外部カメラが PC に接続されている必要があります。 このコースの中では、イマーシブ (VR) ヘッドセットをサポートするために必要な変更がある場合に、その変更が注意事項として記載されています。

前提条件

Note

このチュートリアルは、Unity と C# の基本的な使用経験がある開発者を対象としています。 また、このドキュメント内の前提条件や文章による説明は、執筆時 (2018 年 5 月) にテストおよび検証された内容であることをご了承ください。 「ツールのインストール」の記事に記載されているように、お客様は最新のソフトウェアを自由に使用できます。ただし、このコースの情報は、以下に記載されているものよりも新しいソフトウェアで見つかったものと完全に一致するとは限りません。

このコースでは、次のハードウェアとソフトウェアをお勧めします。

開始する前に

  1. このプロジェクトをビルドする際の問題を避けるために、このチュートリアルで紹介するプロジェクトをルートまたはルートに近いフォルダーに作成することを強くお勧めします (フォルダー パスが長いと、ビルド時に問題が発生する可能性があります)。
  2. HoloLens を設定してテストします。 HoloLens の設定でサポートが必要な場合は、HoloLens セットアップに関する記事にアクセスしてください
  3. 新しい HoloLens アプリの開発を開始するときは、調整とセンサーのチューニングを実行することをお勧めします (ユーザーごとにこれらのタスクを実行すると役立つ場合があります)。

調整の詳細については、この HoloLens の調整に関する記事へのリンクを参照してください。

センサー チューニングの詳細については、このリンク先にある HoloLens センサー チューニングに関する記事を参照してください。

第 1 章 – Azure portal

Azure の Computer Vision API サービスを使用するには、開発するアプリケーションから使用できるようにこのサービスのインスタンスを構成する必要があります。

  1. 最初に、Azure portal にログインします。

    Note

    まだ Azure アカウントをお持ちでない方は、作成する必要があります。 このチュートリアルを教室やラボで受講している場合は、インストラクターや監督者に新しいアカウントの設定サポートを依頼してください。

  2. ログインしたら、左上隅にある[新規作成] をクリックし、検索フィールドに Computer Vision API と入力して Enter キーを押します。

    Azure で新しいリソースを作成する

    Note

    新しいポータルでは、[新規作成] という画面項目名が [リソースの作成] に置き換えられている場合があります。

  3. 新しいページに、Computer Vision API サービスの説明が表示されます。 このページの左下にある [作成] ボタンを選択すると、このサービスとの関連付けを作成することができます。

    Computer Vision API サービスについて

  4. [作成] をクリックしたら、以下の手順を実行します。

    1. このサービス インスタンスに任意の名前を付けて入力します。

    2. サブスクリプションを選択します。

    3. 自分に適した [価格レベル] を選びます。初めて Computer Vision API サービスを作る場合は、Free レベル (F0 という名前) を使えるはずです。

    4. リソース グループを選択するか、新規に作成します。 リソース グループは、Azure アセットのコレクションの監視、アクセス制御、プロビジョニング、課金管理を行う方法を提供します。 1 つのプロジェクト (これらのラボなど) に関連するすべての Azure サービスを共通のリソース グループの下に置くことをお勧めします。

      Azure リソース グループの詳細については、リソース グループに関する記事をご覧ください

    5. リソース グループの [場所] を決定します (新しいリソース グループを作成する場合)。 この場所は、アプリケーションが実行されるリージョン内にすることが理想的です。 一部の Azure アセットは、特定のリージョンでしか利用できません。

    6. また、本サービスに適用されるご契約条件を理解していることの確認も必要です。

    7. [作成] をクリックします。

      サービス作成情報

  5. [作成] をクリックしたら、サービスが作成されるのを待つ必要があります。これには 1 分ほどかかります。

  6. サービスのインスタンスが作成されると、ポータルに通知が表示されます。

    新しいサービスの新しい通知を確認する

  7. 通知をクリックして、新しいサービス インスタンスを確認します。

    [リソースに移動] ボタンを選択します。

  8. 新しいサービス インスタンスを確認するために、通知の [リソースに移動] ボタンをクリックします。 新しい Computer Vision API サービス インスタンスの画面に自動的に移動します。

    新しい Computer Vision API サービス イメージ

  9. このチュートリアルの中で、作成するアプリケーションからご自分のサービスの呼び出しを行う必要があります。これには、そのサービスのサブスクリプション キーを使用します。

  10. Computer Vision API サービスの [クイック スタート] ページで、最初のステップである [キーを取得する] に移動して [キー] をクリックします (または、サービスのナビゲーション メニューにある、鍵のアイコンで示された青い [キー] ハイパーリンクをクリックします)。 これで、ご自分のサービスの "キー" が表示されます。

  11. 表示されているキーの 1 つをコピーします。これは、後でこのプロジェクトに必要になります。

  12. [クイック スタート] ページに戻り、このページからエンドポイントを取得します。 実際の値は、リージョンによって異なる場合があるので注意してください (異なる場合は、後でコードを変更する必要があります)。 後で使用するために、このエンドポイントをコピーしておきます。

    新しいComputer Vision API サービス

    ヒント

    どのようなエンドポイントがあるかは、こちらで確認できます。

第 2 章 – Unity プロジェクトを設定する

次に示すのは Mixed Reality での開発の一般的な設定であるため、他のプロジェクトのテンプレートとして利用できます。

  1. Unity を開き、[New] (新規) をクリックします。

    新しい Unity プロジェクトを開始します。

  2. ここで、Unity プロジェクト名を指定する必要があります。 MR_ComputerVision と入力します。 プロジェクトの種類が [3D] に設定されていることを確認します。 [Location] (場所) を適切な場所に設定します (ルート ディレクトリに近い方が適しています)。 次に、[プロジェクトの作成] をクリックします。

    新しい Unity プロジェクトの詳細を指定します。

  3. Unity を開いた状態で、既定のスクリプト エディターVisual Studio に設定されているかどうか確認することをお勧めします。 [編集] > [基本設定] に移動し、新しいウィンドウで [外部ツール] に移動します。 [外部スクリプト エディター][Visual Studio 2017] に変更します。 [環境設定] ウィンドウを閉じます。

    スクリプト エディターの基本設定を更新します。

  4. 次に、[ファイル] > [ビルド設定] に移動して [ユニバーサル Windows プラットフォーム] を選び、[プラットフォームの切り替え] ボタンをクリックして選択を適用します。

    [ビルド設定] ウィンドウで、プラットフォームを UWP に切り替えます。

  5. 引き続き [ファイル] > [ビルド設定] で、次のことを確認します。

    1. [ターゲット デバイス][HoloLens] に設定されている

      イマーシブ ヘッドセットの場合は、[ターゲット デバイス][任意のデバイス] に設定します。

    2. [Build Type] (ビルドの種類)[D3D] に設定されている

    3. [SDK][Latest installed] (最新のインストール) に設定されている

    4. [Visual Studio Version] (Visual Studio のバージョン)[Latest installed] (最新のインストール) に設定されている

    5. [Build and Run] (ビルドと実行)[Local Machine] (ローカル マシン) に設定されている

    6. シーンを保存し、ビルドに追加します。

      1. これを行うには、[Add Open Scenes] (開いているシーンを追加) を選択します。 保存ウィンドウが表示されます。

        [開いているシーンの追加] ボタンをクリックします

      2. これと、今後のシーン用の新しいフォルダーを作成し、[新しいフォルダー] ボタンを選択して、新しいフォルダーを作成し、「Scenes」という名前を付けます。

        新しい scripts フォルダーを作成する

      3. 新しく作成した Scenes フォルダーを開き、"[File name:](ファイル名)" テキスト フィールドに「MR_ComputerVisionScene」と入力して [Save](保存) をクリックします。

        新しいシーンに名前を付けます。

        Unity のシーンは Unity プロジェクトに関連付けられている必要があるため、Assets フォルダー内に保存する必要があります。 Unity プロジェクトの構築では、通常、Scenes フォルダー (とその他の類似フォルダー) を作成します。

    7. [ビルド設定] の残りの設定は、ここでは既定値のままにしておきます。

  6. [ビルド設定] ウィンドウで、[プレーヤー設定] ボタンをクリックすると、[インスペクター] が配置されているスペースに関連パネルが表示されます。

    プレーヤーの設定を開きます。

  7. このパネルでは、いくつかの設定を確認する必要があります。

    1. [その他の設定] タブで、次の内容を確認します。

      1. [スクリプト ランタイムのバージョン][安定] である (.NET 3.5 と同等)。

      2. [Scripting Backend] (スクリプト バックエンド)[.NET] である

      3. [API Compatibility Level] (API 互換性レベル)[.NET 4.6] である

        その他の設定を更新します。

    2. [公開設定] タブ内の [機能] で、次の内容を確認します。

      1. InternetClient

      2. Web カメラ

        発行設定を更新しています。

    3. さらに、パネルの下にある [XR 設定] ([公開設定] の下) で、[Virtual Reality サポート] をオンにし、Windows Mixed Reality SDK が追加されていることを確認します。

      X R 設定を更新します。

  8. ビルド設定に戻ると、ユニティC#プロジェクトを灰色で表示しなくなり、その横にあるチェックボックスをティックします。

  9. [ビルド設定] ウィンドウを閉じます。

  10. シーンとプロジェクトを保存します ([ファイル] > [シーン/ファイルの保存] > [プロジェクトの保存])。

第 3 章 – メイン カメラのセットアップ

重要

このコースの "Unity のセットアップ" コンポーネントをスキップして、そのままコードに進みたい場合は、この .unitypackage をダウンロードし、これをカスタム パッケージとしてプロジェクトにインポートした後で第 5 章から続けてください。

  1. [Hierarchy] (階層) パネルで [Main Camera] (メイン カメラ) を選択します。

  2. 選択すると、[Main Camera] (メイン カメラ) のすべてのコンポーネントが [Inspector] (インスペクター) パネルに表示されます。

    1. カメラ オブジェクトの名前Main Camera である必要があります (スペルに注意します)。

    2. Main Camera タグMainCamera に設定する必要があります (スペルに注意します)。

    3. [変換の位置]0、0、0 に設定されていることを確認します。

    4. [Clear Flags] (クリア フラグ)[Solid Color] (単色) に設定します (イマーシブ ヘッドセットの場合は無視してください)。

    5. カメラ コンポーネントの [Background Color] (背景色)黒、アルファ 0 (16 進コード: #00000000) に設定します (イマーシブ ヘッドセットの場合は無視してください)。

      カメラ コンポーネントを更新します。

  3. 次に、Main Camera にアタッチされた単純な "カーソル" オブジェクトを作成する必要があります。これは、アプリケーションが実行されているときに画像分析の出力を配置するのに役立ちます。 このカーソルによって、カメラ フォーカスの中心点が決まります。

カーソルを作成するには:

  1. [Hierarchy] (階層) パネルで [Main Camera] (メイン カメラ) を右クリックします。 [3D Object] (3D オブジェクト) の下の [Sphere] (球) をクリックします。

    Cursor オブジェクトを選択します。

  2. 名前を Sphere から Cursor に変更し (カーソル オブジェクトをダブルクリックするか、このオブジェクトが選択されている状態で F2 キーを押します)、このオブジェクトが Main Camera の子として配置されていることを確認します。

  3. [Hierarchy] (階層) パネルで [Cursor] をクリックします。 [Cursor] が選択されている状態で、[Inspector] (インスペクター) パネルで次の変数を調整します。

    1. [Transform] (変換) の [Position] (位置) を 0、0、5 に設定します

    2. [Scale] (スケール) を 0.02、0.02、0.02 に設定します

      [位置とスケールの変換] を更新します。

第 4 章 – ラベル システムを設定する

HoloLens のカメラで画像をキャプチャすると、その画像は分析のためにご自分の Azure Computer Vision API サービス インスタンスに送信されます。

その分析の結果は、認識されたオブジェクトのリストであり、これらはタグと呼ばれます。

ラベル (ワールド空間の 3D テキストとして) は、写真が撮影された場所にこれらのタグを表示するために使用します。

次の手順で、ラベル オブジェクトを設定する方法を説明します。

  1. [Hierarchy] (階層) パネル内の任意の場所 (この時点ではどこでもかまいません) を右クリックし、[3D Object] (3D オブジェクト) の下の [3D Text] (3D テキスト) を追加します。 名前を LabelText に設定します。

    3D Text オブジェクトを作成します。

  2. [Hierarchy] (階層) パネルで [LabelText] をクリックします。 [LabelText] が選択されている状態で、[Inspector] (インスペクター) パネルで次の変数を調整します。

    1. [Position] (位置)0、0、0 に設定します
    2. [Scale] (スケール)0.01、0.01、0.01 に設定します
    3. コンポーネント [Text Mesh] (テキスト メッシュ) で:
    4. [Text] (テキスト) 内のすべてのテキストを "..." に置き換えます
    5. [Anchor] (アンカー)[Middle Center] (中央) に設定します
    6. [Alignment] (配置)[Center] (中央) に設定します
    7. [Tab Size] (タブ サイズ)4 に設定します
    8. [Font Size] (フォント サイズ)50 に設定します
    9. [Color] (色)#FFFFFFFF に設定します

    テキスト コンポーネント

  3. [LabelText] を [Hierarchy] (階層) パネルから [Project] (プロジェクト) パネル内の [Asset] (アセット) フォルダーにドラッグします。 これで LabelText がプレハブになり、コードでインスタンス化できます。

    LabelText オブジェクトのプレハブを作成します。

  4. LabelText を [Hierarchy] (階層) パネルから削除する必要があります。最初のシーンに表示されないようにするためです。 この時点で既にプレハブになっており、Assets フォルダーから個々のインスタンスに対して呼び出されるので、シーン内に残しておく必要はありません。

  5. [Hierarchy] (階層) パネルの最終的なオブジェクト構造は、次の画像のようになります。

    階層パネルの最終的な構造。

第 5 章 – ResultsLabel クラスを作成する

作成する必要がある最初のスクリプトは ResultsLabel クラスです。このクラスは、次のことを行います。

  • カメラの位置を基準にして、適切なワールド空間内にラベルを作成します。
  • 画像分析からのタグを表示します。

このクラスを作成するには:

  1. [プロジェクト] パネル内で右クリックし、[作成] > [フォルダー] の順に選択します。 フォルダーに「Scripts」という名前を付けます。

    scripts フォルダーを作成します。

  2. 作成した Scripts フォルダーをダブルクリックして開きます。 次に、そのフォルダー内で右クリックして [Create] (作成) >[C# Script] (C# スクリプト) を選択します。 スクリプトに「ResultsLabel」という名前を付けます。

  3. 新しい [ResultsLabel] スクリプトをダブルクリックして Visual Studio で開きます。

  4. ResultsLabel クラスに次のコードを挿入します。

        using System.Collections.Generic;
        using UnityEngine;
    
        public class ResultsLabel : MonoBehaviour
        {	
            public static ResultsLabel instance;
    
            public GameObject cursor;
    
            public Transform labelPrefab;
    
            [HideInInspector]
            public Transform lastLabelPlaced;
    
            [HideInInspector]
            public TextMesh lastLabelPlacedText;
    
            private void Awake()
            {
                // allows this instance to behave like a singleton
                instance = this;
            }
    
            /// <summary>
            /// Instantiate a Label in the appropriate location relative to the Main Camera.
            /// </summary>
            public void CreateLabel()
            {
                lastLabelPlaced = Instantiate(labelPrefab, cursor.transform.position, transform.rotation);
    
                lastLabelPlacedText = lastLabelPlaced.GetComponent<TextMesh>();
    
                // Change the text of the label to show that has been placed
                // The final text will be set at a later stage
                lastLabelPlacedText.text = "Analysing...";
            }
    
            /// <summary>
            /// Set the Tags as Text of the last Label created. 
            /// </summary>
            public void SetTagsToLastLabel(Dictionary<string, float> tagsDictionary)
            {
                lastLabelPlacedText = lastLabelPlaced.GetComponent<TextMesh>();
    
                // At this point we go through all the tags received and set them as text of the label
                lastLabelPlacedText.text = "I see: \n";
    
                foreach (KeyValuePair<string, float> tag in tagsDictionary)
                {
                    lastLabelPlacedText.text += tag.Key + ", Confidence: " + tag.Value.ToString("0.00 \n");
                }    
            }
        }
    
  5. Unity に戻る前に、必ず Visual Studio での変更を保存してください。

  6. Unity Editor に戻り、[Scripts] フォルダーにある [ResultsLabel] クラスをクリックして [Hierarchy] (階層) パネルの [Main Camera] オブジェクトにドラッグします。

  7. [Main Camera] をクリックして [Inspector] (インスペクター) パネルを見ます。

カメラにドラッグしたスクリプトには、[Cursor] (カーソル)[Label Prefab] (ラベル プレハブ) の 2 つのフィールドがあることがわかります。

  1. Cursor という名前のオブジェクトを、[Hierarchy] (階層) パネルから [Cursor] (カーソル) という名前のスロットにドラッグします (下図を参照)。

  2. LabelText という名前のオブジェクトを、[Project] (プロジェクト) パネルの [Assets] (アセット) フォルダーから [Label Prefab] (ラベル プレハブ) という名前のスロットにドラッグします。

    Unity 内で参照先を設定します。

第 6 章 – ImageCapture クラスを作成する

次に作成するクラスは ImageCapture クラスです。 このクラスは次のことを行います。

  • HoloLens のカメラを使って画像をキャプチャし、App フォルダーに格納します。
  • ユーザーのタップ ジェスチャをキャプチャします。

このクラスを作成するには:

  1. 先ほど作成した Scripts フォルダーに移動します。

  2. フォルダー内を右クリックし、[Create] (作成) > [C# Script] (C# スクリプト) を選びます。 スクリプトの名前を ImageCapture にします。

  3. 新しい ImageCapture スクリプトをダブルクリックして Visual Studio で開きます。

  4. ファイルの先頭に次の名前空間を追加します。

        using System.IO;
        using System.Linq;
        using UnityEngine;
        using UnityEngine.XR.WSA.Input;
        using UnityEngine.XR.WSA.WebCam;
    
  5. 次の変数を ImageCapture クラスの中の Start() メソッドの上に追加します。

        public static ImageCapture instance; 
        public int tapsCount;
        private PhotoCapture photoCaptureObject = null;
        private GestureRecognizer recognizer;
        private bool currentlyCapturing = false;
    

tapsCount 変数には、ユーザーからキャプチャされたタップ ジェスチャの数が格納されます。 この数値は、キャプチャされた画像の命名に使用されます。

  1. ここで、Awake() メソッドと Start() メソッドのコードを追加する必要があります。 これらは、クラスの初期化時に呼び出されます。

        private void Awake()
        {
            // Allows this instance to behave like a singleton
            instance = this;
        }
    
        void Start()
        {
            // subscribing to the HoloLens API gesture recognizer to track user gestures
            recognizer = new GestureRecognizer();
            recognizer.SetRecognizableGestures(GestureSettings.Tap);
            recognizer.Tapped += TapHandler;
            recognizer.StartCapturingGestures();
        }
    
  2. タップ ジェスチャが発生したときに呼び出されるハンドラーを実装します。

        /// <summary>
        /// Respond to Tap Input.
        /// </summary>
        private void TapHandler(TappedEventArgs obj)
        {
            // Only allow capturing, if not currently processing a request.
            if(currentlyCapturing == false)
            {
                currentlyCapturing = true;
    
                // increment taps count, used to name images when saving
                tapsCount++;
    
                // Create a label in world space using the ResultsLabel class
                ResultsLabel.instance.CreateLabel();
    
                // Begins the image capture and analysis procedure
                ExecuteImageCaptureAndAnalysis();
            }
        }
    

TapHandler() メソッドは、ユーザーからキャプチャされたタップの数をインクリメントし、現在のカーソル位置を使って新しいラベルの位置を決めます。

続いて、このメソッドは ExecuteImageCaptureAndAnalysis() メソッドを呼び出して、このアプリケーションのコア機能を開始します。

  1. 画像がキャプチャされて保存されると、次のハンドラーが呼び出されます。 プロセスが正常終了すると、その結果は分析のために VisionManager (まだ作成していません) に渡されます。

        /// <summary>
        /// Register the full execution of the Photo Capture. If successful, it will begin 
        /// the Image Analysis process.
        /// </summary>
        void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
        {
            // Call StopPhotoMode once the image has successfully captured
            photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
        }
    
        void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
        {
            // Dispose from the object in memory and request the image analysis 
            // to the VisionManager class
            photoCaptureObject.Dispose();
            photoCaptureObject = null;
            StartCoroutine(VisionManager.instance.AnalyseLastImageCaptured()); 
        }
    
  2. 次に、このアプリケーションで画像キャプチャ プロセスを開始して画像を格納するために使用するメソッドを追加します。

        /// <summary>    
        /// Begin process of Image Capturing and send To Azure     
        /// Computer Vision service.   
        /// </summary>    
        private void ExecuteImageCaptureAndAnalysis()  
        {    
            // Set the camera resolution to be the highest possible    
            Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();    
    
            Texture2D targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
    
            // Begin capture process, set the image format    
            PhotoCapture.CreateAsync(false, delegate (PhotoCapture captureObject)    
            {    
                photoCaptureObject = captureObject;    
                CameraParameters camParameters = new CameraParameters();    
                camParameters.hologramOpacity = 0.0f;    
                camParameters.cameraResolutionWidth = targetTexture.width;    
                camParameters.cameraResolutionHeight = targetTexture.height;    
                camParameters.pixelFormat = CapturePixelFormat.BGRA32;
    
                // Capture the image from the camera and save it in the App internal folder    
                captureObject.StartPhotoModeAsync(camParameters, delegate (PhotoCapture.PhotoCaptureResult result)
                {    
                    string filename = string.Format(@"CapturedImage{0}.jpg", tapsCount);
    
                    string filePath = Path.Combine(Application.persistentDataPath, filename);
    
                    VisionManager.instance.imagePath = filePath;
    
                    photoCaptureObject.TakePhotoAsync(filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);
    
                    currentlyCapturing = false;
                });   
            });    
        }
    

警告

このとき、Unity Editor の [Console] (コンソール) パネルにエラーが表示されます。 これは VisionManager クラスがコードで参照されているからですが、このクラスは次の章で作成します。

第 7 章 – Azure と画像分析を呼び出す

作成する必要がある最後のスクリプトは VisionManager クラスです。

このクラスは次のことを行います。

  • キャプチャされた最新の画像をバイト配列として読み込みます。
  • このバイト配列を、分析のためにご自分の Azure Computer Vision API サービス インスタンスに送信します。
  • 応答を JSON 文字列として受け取ります。
  • 応答を逆シリアル化し、結果として得られたタグを ResultsLabel に渡します。

このクラスを作成するには:

  1. Scripts フォルダーをダブルクリックして開きます。

  2. [Scripts] フォルダー内で右クリックし、[Create] (作成) > [C# Script] (C# スクリプト) をクリックします。 スクリプトに「VisionManager」という名前を付けます。

  3. この新しいスクリプトをダブルクリックして Visual Studio で開きます。

  4. VisionManager クラスの先頭にある名前空間を、次に示すのと同一になるように更新します。

        using System;
        using System.Collections;
        using System.Collections.Generic;
        using System.IO;
        using UnityEngine;
        using UnityEngine.Networking;
    
  5. スクリプトの先頭にある VisionManager クラスの "内部" (Start() メソッドの上) に、2 つの "クラス" を作成する必要があります。これらは、Azure からの逆シリアル化された JSON 応答を表します。

        [System.Serializable]
        public class TagData
        {
            public string name;
            public float confidence;
        }
    
        [System.Serializable]
        public class AnalysedObject
        {
            public TagData[] tags;
            public string requestId;
            public object metadata;
        }
    

    Note

    TagData クラスと AnalysedObject クラスの宣言の前に [System.Serializable] 属性を追加する必要があります。これで、Unity ライブラリでの逆シリアル化ができるようになります。

  6. VisionManager クラスの中に、次の変数を追加する必要があります。

        public static VisionManager instance;
    
        // you must insert your service key here!    
        private string authorizationKey = "- Insert your key here -";    
        private const string ocpApimSubscriptionKeyHeader = "Ocp-Apim-Subscription-Key";
        private string visionAnalysisEndpoint = "https://westus.api.cognitive.microsoft.com/vision/v1.0/analyze?visualFeatures=Tags";   // This is where you need to update your endpoint, if you set your location to something other than west-us.
    
        internal byte[] imageBytes;
    
        internal string imagePath;
    

    警告

    ご自分の認証キーauthorizationKey 変数に挿入されていることを確認してください。 この認証キーは、このコースの最初の第 1 章で取得したものです。

    警告

    visionAnalysisEndpoint 変数は、この例で指定したものとは異なる場合があります。 westus は、米国西部リージョン用に作成されたサービス インスタンスを厳密に参照します。 これをご自分のエンドポイント URL で更新してください。次に例をいくつか示します。

    • 西ヨーロッパ: https://westeurope.api.cognitive.microsoft.com/vision/v1.0/analyze?visualFeatures=Tags
    • 東南アジア: https://southeastasia.api.cognitive.microsoft.com/vision/v1.0/analyze?visualFeatures=Tags
    • オーストラリア東部: https://australiaeast.api.cognitive.microsoft.com/vision/v1.0/analyze?visualFeatures=Tags
  7. 次に、Awake のコードを追加する必要があります。

        private void Awake()
        {
            // allows this instance to behave like a singleton
            instance = this;
        }
    
  8. 次に、コルーチン (およびその下の静的ストリーム メソッド) を追加します。これは、ImageCapture クラスによってキャプチャされた画像の分析結果を取得するためのものです。

        /// <summary>
        /// Call the Computer Vision Service to submit the image.
        /// </summary>
        public IEnumerator AnalyseLastImageCaptured()
        {
            WWWForm webForm = new WWWForm();
            using (UnityWebRequest unityWebRequest = UnityWebRequest.Post(visionAnalysisEndpoint, webForm))
            {
                // gets a byte array out of the saved image
                imageBytes = GetImageAsByteArray(imagePath);
                unityWebRequest.SetRequestHeader("Content-Type", "application/octet-stream");
                unityWebRequest.SetRequestHeader(ocpApimSubscriptionKeyHeader, authorizationKey);
    
                // the download handler will help receiving the analysis from Azure
                unityWebRequest.downloadHandler = new DownloadHandlerBuffer();
    
                // the upload handler will help uploading the byte array with the request
                unityWebRequest.uploadHandler = new UploadHandlerRaw(imageBytes);
                unityWebRequest.uploadHandler.contentType = "application/octet-stream";
    
                yield return unityWebRequest.SendWebRequest();
    
                long responseCode = unityWebRequest.responseCode;     
    
                try
                {
                    string jsonResponse = null;
                    jsonResponse = unityWebRequest.downloadHandler.text;
    
                    // The response will be in Json format
                    // therefore it needs to be deserialized into the classes AnalysedObject and TagData
                    AnalysedObject analysedObject = new AnalysedObject();
                    analysedObject = JsonUtility.FromJson<AnalysedObject>(jsonResponse);
    
                    if (analysedObject.tags == null)
                    {
                        Debug.Log("analysedObject.tagData is null");
                    }
                    else
                    {
                        Dictionary<string, float> tagsDictionary = new Dictionary<string, float>();
    
                        foreach (TagData td in analysedObject.tags)
                        {
                            TagData tag = td as TagData;
                            tagsDictionary.Add(tag.name, tag.confidence);                            
                        }
    
                        ResultsLabel.instance.SetTagsToLastLabel(tagsDictionary);
                    }
                }
                catch (Exception exception)
                {
                    Debug.Log("Json exception.Message: " + exception.Message);
                }
    
                yield return null;
            }
        }
    
        /// <summary>
        /// Returns the contents of the specified file as a byte array.
        /// </summary>
        private static byte[] GetImageAsByteArray(string imageFilePath)
        {
            FileStream fileStream = new FileStream(imageFilePath, FileMode.Open, FileAccess.Read);
            BinaryReader binaryReader = new BinaryReader(fileStream);
            return binaryReader.ReadBytes((int)fileStream.Length);
        }  
    
  9. Unity に戻る前に、必ず Visual Studio での変更を保存してください。

  10. Unity Editor に戻り、[Scripts] (スクリプト) フォルダーにある VisionManager クラスと ImageCapture クラスをクリックして、[Hierarchy] (階層) パネルの [Main Camera] オブジェクトにドラッグします。

第 8 章 – ビルドする前に

アプリケーションの完全なテストを実行するには、アプリケーションを HoloLens にサイドロードする必要があります。 実行する前に、次のことを確認してください。

  • 第 2 章で説明されている設定がすべて正しく設定されています。
  • すべてのスクリプトが Main Camera オブジェクトにアタッチされています。
  • Main Camera の [Inspector] (インスペクター) パネルのすべてのフィールドに適切な値が割り当てられています。
  • ご自分の認証キーauthorizationKey 変数に挿入されていることを確認してください。
  • また、VisionManager スクリプトの中に記述されているご自分のエンドポイントが正しいことと、これが "ご自分の" リージョン (このドキュメントでは、既定で "米国西部" を使用します) と一致していることも確認してください。

第 9 章 – UWP ソリューションをビルドし、アプリケーションをサイドロードする

このプロジェクトの Unity セクションに必要なすべての手順が完了したので、ここで Unity からビルドします。

  1. [Build Settings] (ビルド設定) に移動します。( - [File] (ファイル) > [Build Settings...] (ビルド設定...))

  2. [Build Settings] (ビルド設定) ウィンドウで、[Build] (ビルド) をクリックします。

    Unity からアプリをビルドする

  3. [Unity C# プロジェクト] をオンにします (まだオンにしていない場合)。

  4. [ビルド] をクリックします。 Unity によって [エクスプローラー] ウィンドウが起動されます。そこで、アプリのビルド先のフォルダーを作成して選択する必要があります。 ここでそのフォルダーを作成して、「App」という名前を付けます。 次に、App フォルダーを選択した状態で、[フォルダーの選択] を押します。

  5. Unity で、App フォルダーに対してプロジェクトのビルドが開始されます。

  6. Unity によるビルドが完了すると (多少時間がかかる場合があります)、エクスプローラーのウィンドウが開いて、ビルドの場所が表示されます (必ずしも最前面に表示されるとは限らないため、タスク バーを確認すると新しいウィンドウが追加されたことがわかります)。

第 10 章 – HoloLens にデプロイする

HoloLens にデプロイするには、次の手順を実行します。

  1. HoloLens の IP アドレスが必要になります (リモート デプロイの場合)。また、HoloLens が開発者モードになっていることを確認する必要があります。 手順は次のとおりです。

    1. HoloLens を装着した状態で、[設定] を開きます。
    2. [ネットワーク & インターネット>] Wi-Fi > [詳細オプション] に移動します
    3. IPv4 アドレスを書き留めます。
    4. 次に、[設定] に戻り、[Update & Security for Developers]\(開発者向けセキュリティ>の更新\) に移動します
    5. [開発者モード] を [オン] に設定します。
  2. 新しい Unity ビルド (App フォルダー) に移動し、Visual Studio を使用してソリューション ファイルを開きます。

  3. [ソリューション構成] で、[デバッグ] を選択します。

  4. ソリューション プラットフォームで、[X86][リモート コンピューター] を選択します。

    Visual Studio からソリューションをデプロイします。

  5. [ビルド] メニューに移動して [ソリューションの配置] をクリックして、アプリケーションを HoloLens にサイドロードします。

  6. HoloLens にインストールされたアプリの一覧にこのアプリが表示され、起動できる状態になります。

Note

イマーシブ ヘッドセットにデプロイするには、[Solution Platform](ソリューション プラットフォーム)[Local Machine](ローカル コンピューター)に設定し、[Configuration](構成)[Debug](デバッグ) にし、プラットフォームとして x86 を設定します。 次に、[ビルド] メニューの [ソリューションの配置] を選択してローカル コンピューターにデプロイします。

完成した Computer Vision API アプリケーション

これで、Mixed Reality アプリが 1 つ完成しました。このアプリでは Azure Computer Vision API を利用して現実世界のオブジェクトを認識し、見えたものの信頼度を表示することができます。

ラボの結果

ボーナス演習

演習 1

Tags パラメーター (VisionManager 内で使用されている endpoint の中にあります) を使用したのと同様に、アプリの機能を拡張してその他の情報を検出してください。アクセスできるその他のパラメーターについてはこちらをご覧ください。

演習 2

Azure から返されたデータを、会話らしく、読みやすく表示してください。数値を非表示にするとよいでしょう。 ボットがユーザーに話しかけているというイメージです。