次の方法で共有


HoloLens (第 1 世代) と Azure 304: 顔認識


注:

Mixed Reality Academy のチュートリアルは、HoloLens (第 1 世代) と Mixed Realityイマーシブ ヘッドセットを念頭に置いて設計されました。 そのため、これらのデバイスの開発に関するガイダンスを引き続き探している開発者には、これらのチュートリアルを配置しておくことが重要だと考えます。 これらのチュートリアルは、HoloLens 2に使用されている最新のツールセットや相互作用では更新されません。 これらは、サポートされているデバイスでの作業を継続するために維持されます。 今後、HoloLens 2向けに開発する方法を示す新しい一連のチュートリアルが掲載されます。 この通知は、投稿時にこれらのチュートリアルへのリンクで更新されます。


このコースを修了した結果

このコースでは、Microsoft Face API を使用して、Azure Cognitive Services を使用して、複合現実アプリケーションに顔認識機能を追加する方法について説明します。

Azure Face API は、開発者に最も高度な顔アルゴリズムをすべてクラウドで提供する Microsoft サービスです。 Face API には、属性を持つ顔検出と顔認識の 2 つの主要な機能があります。 これにより、開発者は顔のグループのセットを設定し、後でサービスにクエリ イメージを送信して、顔が属するユーザーを決定できます。 詳細については、「顔認識のAzure」ページを参照してください。

このコースを完了すると、Mixed Reality HoloLens アプリケーションが用意されています。これにより、次の操作を行うことができます。

  1. オンボード HoloLens カメラを使用して画像のキャプチャを開始するには、 タップ ジェスチャ を使用します。
  2. キャプチャしたイメージをAzure Face API サービスに送信します。
  3. Face API アルゴリズムの結果を受け取ります。
  4. 一致したユーザーの名前を表示するには、単純なユーザー インターフェイスを使用します。

これにより、Face API Service から Unity ベースの Mixed Reality アプリケーションに結果を取得する方法について説明します。

アプリケーションでは、結果を設計と統合する方法はユーザー次第です。 このコースは、Azure サービスを Unity プロジェクトと統合する方法を学習するように設計されています。 このコースから得た知識を使用して、Mixed Reality アプリケーションを強化するのがあなたの仕事です。

デバイスのサポート

コース (/previous-versions/mixed-reality/hololens-1/hololens1-hardware)HoloLens イマーシブ ヘッドセット
MR と Azure 304: 顔認識 ✔️ ✔️

注:

このコースでは主に HoloLens に焦点を当てていますが、このコースで学習した内容をイマーシブ (VR) ヘッドセットWindows Mixed Reality適用することもできます。 イマーシブ (VR) ヘッドセットにはアクセス可能なカメラがないため、PC に接続されている外部カメラが必要です。 コースに従うと、イマーシブ (VR) ヘッドセットをサポートするために採用する必要がある変更に関するメモが表示されます。

前提条件

注:

このチュートリアルは、Unityと C# に関する基本的な経験を持つ開発者向けに設計されています。 また、このドキュメント内の前提条件と記述された手順は、執筆時点 (2018 年 5 月) にテストおよび検証された内容を表しています。 ツールのインストールに関する記事に記載されているように、最新のソフトウェアを自由に使用できますが、このコースの情報は、以下に示すソフトウェアよりも新しいソフトウェアで見つけたものと完全に一致するとは想定しないでください。

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

始める前に

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

調整に関するヘルプについては、 HoloLens の調整に関する記事のリンクを参照してください

センサーのチューニングに関するヘルプについては、 HoloLens センサーチューニングに関する記事のリンクを参照してください

第 1 章 - Azure ポータル

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

  1. まず、Azure ポータルにログインします。

    注:

    Azure アカウントがまだない場合は、アカウントを作成する必要があります。 教室やラボの状況でこのチュートリアルに従っている場合は、講師またはプロクターに新しいアカウントの設定に関するヘルプを依頼してください。

  2. ログインしたら、左上隅の [ 新規 ] をクリックし、 Face API を検索して Enter キーを押 します

    face api を検索する

    注:

    新しいポータルでは、New という単語がリソースの作成に置き換えられた可能性があります。

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

    face api 情報

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

    1. このサービス インスタンスの目的の名前を挿入します。

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

    3. 適切な価格レベルを選択します。 Face API サービスを初めて作成する場合は、無料レベル (F0 という名前) を使用できます。

    4. リソース グループを選択するか、新しい リソース グループ を作成します。 リソース グループを使用すると、Azure資産のコレクションに対して、アクセスの監視、制御、課金のプロビジョニング、管理を行うことができます。 すべてのAzure サービスを 1 つのプロジェクト (たとえば、これらのラボなど) に共通のリソース グループの下に保持することをお勧めします。

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

    5. 後で使用する UWP アプリ Person Maker では、場所に "米国西部" を使用する必要があります。

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

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

      face api サービスを作成する

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

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

    サービス作成通知

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

    リソース通知に移動する

  8. 準備ができたら、通知の [ リソースに移動 ] ボタンをクリックして、新しいサービス インスタンスを探索します。

    顔 api キーにアクセスする

  9. このチュートリアルでは、アプリケーションでサービスを呼び出す必要があります。これは、サービスのサブスクリプション 'key' を使用して行われます。 Face API サービスの [クイック スタート] ページで、最初のポイントは数値 1 で、キーを取得します。

  10. [サービス] ページで、青色の [キー] ハイパーリンク ([クイック スタート] ページの場合) またはサービス ナビゲーション メニューの [キー] リンク (左側の [キー] アイコンで示されます) を選択して、キーを表示します。

    注:

    後で必要な場合は、いずれかのキーをメモして保護します。

第 2 章 - "Person Maker" UWP アプリケーションの使用

Person Maker という名前の事前構築済みの UWP アプリケーションを必ずダウンロードしてください。 このアプリは、このコースの最終製品ではなく、後のプロジェクトが依存するAzureエントリを作成するのに役立つツールにすぎません。

Person Maker を使用すると、ユーザーとユーザーのグループに関連付けられているAzureエントリを作成できます。 アプリケーションは、必要なすべての情報を、後で FaceAPI で使用して追加したユーザーの顔を認識できる形式で配置します。

[重要] Person Maker では、基本的な調整を使用して、 無料サブスクリプションレベルの 1 分あたりのサービス呼び出し数を超えないようにします。 上部の緑色のテキストは赤に変更され、スロットルが発生すると 'ACTIVE' として更新されます。この場合は、アプリケーションを待つだけです (次に顔サービスにアクセスし、もう一度使用できる場合は 'IN-ACTIVE' として更新されるまで待機します)。

このアプリケーションでは、 Microsoft.ProjectOxford.Face ライブラリを使用します。これにより、Face API を最大限に活用できます。 このライブラリは、NuGet パッケージとして無料で利用できます。 この API と同様の詳細については、API リファレンス記事を参照してください

注:

これらは必要な手順に過ぎず、これらの操作を行う方法の手順はドキュメントの下にあります。 Person Maker アプリを使用すると、次のことができます。

  • ユーザー グループを作成します。これは、関連付ける複数のユーザーで構成されるグループです。 Azure アカウントを使用すると、複数のユーザー グループをホストできます。

  • Person グループのメンバーである Person を作成します。 各ユーザーには、多数の Face イメージが関連付けられています。

  • 顔画像Person に割り当てて、Azure Face API Service が対応する人物を認識できるようにします。

  • Azure Face API サービストレーニングします。

このアプリをトレーニングしてユーザーを認識するには、Person Group に追加する各ユーザーの 10 枚 (10 枚) のクローズアップ写真が必要です。 Windows 10 Camアプリは、これらを取るのに役立ちます。 各写真が明確であることを確認する必要があります (被写体からぼやけたり、目立たなくなったり、遠すぎたりしないようにする)、jpg または png ファイル形式の写真を持ち、画像ファイルのサイズは 4 MB 以下で、 1 KB 以下にする必要があります。

注:

このチュートリアルに従っている場合は、HoloLens をオンにしたときのように、トレーニングに独自の顔を使用しないでください。自分を見ることはできません。 同僚や仲間の学生の顔を使用します。

実行中 のユーザー メーカー:

  1. PersonMaker フォルダーを開き、PersonMaker ソリューションをダブルクリックして Visual Studio で開きます。

  2. PersonMaker ソリューションが開いたら、次の点を確認します。

    1. [ソリューション構成][デバッグ] に設定されています。

    2. ソリューション プラットフォームx86 に設定されている

    3. ターゲット プラットフォームローカル コンピューターです

    4. また、NuGet パッケージの復元が必要な場合もあります (ソリューションを右クリックし、[NuGet パッケージの復元] を選択します)。

  3. [ ローカル コンピューター ] をクリックすると、アプリケーションが起動します。 小さい画面では、すべてのコンテンツが表示されない場合があることに注意してください。ただし、さらに下にスクロールして表示することもできます。

    person maker ユーザー インターフェイス

  4. Azure内の Face API サービスから、必要なAzure認証キーを挿入します。

  5. 挿入:

    1. ユーザー グループに割り当てる ID。 ID は小文字で、スペースは必要ありません。 この ID は、Unity プロジェクトの後半で必要であるため、メモしておきます。
    2. ユーザー グループに割り当てる名前 (スペースを含めることができます)。
  6. [ ユーザー グループの作成 ] ボタンを押します。 ボタンの下に確認メッセージが表示されます。

注:

"アクセス拒否" エラーが発生した場合は、Azure サービスに設定した場所をチェックします。 上記のように、このアプリは '米国西部' 用に設計されています。

重要

[ 既知のグループのフェッチ ] ボタンをクリックすることもできます。これは、ユーザー グループを作成し、新しいグループを作成するのではなく、そのグループを使用する場合に適しています。 [既知の グループを持つユーザー グループの作成 ] をクリックすると、グループもフェッチされることに注意してください。

  1. 作成するユーザー名前を挿入します。

    1. [ ユーザーの作成 ] ボタンをクリックします。

    2. ボタンの下に確認メッセージが表示されます。

    3. 以前に作成したユーザーを削除する場合は、テキスト ボックスに名前を書き込み、Delete Person キーを押します。

  2. グループに追加するユーザーの 10 枚 (10 枚) の写真の場所がわかっていることを確認します。

  3. [フォルダーの作成] と [フォルダーを開く] を押して、ユーザーに関連付けられているフォルダーの Windows エクスプローラーを開きます。 フォルダーに 10 個の (10 個の) イメージを追加します。 JPG またはPNG ファイル形式である必要があります。

  4. [Azureに送信] をクリックします。 カウンターには、送信の状態が表示され、その後に完了したメッセージが表示されます。

  5. カウンターが終了し、確認メッセージが表示されたら、[ トレーニング ] をクリックしてサービスをトレーニングします。

プロセスが完了したら、Unityに移動する準備が整います。

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

Mixed Reality を使用して開発するための一般的なセットアップを次に示します。そのため、他のプロジェクトに適したテンプレートです。

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

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

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

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

  3. Unity開いている場合は、既定の [スクリプト エディター]Visual Studio に設定されていることを確認する必要があります。 [>基本設定の編集] に移動し、新しいウィンドウから [外部ツール] に移動します。 [外部スクリプト エディター]Visual Studio 2017 に変更します。 [基本設定] ウィンドウを閉じます。

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

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

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

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

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

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

    2. ビルドの種類D3D に設定されている

    3. SDK[最新インストール済み] に設定されている

    4. Visual Studio のバージョン[最新インストール済み] に設定されている

    5. ビルドと実行ローカル コンピューターに設定されている

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

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

        [開いているシーンの追加] ボタン

      2. [ 新しいフォルダー ] ボタンを選択して新しいフォルダーを作成し、 Scenes という名前を付けます

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

      3. 新しく作成した Scenes フォルダーを開き、[ ファイル名: テキスト] フィールドに 「FaceRecScene」と入力し、[ 保存] を押します

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

    7. [ ビルド設定] の残りの設定は、現時点では既定値のままにする必要があります。

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

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

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

    1. [その他の設定] タブで、次 の手順を実行 します。

      1. スクリプト ランタイムバージョン試験的 (.NET 4.6 同等) にする必要があります。 これを変更すると、エディターを再起動する必要が発生します。

      2. スクリプト バックエンド.NET にする必要があります

      3. API 互換性レベル.NET 4.6 にする必要があります

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

    2. [発行設定] タブの [機能] で、次チェックします。

      • InternetClient

      • ウェブカメラ

        発行設定の更新。

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

      X R 設定を更新します。

  8. [ビルド設定] に戻り、C# プロジェクトUnity灰色表示されなくなりました。この横にあるチェック ボックスをオンにします。

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

  10. シーンとプロジェクトを保存します (FILE > SAVE SCENE/FILE > プロジェクトを保存します)。

第 4 章 - メイン カメラのセットアップ

重要

このコースのUnityセットアップ コンポーネントをスキップしてコードに直接進む場合は、この .unitypackage を自由にダウンロードして、カスタム パッケージとしてプロジェクトにインポートしてください。 このパッケージには、第 5 章で説明されている Newtonsoft DLL のインポートも含まれています。 これをインポートすると、 第 6 章から続行できます。

  1. [階層] パネルで、メイン カメラを選択します。

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

    1. Camera オブジェクトには Main Camera という名前を付ける必要があります (スペルに注意してください)。

    2. メイン カメラ タグMainCamera に設定する必要があります (スペルに注意してください)。

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

    4. [クリア フラグ][純色] に設定する

    5. カメラ コンポーネントの 背景色黒、アルファ 0 に設定します (16 進数コード: #000000000)

      カメラ コンポーネントを設定する

第 5 章 – Newtonsoft.Json ライブラリをインポートする

重要

最後のチャプターで '.unitypackage' をインポートした場合は、このチャプターをスキップできます。

受信し、Bot Serviceに送信されたオブジェクトを逆シリアル化し、シリアル化するには、Newtonsoft.Json ライブラリをダウンロードする必要があります。 互換性のあるバージョンは、このUnity パッケージ ファイル内の正しいUnity フォルダー構造で既に編成されています。

ライブラリをインポートするには:

  1. Unity パッケージをダウンロードします。

  2. [ アセット]、[ パッケージのインポート]、[ カスタム パッケージ] をクリックします。

    Newtonsoft.Json のインポート

  3. ダウンロードしたUnity パッケージを探し、[開く] をクリックします。

  4. パッケージのすべてのコンポーネントがチェックされていることを確認し、[ インポート] をクリックします。

    Newtonsoft.Json アセットをインポートする

第 6 章 - FaceAnalysis クラスを作成する

FaceAnalysis クラスの目的は、Azure Face Recognition Service と通信するために必要なメソッドをホストすることです。

  • サービスにキャプチャ イメージを送信した後、その画像を分析し、その中の顔を特定し、既知の人物に属しているかどうかを判断します。
  • 既知の人物が見つかった場合、このクラスはその名前をシーン内の UI テキストとして表示します。

FaceAnalysis クラスを作成するには:

  1. プロジェクト パネルにある Assets フォルダー を右クリックし、[ 作成>Folder] をクリックします。 [スクリプト] フォルダーを呼び出 します

    FaceAnalysis クラスを作成します。

  2. 作成したフォルダーをダブルクリックして開きます。

  3. フォルダー内を右クリックし、[ 作成>C# スクリプト] をクリックします。 スクリプト FaceAnalysis を呼び出します。

  4. 新しい FaceAnalysis スクリプトをダブルクリックして、Visual Studio 2017 で開きます。

  5. FaceAnalysis クラスの上に次の名前空間を入力します。

        using Newtonsoft.Json;
        using System.Collections;
        using System.Collections.Generic;
        using System.IO;
        using System.Text;
        using UnityEngine;
        using UnityEngine.Networking;
    
  6. これで、脱テリアに使用されるすべてのオブジェクトを追加する必要があります。 これらのオブジェクトは、FaceAnalysis スクリプトの外部 (下の中かっこの下) の外側に追加する必要があります。

        /// <summary>
        /// The Person Group object
        /// </summary>
        public class Group_RootObject
        {
            public string personGroupId { get; set; }
            public string name { get; set; }
            public object userData { get; set; }
        }
    
        /// <summary>
        /// The Person Face object
        /// </summary>
        public class Face_RootObject
        {
            public string faceId { get; set; }
        }
    
        /// <summary>
        /// Collection of faces that needs to be identified
        /// </summary>
        public class FacesToIdentify_RootObject
        {
            public string personGroupId { get; set; }
            public List<string> faceIds { get; set; }
            public int maxNumOfCandidatesReturned { get; set; }
            public double confidenceThreshold { get; set; }
        }
    
        /// <summary>
        /// Collection of Candidates for the face
        /// </summary>
        public class Candidate_RootObject
        {
            public string faceId { get; set; }
            public List<Candidate> candidates { get; set; }
        }
    
        public class Candidate
        {
            public string personId { get; set; }
            public double confidence { get; set; }
        }
    
        /// <summary>
        /// Name and Id of the identified Person
        /// </summary>
        public class IdentifiedPerson_RootObject
        {
            public string personId { get; set; }
            public string name { get; set; }
        }
    
  7. Start() メソッドと Update() メソッドは使用されないため、今すぐ削除してください。

  8. FaceAnalysis クラス内に、次の変数を追加します。

        /// <summary>
        /// Allows this class to behave like a singleton
        /// </summary>
        public static FaceAnalysis Instance;
    
        /// <summary>
        /// The analysis result text
        /// </summary>
        private TextMesh labelText;
    
        /// <summary>
        /// Bytes of the image captured with camera
        /// </summary>
        internal byte[] imageBytes;
    
        /// <summary>
        /// Path of the image captured with camera
        /// </summary>
        internal string imagePath;
    
        /// <summary>
        /// Base endpoint of Face Recognition Service
        /// </summary>
        const string baseEndpoint = "https://westus.api.cognitive.microsoft.com/face/v1.0/";
    
        /// <summary>
        /// Auth key of Face Recognition Service
        /// </summary>
        private const string key = "- Insert your key here -";
    
        /// <summary>
        /// Id (name) of the created person group 
        /// </summary>
        private const string personGroupId = "- Insert your group Id here -";
    

    注:

    キーpersonGroupId を、前に作成したグループのサービス キーと ID に置き換えます。

  9. クラスを初期化し、ImageCapture クラスを Main Camera に追加し、Label 作成メソッドを呼び出す Awake() メソッドを追加します。

        /// <summary>
        /// Initialises this class
        /// </summary>
        private void Awake()
        {
            // Allows this instance to behave like a singleton
            Instance = this;
    
            // Add the ImageCapture Class to this Game Object
            gameObject.AddComponent<ImageCapture>();
    
            // Create the text label in the scene
            CreateLabel();
        }
    
  10. 分析結果を表示する Label オブジェクトを作成する CreateLabel() メソッドを追加します。

        /// <summary>
        /// Spawns cursor for the Main Camera
        /// </summary>
        private void CreateLabel()
        {
            // Create a sphere as new cursor
            GameObject newLabel = new GameObject();
    
            // Attach the label to the Main Camera
            newLabel.transform.parent = gameObject.transform;
    
            // Resize and position the new cursor
            newLabel.transform.localScale = new Vector3(0.4f, 0.4f, 0.4f);
            newLabel.transform.position = new Vector3(0f, 3f, 60f);
    
            // Creating the text of the Label
            labelText = newLabel.AddComponent<TextMesh>();
            labelText.anchor = TextAnchor.MiddleCenter;
            labelText.alignment = TextAlignment.Center;
            labelText.tabSize = 4;
            labelText.fontSize = 50;
            labelText.text = ".";       
        }
    
  11. DetectFacesFromImage() メソッドと GetImageAsByteArray() メソッドを追加します。 前者は、送信された画像内の可能な顔を検出するように Face Recognition Service に要求しますが、後者はキャプチャされた画像をバイト配列に変換する必要があります。

        /// <summary>
        /// Detect faces from a submitted image
        /// </summary>
        internal IEnumerator DetectFacesFromImage()
        {
            WWWForm webForm = new WWWForm();
            string detectFacesEndpoint = $"{baseEndpoint}detect";
    
            // Change the image into a bytes array
            imageBytes = GetImageAsByteArray(imagePath);
    
            using (UnityWebRequest www = 
                UnityWebRequest.Post(detectFacesEndpoint, webForm))
            {
                www.SetRequestHeader("Ocp-Apim-Subscription-Key", key);
                www.SetRequestHeader("Content-Type", "application/octet-stream");
                www.uploadHandler.contentType = "application/octet-stream";
                www.uploadHandler = new UploadHandlerRaw(imageBytes);
                www.downloadHandler = new DownloadHandlerBuffer();
    
                yield return www.SendWebRequest();
                string jsonResponse = www.downloadHandler.text;
                Face_RootObject[] face_RootObject = 
                    JsonConvert.DeserializeObject<Face_RootObject[]>(jsonResponse);
    
                List<string> facesIdList = new List<string>();
                // Create a list with the face Ids of faces detected in image
                foreach (Face_RootObject faceRO in face_RootObject)
                {
                    facesIdList.Add(faceRO.faceId);
                    Debug.Log($"Detected face - Id: {faceRO.faceId}");
                }
    
                StartCoroutine(IdentifyFaces(facesIdList));
            }
        }
    
        /// <summary>
        /// Returns the contents of the specified file as a byte array.
        /// </summary>
        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);
        }
    
  12. IdentifyFaces() メソッドを追加します。このメソッドは、送信された画像で以前に検出された既知の顔を識別するように Face Recognition Service に要求します。 要求は、識別されたユーザーの ID を返しますが、名前は返しません。

        /// <summary>
        /// Identify the faces found in the image within the person group
        /// </summary>
        internal IEnumerator IdentifyFaces(List<string> listOfFacesIdToIdentify)
        {
            // Create the object hosting the faces to identify
            FacesToIdentify_RootObject facesToIdentify = new FacesToIdentify_RootObject();
            facesToIdentify.faceIds = new List<string>();
            facesToIdentify.personGroupId = personGroupId;
            foreach (string facesId in listOfFacesIdToIdentify)
            {
                facesToIdentify.faceIds.Add(facesId);
            }
            facesToIdentify.maxNumOfCandidatesReturned = 1;
            facesToIdentify.confidenceThreshold = 0.5;
    
            // Serialize to Json format
            string facesToIdentifyJson = JsonConvert.SerializeObject(facesToIdentify);
            // Change the object into a bytes array
            byte[] facesData = Encoding.UTF8.GetBytes(facesToIdentifyJson);
    
            WWWForm webForm = new WWWForm();
            string detectFacesEndpoint = $"{baseEndpoint}identify";
    
            using (UnityWebRequest www = UnityWebRequest.Post(detectFacesEndpoint, webForm))
            {
                www.SetRequestHeader("Ocp-Apim-Subscription-Key", key);
                www.SetRequestHeader("Content-Type", "application/json");
                www.uploadHandler.contentType = "application/json";
                www.uploadHandler = new UploadHandlerRaw(facesData);
                www.downloadHandler = new DownloadHandlerBuffer();
    
                yield return www.SendWebRequest();
                string jsonResponse = www.downloadHandler.text;
                Debug.Log($"Get Person - jsonResponse: {jsonResponse}");
                Candidate_RootObject [] candidate_RootObject = JsonConvert.DeserializeObject<Candidate_RootObject[]>(jsonResponse);
    
                // For each face to identify that ahs been submitted, display its candidate
                foreach (Candidate_RootObject candidateRO in candidate_RootObject)
                {
                    StartCoroutine(GetPerson(candidateRO.candidates[0].personId));
    
                    // Delay the next "GetPerson" call, so all faces candidate are displayed properly
                    yield return new WaitForSeconds(3);
                }           
            }
        }
    
  13. GetPerson() メソッドを追加します。 次に、人物 ID を指定すると、このメソッドは、識別されたユーザーの名前を返すように Face Recognition Service に要求します。

        /// <summary>
        /// Provided a personId, retrieve the person name associated with it
        /// </summary>
        internal IEnumerator GetPerson(string personId)
        {
            string getGroupEndpoint = $"{baseEndpoint}persongroups/{personGroupId}/persons/{personId}?";
            WWWForm webForm = new WWWForm();
    
            using (UnityWebRequest www = UnityWebRequest.Get(getGroupEndpoint))
            {
                www.SetRequestHeader("Ocp-Apim-Subscription-Key", key);
                www.downloadHandler = new DownloadHandlerBuffer();
                yield return www.SendWebRequest();
                string jsonResponse = www.downloadHandler.text;
    
                Debug.Log($"Get Person - jsonResponse: {jsonResponse}");
                IdentifiedPerson_RootObject identifiedPerson_RootObject = JsonConvert.DeserializeObject<IdentifiedPerson_RootObject>(jsonResponse);
    
                // Display the name of the person in the UI
                labelText.text = identifiedPerson_RootObject.name;
            }
        }
    
  14. Unity エディターに戻る前に、変更を保存することを忘れないでください。

  15. Unity エディターで、[プロジェクト] パネルの [スクリプト] フォルダーから [階層] パネルの Main Camera オブジェクトに FaceAnalysis スクリプトをドラッグします。 新しいスクリプト コンポーネントがメイン カメラに追加されます。

FaceAnalysis をメイン カメラに配置する

第 7 章 - ImageCapture クラスを作成する

ImageCapture クラスの目的は、キャプチャした画像を分析し、その中の顔を識別し、既知の人物に属しているかどうかを判断するために、Azure顔認識サービスと通信するために必要なメソッドをホストすることです。 既知の人物が見つかった場合、このクラスはその名前をシーン内の UI テキストとして表示します。

ImageCapture クラスを作成するには:

  1. 作成した Scripts フォルダー内を右クリックし、[ 作成]、[ C# スクリプト] の順にクリックします。 スクリプト ImageCapture を呼び出します。

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

  3. ImageCapture クラスの上に次の名前空間を入力します。

        using System.IO;
        using System.Linq;
        using UnityEngine;
        using UnityEngine.XR.WSA.Input;
        using UnityEngine.XR.WSA.WebCam;
    
  4. ImageCapture クラス内に、次の変数を追加します。

        /// <summary>
        /// Allows this class to behave like a singleton
        /// </summary>
        public static ImageCapture instance;
    
        /// <summary>
        /// Keeps track of tapCounts to name the captured images 
        /// </summary>
        private int tapsCount;
    
        /// <summary>
        /// PhotoCapture object used to capture images on HoloLens 
        /// </summary>
        private PhotoCapture photoCaptureObject = null;
    
        /// <summary>
        /// HoloLens class to capture user gestures
        /// </summary>
        private GestureRecognizer recognizer;
    
  5. クラスを初期化し、HoloLens がユーザーのジェスチャをキャプチャできるようにするために必要な Awake() メソッドと Start() メソッドを追加します。

        /// <summary>
        /// Initialises this class
        /// </summary>
        private void Awake()
        {
            instance = this;
        }
    
        /// <summary>
        /// Called right after Awake
        /// </summary>
        void Start()
        {
            // Initialises user gestures capture 
            recognizer = new GestureRecognizer();
            recognizer.SetRecognizableGestures(GestureSettings.Tap);
            recognizer.Tapped += TapHandler;
            recognizer.StartCapturingGestures();
        }
    
  6. ユーザーが Tap ジェスチャを実行したときに呼び出される TapHandler() を追加します。

        /// <summary>
        /// Respond to Tap Input.
        /// </summary>
        private void TapHandler(TappedEventArgs obj)
        {
            tapsCount++;
            ExecuteImageCaptureAndAnalysis();
        }
    
  7. ExecuteImageCaptureAndAnalysis() メソッドを追加します。これにより、イメージ キャプチャのプロセスが開始されます。

        /// <summary>
        /// Begin process of Image Capturing and send To Azure Computer Vision service.
        /// </summary>
        private void ExecuteImageCaptureAndAnalysis()
        {
            Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending
                ((res) => res.width * res.height).First();
            Texture2D targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
    
            PhotoCapture.CreateAsync(false, delegate (PhotoCapture captureObject)
            {
                photoCaptureObject = captureObject;
    
                CameraParameters c = new CameraParameters();
                c.hologramOpacity = 0.0f;
                c.cameraResolutionWidth = targetTexture.width;
                c.cameraResolutionHeight = targetTexture.height;
                c.pixelFormat = CapturePixelFormat.BGRA32;
    
                captureObject.StartPhotoModeAsync(c, delegate (PhotoCapture.PhotoCaptureResult result)
                {
                    string filename = string.Format(@"CapturedImage{0}.jpg", tapsCount);
                    string filePath = Path.Combine(Application.persistentDataPath, filename);
    
                    // Set the image path on the FaceAnalysis class
                    FaceAnalysis.Instance.imagePath = filePath;
    
                    photoCaptureObject.TakePhotoAsync
                    (filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);
                });
            });
        }
    
  8. 写真キャプチャ プロセスが完了したときに呼び出されるハンドラーを追加します。

        /// <summary>
        /// Called right after the photo capture process has concluded
        /// </summary>
        void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
        {
            photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
        }
    
        /// <summary>
        /// Register the full execution of the Photo Capture. If successful, it will begin the Image Analysis process.
        /// </summary>
        void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
        {
            photoCaptureObject.Dispose();
            photoCaptureObject = null;
    
            // Request image caputer analysis
            StartCoroutine(FaceAnalysis.Instance.DetectFacesFromImage());
        }
    
  9. Unity エディターに戻る前に、変更を保存することを忘れないでください。

第 8 章 - ソリューションの構築

アプリケーションの徹底的なテストを実行するには、HoloLens にサイドロードする必要があります。

実行する前に、次のことを確認してください。

  • 第 3 章で説明されているすべての設定が正しく設定されています。
  • スクリプト FaceAnalysis は Main Camera オブジェクトにアタッチされます。
  • 認証キーグループ ID の両方が FaceAnalysis スクリプト内で設定されています。

この時点で、ソリューションをビルドする準備ができました。 ソリューションが構築されたら、アプリケーションをデプロイする準備が整います。

ビルド プロセスを開始するには:

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

  2. [ファイル]、[ビルド設定] の順に移動し、[開いているシーンの追加] をクリックします。

  3. C# プロジェクトUnityチェック を入れておきます。

    Visual Studio ソリューションをデプロイする

  4. [ビルド] を押します。 その後、Unityはエクスプローラー ウィンドウを起動します。ここで、アプリをビルドするフォルダーを作成して選択する必要があります。 Unity プロジェクト内にそのフォルダーを今すぐ作成し、App と呼びます。 次に、App フォルダーが選択された状態で、[フォルダーの選択] を押します。

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

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

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

  7. App フォルダーを開き、新しいプロジェクト ソリューションを開きます (上記のMR_FaceRecognition.sln)。

第 9 章 - アプリケーションのデプロイ

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 リモート マシンを選択 します

    ソリューション構成を変更する

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

  6. これで、HoloLens にインストールされているアプリの一覧にアプリが表示され、起動する準備が整いました。

注:

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

第 10 章 - アプリケーションの使用

  1. HoloLens を装着して、アプリを起動します。

  2. Face API に登録したユーザーを確認します。 以下を確認してください。

    • 人の顔が遠すぎず、はっきりと見える
    • 環境照明が暗すぎない
  3. タップ ジェスチャを使用して、ユーザーの画像をキャプチャします。

  4. アプリが分析要求を送信し、応答を受け取るのを待ちます。

  5. ユーザーが正常に認識されると、そのユーザーの名前が UI テキストとして表示されます。

  6. 数秒ごとにタップ ジェスチャを使用してキャプチャ プロセスを繰り返すことができます。

完成したAzure Face API アプリケーション

これで、Azure顔認識サービスを適用して画像内の顔を検出し、既知の顔を識別する Mixed Reality アプリを構築しました。

このコースを修了した結果

ボーナス演習

演習 1

Azure Face API は、1 つの画像で最大 64 個の顔を検出するのに十分な強力です。 アプリケーションを拡張して、他の多くのユーザーの間で 2 つまたは 3 つの顔を認識できるようにします。

演習 2

Azure Face API では、あらゆる種類の属性情報を返すこともできます。 これをアプリケーションに統合します。 Emotion API と組み合わせると、さらに興味深いものになる可能性があります。