HoloLens (第 1 世代) と Azure 303: 自然言語の理解 (LUIS)


Note

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


このコースでは、Language Understanding API で Azure Cognitive Services を使用して Mixed Reality アプリケーションに Language Understanding を統合する方法について説明します。

ラボの結果

Language Understanding (LUIS) は Microsoft Azure サービスです。このサービスにより、アプリケーションは、ユーザーが必要とするものを抽出するなどして、ユーザーの入力を独自の言葉で除外することができます。 これは機械学習を通じて実現されます。機械学習では、入力情報を認識して学習した後、詳細な関連情報を返信できます。 詳細については、Azure Language Understanding (LUIS) のページを参照してください。

このコースを修了すると、次のことができる Mixed Reality イマーシブ ヘッドセット アプリケーションを手に入れることができます。

  1. イマーシブ ヘッドセットに接続されているマイクを使用して、ユーザー入力音声をキャプチャします。
  2. キャプチャしたディクテーションを Azure Language Understanding Intelligent Service (LUIS) に送信します。
  3. LUIS では、送信情報から意味を抽出して分析し、ユーザーの要求の意図を判断しようとします。

開発には、ユーザーが音声を使用したり視線入力してシーン内のオブジェクトのサイズと色を変更できるアプリの作成が含まれます。 モーション コントローラーの使用については説明しません。

アプリケーションで結果をどのようにデザインと統合するかは自由です。 このコースは、Azure のサービスを Unity プロジェクトに統合する方法を学べるよう設計されています。 このコースで得られた知識を使用して、ご自分の Mixed Reality アプリケーションを強化しましょう。

LUIS を複数回トレーニングできるように準備します。これについては、第 12 章で説明します。 LUIS がトレーニングされると、より多くの結果が得られます。

デバイス サポート

コース HoloLens イマーシブ ヘッドセット
MR と Azure 303: 自然言語の理解 (LUIS) ✔️ ✔️

注意

このコースでは Windows Mixed Reality イマーシブ (VR) ヘッドセットを中心に取り上げていますが、このコースで習得したことは、Microsoft HoloLens にも応用できます。 このコースに取り組む過程で、HoloLens をサポートするために別途行う必要のある変更があれば、注意事項として記載しています。 HoloLens を使用すると、音声キャプチャ中に反響音が生じることがあります。

前提条件

Note

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

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

開始する前に

  1. このプロジェクトをビルドする際の問題を避けるために、このチュートリアルで紹介するプロジェクトをルートまたはルートに近いフォルダーに作成することを強くお勧めします (フォルダー パスが長いと、ビルド時に問題が発生する可能性があります)。

  2. コンピューターでディクテーションを有効にするには、[Windows の設定] [プライバシー>の音声]>、[手描き入力] & [入力] に移動し、[音声サービスをオンにして候補を入力する] ボタンを押します。

  3. このチュートリアルのコードを使用すると、コンピューターに設定されている既定のマイク デバイスから録音できます。 既定のマイク デバイスが、音声をキャプチャするために使用するものとして設定されていることを確認します。

  4. ヘッドセットにマイクが内蔵されている場合、Mixed Reality ポータルの設定で [ヘッドセット着用時はヘッドセットのマイクに切り替える] オプションがオンになっていることを確認します。

    イマーシブ ヘッドセットの設定

第 1 章 – Azure portal を設定する

Azure で Language Understanding サービスを使用するには、アプリケーションで使用できるようにサービスのインスタンスを構成する必要があります。

  1. Azure Portal にログインします。

    Note

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

  2. ログインしたら、左上隅にある[新規作成] をクリックして、Language Understanding を検索し、Enter キーを押します。

    LUIS リソースの作成

    Note

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

  3. 右側の新しいページには、Language Understanding サービスの説明が表示されます。 このページの左下にある [作成] ボタンをクリックすると、このサービスのインスタンスが作成されます。

    LUIS サービスの作成 - 法的通知

  4. [作成] をクリックしたら、次のようにします。

    1. このサービス インスタンスの任意の [名前] を入力します。

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

    3. 適切な [価格レベル] を選択します。これが初めて作成する LUIS Service の場合は、無料レベル (F0 という名前) を使用できるはずです。 無料の割り当て分でもこのコースには十分です。

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

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

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

    6. また、本サービスに適用される利用規約を理解していることを確認する必要があります。

    7. [作成] を選択します

      LUIS サービスの作成 - ユーザー入力

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

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

    新しい Azure 通知イメージ

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

    リソースの作成に成功した通知

  8. 通知の [リソースに移動] ボタンをクリックして、新しいサービス インスタンスを確認します。 新しい LUIS サービス インスタンスが表示されます。

    LUIS キーへのアクセス

  9. このチュートリアルでは、アプリケーションがサービスの呼び出しを行う必要があります。これは、サービスのサブスクリプション キーを使用して実行されます。

  10. LUIS API サービスの [クイック スタート] ページで、最初の手順の [キーを取得する] に移動して、[キー] をクリックします (サービスのナビゲーション メニューにある鍵のアイコンで示された青いハイパーリンクの [キー] をクリックして、これを行うこともできます)。 これにより、サービスの "キー" が表示されます。

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

  12. [サービス] ページで、[Language Understanding ポータル] をクリックして、LUIS アプリ内で新しいサービスの作成に使用する Web ページにリダイレクトします。

第 2 章 – Language Understanding ポータル

このセクションでは、LUIS ポータルで LUIS アプリを作成する方法について説明します。

重要

この章では "エンティティ"、"意図"、および "発話" を設定しますが、これは LUIS サービス構築の最初の手順にすぎないことに注意してください。サービスを何度も再トレーニングして、より正確なものにする必要もあります。 サービスの再トレーニングについては、このコースの最後の章で説明されています。完了していることを確認してください。

  1. Language Understanding ポータルにアクセスしたら、Azure portal と同じ資格情報を使用してログインすることが必要な場合があります (まだログインしていない場合)。

    LUIS ログイン ページ

  2. LUIS を初めて使用する場合は、[ようこそ] ページの一番下までスクロールし、[LUIS アプリの作成] ボタンを見つけてクリックする必要があります。

    LUIS アプリの作成ページ

  3. ログインしたら、[マイ アプリ] をクリックします (現在このセクションにいない場合)。 次に [新しいアプリの作成] をクリックします。

    LUIS - マイ アプリイメージ

  4. アプリに名前を付けます。

  5. アプリで英語以外の言語を認識する場合は、[カルチャ] を適切な言語に変更する必要があります。

  6. ここでは、新しい LUIS アプリの [説明] を追加することもできます。

    LUIS - 新しいアプリを作成する

  7. [完了] を押すと、新しい LUIS アプリケーションの [ビルド] ページが表示されます。

  8. ここで理解しておくべき重要な概念がいくつかあります。

    • "意図" は、ユーザーからのクエリに従って呼び出されるメソッドを表します。 "意図" には、1 つまたは複数の "エンティティ" を含めることができます。
    • "エンティティ" は、"意図" に関連する情報を記述するクエリのコンポーネントです。
    • "発話" は、開発者によって提供されるクエリの例であり、自身をトレーニングするために LUIS が使用します。

これらの概念をはっきり理解できていなくても問題ありません。この章ではさらに詳しく説明します。

最初に、このコースを構築するために必要な "エンティティ" を作成します。

  1. ページの左側にある [エンティティ] をクリックし、[新しいエンティティの作成] をクリックします。

    新しいエンティティを作成する

  2. 新しいエンティティに「」という名前を付け、その種類を [シンプル] に設定して [完了] を押します。

    単純なエンティティの作成 - 色

  3. このプロセスを繰り返して、次の名前のシンプルなエンティティをあと 3 つ作成します。

    • アップサイズ
    • ダウンサイズ
    • target

結果は次の図のようになります。

エンティティ作成の結果

この時点で、意図の作成を開始できます。

警告

"None" という意図は削除しないでください。

  1. ページの左側にある [意図] をクリックし、[新しいエンティティの作成] をクリックします。

    新しい意図を作成する

  2. 新しい意図に「ChangeObjectColor」という名前を付けます。

    重要

    この意図の名前は、このコースの後半でコード内で使用されます。したがって、最適な結果を得るために、この名前を指定されたとおりに使用してください。

名前を確認すると、[意図] ページにリダイレクトされます。

LUIS - 意図ページ

5 つ以上の異なる "発話" を入力するよう求めるテキスト ボックスが表示されます。

Note

すべての発話は LUIS によって小文字に変換されます。

  1. (現在は "5 つくらいの例を入力してください..." というテキストが表示されている) 上部のテキスト ボックスに次の発話を入力して、Enter キーを押します。
The color of the cylinder must be red

その新しい発話が、下の一覧に表示されます。

同じ手順を繰り返して、次の 6 つの発話を入力します。

make the cube black

make the cylinder color white

change the sphere to red

change it to green

make this yellow

change the color of this object to blue

作成した発話ごとに、LUIS でエンティティとして使用する単語を識別する必要があります。 この例では、すべての色に "色" エンティティのラベルを、ターゲットへの参照になる可能性があるものすべてに "ターゲット" エンティティのラベルを付ける必要があります。

  1. これを行うために、最初の発話の "円柱" という単語をクリックして "ターゲット" を選択してみてください。

    発話ターゲットを識別する

  2. 次に、最初の発話の "赤" という単語をクリックして、"色" を選択します。

    発話エンティティを識別する

  3. 次の行にもラベルを付けます。"立方体" は "ターゲット" に、"黒" は "色" にする必要があります。 具体的でないターゲットの種類も利用できるように、提供している例では "これ"、"それ"、"このオブジェクト" などの語も使用しています。

  4. すべての発話がラベル付きのエンティティを持つようになるまで、上記の手順を繰り返します。 ヘルプが必要な場合は、次の図を参照してください。

    ヒント

    エンティティ ラベルを付ける単語を選択するときは:

    • 単語が 1 つの場合は、クリックするだけです。
    • 2 つ以上の単語のセットについては、セットの先頭と末尾をクリックします。

    Note

    [トークン ビュー] トグルボタンを使用して、エンティティ ビューとトークン ビューを切り替えることができます。

  5. 次の図は、エンティティ ビューとトークン ビューのそれぞれに表示された結果を示しています。

    エンティティ ビュー & トークン

  6. この時点で、ページの右上にある [トレーニング] ボタンを押して、小さな丸のインジケーターが緑色になるまで待ちます。 これは、この意図を認識するために LUIS のトレーニングが正常に行われたことを示します。

    LUIS のトレーニング

  7. この演習では、"ターゲット"、"アップサイズ"、"ダウンサイズ" の各エンティティを使用して、ChangeObjectSize という新しい意図を作成します。

  8. 前の意図と同じ手順に従って、"サイズ" の変更に関する次の 8 つの発話を入力します。

    increase the dimensions of that
    
    reduce the size of this
    
    i want the sphere smaller
    
    make the cylinder bigger
    
    size down the sphere
    
    size up the cube
    
    decrease the size of that object
    
    increase the size of this object
    
  9. 結果は次の図のようになります。

    ChangeObjectSize トークン/エンティティを設定する

  10. ChangeObjectColorChangeObjectSize の両方の意図の作成とトレーニングが完了したら、ページの上部にある [発行] ボタンをクリックします。

    LUIS サービスを発行する

  11. [発行] ページで、LUIS アプリを完成させ発行して、コードからアクセスできるようにします。

    1. [発行先] ドロップダウンを [運用環境] に設定します。

    2. [タイム ゾーン] を、使用する地域のタイム ゾーンに設定します。

    3. [予測されるすべての意図スコアを含める] チェック ボックスをオンにします。

    4. [運用スロットに発行] をクリックします。

      発行設定

  12. [リソースとキー] セクションで、次の手順を実行します。

    1. Azure Portal でサービス インスタンスに設定するリージョンを選択します。
    2. 次の Starter_Key 要素があることがわかりますが、無視します。
    3. [キーの追加] をクリックし、サービス インスタンスを作成するときに Azure Portal で取得した "キー" を入力します。 Azure と LUIS ポータルが同じユーザーにログインしている場合は、[テナント名]、[サブスクリプション名]、および使用する [キー] のドロップダウン メニューが表示されます (Azure portal で以前に指定したものと同じ名前になります)。

    重要

    [エンドポイント] には、入力したキーに対応するエンドポイントが表示されています。直後にコードで使用するので、コピーしておきます。

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

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

  1. Unity を開き、[新規作成] をクリックします。

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

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

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

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

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

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

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

  5. [ファイル] > [ビルド設定] に移動して、次を確認します。

    1. [Target Device] (ターゲット デバイス)[Any Device] (任意のデバイス) に設定されている

      Microsoft HoloLens の場合は、[Target Device] (ターゲット デバイス)[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 フォルダーを開き、[ファイル名] テキスト フィールドに「MR_LuisScene」と入力して [保存] をクリックします。

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

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

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

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

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

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

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

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

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

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

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

      1. InternetClient

      2. マイク

        発行設定の更新。

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

      X R 設定を更新します。

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

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

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

第 4 章 – シーンを作成する

重要

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

  1. [階層] パネルの何もない領域を右クリックし、[3D オブジェクト][平面] の順に選択して追加します。

    平面を作成します。

  2. [階層] 内で右クリックしてさらにオブジェクトを作成する場合、最後のオブジェクトがまだ選択されていると、選択したオブジェクトが新しいオブジェクトの親になることに注意してください。 これを回避するには、[階層] 内の何もない領域で左クリックしてから右クリックします。

  3. 上記の手順を繰り返して、次のオブジェクトを追加します。

    1. Sphere
    2. [円柱]
    3. Cube
    4. 3D テキスト
  4. 結果のシーンの [階層] は次の図のようになります。

    シーン階層の設定。

  5. [メイン カメラ] を左クリックして選択します。[インスペクター] パネルに、[カメラ] オブジェクトとそのコンポーネントのすべてが表示されます。

  6. [インスペクター] パネルの一番下にある [コンポーネントの追加] ボタンをクリックします。

    オーディオ ソースの追加

  7. 上の図のように、"オーディオ ソース" という名前のコンポーネントを検索します。

  8. [メイン カメラ] の [変換] コンポーネントが (0,0,0) に設定されていることも確認してください。このように設定するには、[カメラ] の [変換] コンポーネントの横にある歯車のアイコンを押して [リセット] を選択します。 [変換] コンポーネントは次のようになります。

    1. [位置] は 0, 0, 0 に設定されます。
    2. [回転] は 0, 0, 0 に設定されます。

    Note

    Microsoft HoloLens の場合、[メイン カメラ]上にある [カメラ] コンポーネントの一部である以下も変更する必要があります。

    • [クリア フラグ]: 単色。
    • [背景] "黒、アルファ 0" – [Hex カラー]: #00000000
  9. [平面] を左クリックして選択します。 [インスペクター] パネルで、[変換] コンポーネントに次の値を設定します。

    X 軸 Y 軸 Z 軸
    0 -1 0
  10. [球] を左クリックして選択します。 [インスペクター] パネルで、[変換] コンポーネントに次の値を設定します。

    X 軸 Y 軸 Z 軸
    2 1 2
  11. [円柱] を左クリックして選択します。 [インスペクター] パネルで、[変換] コンポーネントに次の値を設定します。

    X 軸 Y 軸 Z 軸
    -2 1 2
  12. [立方体] を左クリックして選択します。 [インスペクター] パネルで、[変換] コンポーネントに次の値を設定します。

変換 - 位置

X Y Z
0 1 4

変換 - 回転

X Y Z
45 45 0
  1. [新しいテキスト] オブジェクトを左クリックして選択します。 [インスペクター] パネルで、[変換] コンポーネントに次の値を設定します。

変換 - 位置

X Y Z
-2 6 9

変換 - スケール

X Y Z
0.1 0.1 0.1
  1. [テキスト メッシュ] コンポーネントの [フォント サイズ]50 に変更します。

  2. [テキスト メッシュ] オブジェクトの名前を "ディクテーション テキスト" に変更します。

    3D Text オブジェクトを作成する

  3. [階層] パネルの構造は次のようになります。

    シーン ビューのテキスト メッシュ

  4. 最終的なシーンは次の図のようになります。

    シーン ビュー。

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

最初に作成するスクリプトは、MicrophoneManager クラスです。 次に、LuisManagerBehaviours クラス、最後に Gaze クラスを作成します (各章で取り扱いますが、すべてをここで作成してもかまいません)。

MicrophoneManager クラスは次の責任を負います。

  • ヘッドセットまたはコンピューターに接続されている録音デバイス (既定のものである方) を検出する。
  • オーディオ (音声) をキャプチャし、ディクテーションを使用して文字列として保存する。
  • 音声が一時停止したら、LuisManager クラスにディクテーションを送信する。

このクラスを作成するには、次の手順を実行します。

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

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

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

  3. MicrophoneManager をダブルクリックして、Visual Studio で開きます。

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

        using UnityEngine;
        using UnityEngine.Windows.Speech;
    
  5. 次に、MicrophoneManager クラス内に以下の変数を追加します。

        public static MicrophoneManager instance; //help to access instance of this object
        private DictationRecognizer dictationRecognizer;  //Component converting speech to text
        public TextMesh dictationText; //a UI object used to debug dictation result
    
  6. ここで、Awake() メソッドと Start() メソッドのコードを追加する必要があります。 これらは、クラスの初期化時に呼び出されます。

        private void Awake()
        {
            // allows this class instance to behave like a singleton
            instance = this;
        }
    
        void Start()
        {
            if (Microphone.devices.Length > 0)
            {
                StartCapturingAudio();
                Debug.Log("Mic Detected");
            }
        }
    
  7. ここで、音声キャプチャを開始および停止し、その音声キャプチャをこの後の手順で作成する LuisManager クラスに渡すのにアプリが使用するメソッドが必要になります。

        /// <summary>
        /// Start microphone capture, by providing the microphone as a continual audio source (looping),
        /// then initialise the DictationRecognizer, which will capture spoken words
        /// </summary>
        public void StartCapturingAudio()
        {
            if (dictationRecognizer == null)
            {
                dictationRecognizer = new DictationRecognizer
                {
                    InitialSilenceTimeoutSeconds = 60,
                    AutoSilenceTimeoutSeconds = 5
                };
    
                dictationRecognizer.DictationResult += DictationRecognizer_DictationResult;
                dictationRecognizer.DictationError += DictationRecognizer_DictationError;
            }
            dictationRecognizer.Start();
            Debug.Log("Capturing Audio...");
        }
    
        /// <summary>
        /// Stop microphone capture
        /// </summary>
        public void StopCapturingAudio()
        {
            dictationRecognizer.Stop();
            Debug.Log("Stop Capturing Audio...");
        }
    
  8. 音声が一時停止したときに呼び出される "ディクテーション ハンドラー" を追加します。 このメソッドは、ディクテーション テキストを LuisManager クラスに渡します。

        /// <summary>
        /// This handler is called every time the Dictation detects a pause in the speech. 
        /// This method will stop listening for audio, send a request to the LUIS service 
        /// and then start listening again.
        /// </summary>
        private void DictationRecognizer_DictationResult(string dictationCaptured, ConfidenceLevel confidence)
        {
            StopCapturingAudio();
            StartCoroutine(LuisManager.instance.SubmitRequestToLuis(dictationCaptured, StartCapturingAudio));
            Debug.Log("Dictation: " + dictationCaptured);
            dictationText.text = dictationCaptured;
        }
    
        private void DictationRecognizer_DictationError(string error, int hresult)
        {
            Debug.Log("Dictation exception: " + error);
        }
    

    重要

    Update() メソッドは、このクラスでは使用しないので削除します。

  9. Unity に戻る前に、必ず Visual Studio で変更を保存してください。

    Note

    この時点で、Unity エディターの [コンソール] パネルにエラーが表示されます。 これは、次の章で作成する LuisManager クラスがコードで参照されているためです。

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

次に、LuisManager クラスを作成します。このクラスは、Azure LUIS サービスの呼び出しを行います。

このクラスの目的は、MicrophoneManager クラスからディクテーション テキストを受け取り、分析のために Azure Language Understanding API に送信することです。

このクラスは、JSON 応答を逆シリアル化し、Behaviours クラスの適切なメソッドを呼び出してアクションをトリガーします。

このクラスを作成するには、次の手順を実行します。

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

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

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

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

        using System;
        using System.Collections;
        using System.Collections.Generic;
        using System.IO;
        using UnityEngine;
        using UnityEngine.Networking;
    
  5. まず、LuisManager クラスの内部 (同じスクリプト ファイル内、Start() メソッドの上) に、Azure からの逆シリアル化された JSON 応答を表す 3 つのクラスを作成します。

        [Serializable] //this class represents the LUIS response
        public class AnalysedQuery
        {
            public TopScoringIntentData topScoringIntent;
            public EntityData[] entities;
            public string query;
        }
    
        // This class contains the Intent LUIS determines 
        // to be the most likely
        [Serializable]
        public class TopScoringIntentData
        {
            public string intent;
            public float score;
        }
    
        // This class contains data for an Entity
        [Serializable]
        public class EntityData
        {
            public string entity;
            public string type;
            public int startIndex;
            public int endIndex;
            public float score;
        }
    
  6. 次に、LuisManager クラス内に以下の変数を追加します。

        public static LuisManager instance;
    
        //Substitute the value of luis Endpoint with your own End Point
        string luisEndpoint = "https://westus.api.cognitive... add your endpoint from the Luis Portal";
    
  7. 必ず、ここで LUIS エンドポイントを配置してください (LUIS ポータルから取得します)。

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

        private void Awake()
        {
            // allows this class instance to behave like a singleton
            instance = this;
        }
    
  9. 次に、このアプリケーションが MicrophoneManager クラスから受信したディクテーションを LUIS に送信し、応答を受信して逆シリアル化するために使用するメソッドが必要になります。

  10. 意図の値と、関連付けられたエンティティが決定されると、意図したアクションをトリガーするために、これらが Behaviours クラスのインスタンスに渡されます。

        /// <summary>
        /// Call LUIS to submit a dictation result.
        /// The done Action is called at the completion of the method.
        /// </summary>
        public IEnumerator SubmitRequestToLuis(string dictationResult, Action done)
        {
            string queryString = string.Concat(Uri.EscapeDataString(dictationResult));
    
            using (UnityWebRequest unityWebRequest = UnityWebRequest.Get(luisEndpoint + queryString))
            {
                yield return unityWebRequest.SendWebRequest();
    
                if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError)
                {
                    Debug.Log(unityWebRequest.error);
                }
                else
                {
                    try
                    {
                        AnalysedQuery analysedQuery = JsonUtility.FromJson<AnalysedQuery>(unityWebRequest.downloadHandler.text);
    
                        //analyse the elements of the response 
                        AnalyseResponseElements(analysedQuery);
                    }
                    catch (Exception exception)
                    {
                        Debug.Log("Luis Request Exception Message: " + exception.Message);
                    }
                }
    
                done();
                yield return null;
            }
        }
    
  11. 結果の AnalysedQuery を読み取ってエンティティを決定する、AnalyseResponseElements() という名前の新しいメソッドを作成します。 これらのエンティティが決定されると、アクションで使用するために Behaviours クラスのインスタンスに渡されます。

        private void AnalyseResponseElements(AnalysedQuery aQuery)
        {
            string topIntent = aQuery.topScoringIntent.intent;
    
            // Create a dictionary of entities associated with their type
            Dictionary<string, string> entityDic = new Dictionary<string, string>();
    
            foreach (EntityData ed in aQuery.entities)
            {
                entityDic.Add(ed.type, ed.entity);
            }
    
            // Depending on the topmost recognized intent, read the entities name
            switch (aQuery.topScoringIntent.intent)
            {
                case "ChangeObjectColor":
                    string targetForColor = null;
                    string color = null;
    
                    foreach (var pair in entityDic)
                    {
                        if (pair.Key == "target")
                        {
                            targetForColor = pair.Value;
                        }
                        else if (pair.Key == "color")
                        {
                            color = pair.Value;
                        }
                    }
    
                    Behaviours.instance.ChangeTargetColor(targetForColor, color);
                    break;
    
                case "ChangeObjectSize":
                    string targetForSize = null;
                    foreach (var pair in entityDic)
                    {
                        if (pair.Key == "target")
                        {
                            targetForSize = pair.Value;
                        }
                    }
    
                    if (entityDic.ContainsKey("upsize") == true)
                    {
                        Behaviours.instance.UpSizeTarget(targetForSize);
                    }
                    else if (entityDic.ContainsKey("downsize") == true)
                    {
                        Behaviours.instance.DownSizeTarget(targetForSize);
                    }
                    break;
            }
        }
    

    重要

    Start() メソッドと Update() メソッドは、このクラスでは使用しないので削除します。

  12. Unity に戻る前に、必ず Visual Studio で変更を保存してください。

Note

この時点で、Unity エディターの [コンソール] パネルにいくつかのエラーが表示されます。 これは、次の章で作成する Behaviours クラスがコードで参照されているためです。

第 7 章 – Behaviours クラスを作成する

Behaviours クラスは、LuisManager クラスによって提供されるエンティティを使用してアクションをトリガーします。

このクラスを作成するには、次の手順を実行します。

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

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

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

  4. 次に、Behaviours クラス内に以下の変数を追加します。

        public static Behaviours instance;
    
        // the following variables are references to possible targets
        public GameObject sphere;
        public GameObject cylinder;
        public GameObject cube;
        internal GameObject gazedTarget;
    
  5. Awake() メソッドのコードを追加します。 このメソッドは、クラスの初期化時に呼び出されます。

        void Awake()
        {
            // allows this class instance to behave like a singleton
            instance = this;
        }
    
  6. 次のメソッドは、どのオブジェクトがクエリのターゲットであるかを決定して適切なアクションをトリガーするために、(前に作成した) LuisManager クラスによって呼び出されます。

        /// <summary>
        /// Changes the color of the target GameObject by providing the name of the object
        /// and the name of the color
        /// </summary>
        public void ChangeTargetColor(string targetName, string colorName)
        {
            GameObject foundTarget = FindTarget(targetName);
            if (foundTarget != null)
            {
                Debug.Log("Changing color " + colorName + " to target: " + foundTarget.name);
    
                switch (colorName)
                {
                    case "blue":
                        foundTarget.GetComponent<Renderer>().material.color = Color.blue;
                        break;
    
                    case "red":
                        foundTarget.GetComponent<Renderer>().material.color = Color.red;
                        break;
    
                    case "yellow":
                        foundTarget.GetComponent<Renderer>().material.color = Color.yellow;
                        break;
    
                    case "green":
                        foundTarget.GetComponent<Renderer>().material.color = Color.green;
                        break;
    
                    case "white":
                        foundTarget.GetComponent<Renderer>().material.color = Color.white;
                        break;
    
                    case "black":
                        foundTarget.GetComponent<Renderer>().material.color = Color.black;
                        break;
                }          
            }
        }
    
        /// <summary>
        /// Reduces the size of the target GameObject by providing its name
        /// </summary>
        public void DownSizeTarget(string targetName)
        {
            GameObject foundTarget = FindTarget(targetName);
            foundTarget.transform.localScale -= new Vector3(0.5F, 0.5F, 0.5F);
        }
    
        /// <summary>
        /// Increases the size of the target GameObject by providing its name
        /// </summary>
        public void UpSizeTarget(string targetName)
        {
            GameObject foundTarget = FindTarget(targetName);
            foundTarget.transform.localScale += new Vector3(0.5F, 0.5F, 0.5F);
        }
    
  7. どの GameObjects が現在の意図のターゲットであるかを決定するための FindTarget() メソッドを追加します。 このメソッドは、エンティティで明示的なターゲットが定義されていない場合、"視線の先にある" GameObject を既定でターゲットとします。

        /// <summary>
        /// Determines which object reference is the target GameObject by providing its name
        /// </summary>
        private GameObject FindTarget(string name)
        {
            GameObject targetAsGO = null;
    
            switch (name)
            {
                case "sphere":
                    targetAsGO = sphere;
                    break;
    
                case "cylinder":
                    targetAsGO = cylinder;
                    break;
    
                case "cube":
                    targetAsGO = cube;
                    break;
    
                case "this": // as an example of target words that the user may use when looking at an object
                case "it":  // as this is the default, these are not actually needed in this example
                case "that":
                default: // if the target name is none of those above, check if the user is looking at something
                    if (gazedTarget != null) 
                    {
                        targetAsGO = gazedTarget;
                    }
                    break;
            }
            return targetAsGO;
        }
    

    重要

    Start() メソッドと Update() メソッドは、このクラスでは使用しないので削除します。

  8. Unity に戻る前に、必ず Visual Studio で変更を保存してください。

第 8 章 – Gaze クラスを作成する

このアプリを完成させるために必要な最後のクラスは、Gaze クラスです。 このクラスは、ユーザーの視覚フォーカスが現在捉えている GameObject への参照を更新します。

このクラスを作成するには、次の手順を実行します。

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

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

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

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

        using UnityEngine;
    
        public class Gaze : MonoBehaviour
        {        
            internal GameObject gazedObject;
            public float gazeMaxDistance = 300;
    
            void Update()
            {
                // Uses a raycast from the Main Camera to determine which object is gazed upon.
                Vector3 fwd = gameObject.transform.TransformDirection(Vector3.forward);
                Ray ray = new Ray(Camera.main.transform.position, fwd);
                RaycastHit hit;
                Debug.DrawRay(Camera.main.transform.position, fwd);
    
                if (Physics.Raycast(ray, out hit, gazeMaxDistance) && hit.collider != null)
                {
                    if (gazedObject == null)
                    {
                        gazedObject = hit.transform.gameObject;
    
                        // Set the gazedTarget in the Behaviours class
                        Behaviours.instance.gazedTarget = gazedObject;
                    }
                }
                else
                {
                    ResetGaze();
                }         
            }
    
            // Turn the gaze off, reset the gazeObject in the Behaviours class.
            public void ResetGaze()
            {
                if (gazedObject != null)
                {
                    Behaviours.instance.gazedTarget = null;
                    gazedObject = null;
                }
            }
        }
    
  5. Unity に戻る前に、必ず Visual Studio で変更を保存してください。

第 9 章 – シーンのセットアップの完了

  1. シーンのセットアップを完了するには、[階層] パネルで、作成した各スクリプトを Scripts フォルダーから [メイン カメラ] オブジェクトにドラッグします。

  2. [メイン カメラ] を選択して [インスペクター] パネルを表示すると、アタッチした各スクリプトを確認できます。各スクリプトには、まだ設定されていないパラメーターがあります。

    カメラ参照ターゲットの設定。

  3. これらのパラメーターを正しく設定するには、以下の手順に従います。

    1. MicrophoneManager については、次のように操作します。

      • [階層] パネルから、[ディクテーション テキスト] オブジェクトを [ディクテーション テキスト] のパラメーター値ボックスにドラッグします。
    2. Behaviours については、[階層] パネルから次のように操作します。

      • [球] オブジェクトを [球] の参照ターゲット ボックスにドラッグします。
      • [円柱][円柱] の参照ターゲット ボックスにドラッグします。
      • [立方体][立方体] の参照ターゲット ボックスにドラッグします。
    3. Gaze については、次のように操作します。

      • [視線入力の最大距離]300 に設定します (まだ設定されていない場合)。
  4. 結果は次の図のようになります。

    カメラ参照ターゲットを表示し、設定します。

第 10 章 – Unity エディターでのテスト

シーンのセットアップが正しく実装されているかテストします。

次のことを確認します。

  • すべてのスクリプトが [メイン カメラ] オブジェクトにアタッチされている。
  • [インスペクター] パネル で [メイン カメラ] のすべてのフィールドが適切に割り当てられている。
  1. Unity エディターで [再生] ボタンを押します。 アプリは、アタッチ状態のイマーシブ ヘッドセット内で実行されている必要があります。

  2. 次のようないくつかの発話を試してみてください。

    make the cylinder red
    
    change the cube to yellow
    
    I want the sphere blue
    
    make this to green
    
    change it to white
    

    Note

    既定のオーディオ デバイスの変更について Unity コンソールにエラーが表示される場合は、シーンが想定どおりに機能しない可能性があります。 これは、ヘッドセットにマイクが内蔵されている場合の、Mixed Reality ポータルにおける内蔵マイクの取り扱いが原因です。 このエラーが表示された場合は、シーンを停止してからもう一度開始するだけで、期待どおりに動作するはずです。

第 11 章 – UWP ソリューションをビルドしてサイドロードする

アプリケーションが Unity エディターで動作している状態を確認したら、ビルドしてデプロイする準備が整います。

ビルドするには、以下の手順を実行します。

  1. [ファイル] > [保存] の順にクリックして現在のシーンを保存します。

  2. [ファイル] > [ビルド設定] に移動します。

  3. [Unity C# プロジェクト] チェック ボックスをオンにします (UWP プロジェクトが作成された後にコードを表示およびデバッグするのに便利です)。

  4. [開いているシーンの追加] をクリックし、[ビルド] を クリックします。

    [ビルド設定] ウィンドウ

  5. ソリューションをビルドするフォルダーを選択するよう求めるプロンプトが表示されます。

  6. BUILDS フォルダーを作成し、そのフォルダー内にお好みの適切な名前で別のフォルダーを作成します。

  7. 新しいフォルダーをクリックし、[フォルダーの選択] をクリックすると、その場所でビルドが開始されます。

    ビルド フォルダーの作成ビルド フォルダーの選択

  8. Unity でビルドが完了すると (これには時間がかかる場合があります)、[エクスプローラー] ウィンドウでビルドの場所が開きます。

ローカル コンピューターにデプロイするには、以下の手順を実行します。

  1. Visual Studio で、前の章で作成したソリューション ファイルを開きます。

  2. [ソリューション プラットフォーム] で、[x86][ローカル コンピューター] を選択します。

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

    Microsoft HoloLens の場合は、これを [リモート コンピューター] に設定した方が便利かもしれません。そうすると、お使いのコンピューターに縛られずに済みます。 ただし、次のことも行う必要があります。

    • HoloLens の IP アドレス を把握します。これは 、[設定 > ] [ネットワーク] & [インターネット > ] Wi-Fi > [詳細オプション] にあります。IPv4 は使用する必要があるアドレスです。
    • 開発者モードがオンになっていることを確認します「Settings > Update & Security > For developers」を参照してください

    アプリをデプロイする

  4. [ビルド] メニュー[ソリューションの配置] をクリックして、アプリケーションをお使いのコンピューターにサイドロードします。

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

  6. 起動すると、"マイク" へのアクセスを認可するように求めるメッセージがアプリに表示されます。 "モーション コントローラー"、"音声入力"、または "キーボード" を使用して [はい] ボタンを押します。

第 12 章 – LUIS サービスの改善

重要

この章の内容は非常に重要であり、LUIS サービスの精度向上に役立つため、何度か繰り返すことが必要な場合があります。必ず完了してください。

LUIS によって提供される理解のレベルを向上させるためには、新しい発話をキャプチャし、それらを使用して LUIS アプリを再トレーニングする必要があります。

たとえば、 "増やす" や "アップサイズ" を理解するように LUIS をトレーニングした場合、"大きくする" のような言葉もアプリに理解させたいと考えるでしょう。

アプリケーションを数回使用すれば、話したすべての言葉が LUIS によって収集され、LUIS ポータルで使用できるようになります。

  1. このリンクからポータル アプリケーションに移動し、ログインします。

  2. Microsoft 資格情報でログインしたら、アプリの名前をクリックします。

  3. ページの左側にある [エンドポイント発話の確認] ボタンをクリックします。

    発話を確認する

  4. Mixed Reality アプリケーションによって LUIS に送信された発話の一覧が表示されます。

    発話の一覧

いくつかの "エンティティ" が強調表示されています。

強調表示された各単語にマウス ポインターを合わせると、各発話を確認し、正しく認識されたエンティティ、間違っているエンティティ、欠落しているエンティティを特定できます。

上の例では、"スペア" という単語がターゲットとして強調表示されているため、間違いを修正する必要があります。そのためには、マウスでこの単語をポイントして [ラベルの削除] をクリックします。

発話の確認ラベル イメージの削除

  1. 完全に間違っている発話が見つかった場合は、画面の右側にある [削除] ボタンを使用して削除できます。

    間違った発話を削除する

  2. または、発話が LUIS によって正しく解釈されたと思われる場合は、[調整された意図に追加] ボタンを使用してこの理解を有効にすることができます。

    配置された意図にを追加する

  3. 表示されている発話をすべて並べ替えたら、ページを再度読み込み、使用可能な発話がほかにないか確認してください。

  4. アプリケーションの理解を向上させるために、このプロセスは可能な限り何度も繰り返す必要があります。

お楽しみください!

完成した LUIS 統合アプリケーション

おめでとうございます。Azure Language Understanding Intelligence Service を活用して、ユーザーの言葉を理解し、その情報に対して行動する Mixed Reality アプリを構築しました。

ラボの結果

ボーナス演習

演習 1

このアプリケーションの使用中、床オブジェクトを視線で捉えてその色を変更するように指示すると、変更が行われます。 アプリケーションが床の色を変更するのをやめさせるにはどうすればよいですか?

演習 2

LUIS とアプリの機能を拡張して、シーン内のオブジェクトに対する機能を追加してみてください。たとえば、ユーザーの発声内容に応じて、視線入力のヒット ポイントに新しいオブジェクトを作成し、それらのオブジェクトを現在のシーン オブジェクトと共に既存のコマンドで操作できるようにする機能などです。