注意

Mixed Reality Academy チュートリアルでは、HoloLens として設計された (第 1 世代) と混在の現実イマーシブ ヘッドセットに注意してください。The Mixed Reality Academy tutorials were designed with HoloLens (1st gen) and Mixed Reality Immersive Headsets in mind. そのため、これらのデバイス向けの開発にガイダンスがまだ必要な開発者のための場所でこれらのチュートリアルのままにすることが重要と思われます。As such, we feel it is important to leave these tutorials in place for developers who are still looking for guidance in developing for those devices. これらのチュートリアルは いない 最新のツールセットや相互作用が使用されている HoloLens 2 で更新されます。These tutorials will not be updated with the latest toolsets or interactions being used for HoloLens 2. サポートされているデバイスで作業を続行するが保持されます。They will be maintained to continue working on the supported devices. 一連の新しい HoloLens 2 を開発する方法を示すチュートリアルは、今後投稿があります。There will be a new series of tutorials that will be posted in the future that will demonstrate how to develop for HoloLens 2. この通知が投稿されるときにこれらのチュートリアルへのリンクが更新されます。This notice will be updated with a link to those tutorials when they are posted.


MR と Azure 302b:カスタム ビジョンMR and Azure 302b: Custom vision

このコースでは複合現実のアプリケーションで Azure の Custom Vision 機能を使用して、指定されたイメージ内でカスタム ビジュアルのコンテンツを認識する方法については。In this course, you will learn how to recognize custom visual content within a provided image, using Azure Custom Vision capabilities in a mixed reality application.

このサービスを使用して、オブジェクトのイメージを使用して機械学習モデルのトレーニングにはできます。This service will allow you to train a machine learning model using object images. Microsoft HoloLens または没入型の (VR) ヘッドセットの PC に接続されているカメラのカメラ キャプチャによって提供される、類似のオブジェクトを認識するのにトレーニング済みモデルを使用するされます。You will then use the trained model to recognize similar objects, as provided by the camera capture of Microsoft HoloLens or a camera connected to your PC for immersive (VR) headsets.

コースの結果

Azure の Custom Vision には、Microsoft の Cognitive サービスにより、カスタム イメージ分類モデルを構築する開発者ですが。Azure Custom Vision is a Microsoft Cognitive Service which allows developers to build custom image classifiers. これらの分類モデルを認識して新しいイメージで、使用するまたは、その新しいイメージ内のオブジェクトを分類します。These classifiers can then be used with new images to recognize, or classify, objects within that new image. サービスは、プロセスを合理化するシンプルで使いやすい、オンライン ポータルを提供します。The Service provides a simple, easy to use, online portal to streamline the process. 詳細については、次を参照してください。、 Azure Custom Vision Service ページします。For more information, visit the Azure Custom Vision Service page.

このコースの完了したら、2 つのモードで動作できる必要が複合現実のアプリケーションが用意されます。Upon completion of this course, you will have a mixed reality application which will be able to work in two modes:

  • 分析モード: Custom Vision Service 手動でセットアップ イメージをアップロードし、タグを作成し、トレーニング、サービスによって (このケースのマウスとキーボード) のさまざまなオブジェクトを認識します。Analysis Mode: setting up the Custom Vision Service manually by uploading images, creating tags, and training the Service to recognize different objects (in this case mouse and keyboard). 後は、カメラを使用してイメージをキャプチャし、現実の世界でこれらのオブジェクトを認識する HoloLens アプリを作成します。You will then create a HoloLens app that will capture images using the camera, and try to recognize those objects in the real world.

  • トレーニング モード: は、アプリで「トレーニング モード」は有効にするコードを実装します。Training Mode: you will implement code that will enable a "Training Mode" in your app. トレーニング モードを使用すると、HoloLens のカメラを使用してイメージをキャプチャ、キャプチャしたイメージをサービスにアップロードし、カスタム ビジョン モデルをトレーニングできます。The training mode will allow you to capture images using the HoloLens' camera, upload the captured images to the Service, and train the custom vision model.

このコースでは、Custom Vision Service から Unity に基づくサンプル アプリケーションに結果を取得する方法を説明します。This course will teach you how to get the results from the Custom Vision Service into a Unity-based sample application. 最大をカスタム アプリケーションをビルドしている場合にこれらの概念を適用することがあります。It will be up to you to apply these concepts to a custom application you might be building.

デバイスのサポートDevice support

コースCourse HoloLensHoloLens イマーシブ ヘッドセットImmersive headsets
MR と Azure 302b:カスタム ビジョンMR and Azure 302b: Custom vision ✔️✔️ ✔️✔️

注意

このコースは、HoloLens で主にフォーカスします、Windows Mixed Reality 没入型 (VR) ヘッドセットには、このコースで学習する内容を適用することもできます。While this course primarily focuses on HoloLens, you can also apply what you learn in this course to Windows Mixed Reality immersive (VR) headsets. (VR) のイマーシブ ヘッドセットはアクセス可能な cameras があるないため、外部のカメラを PC に接続されている必要があります。Because immersive (VR) headsets do not have accessible cameras, you will need an external camera connected to your PC. コースを実行するとき、没入型の (VR) ヘッドセットをサポートするために使用する必要があります変更でノートが表示されます。As you follow along with the course, you will see notes on any changes you might need to employ to support immersive (VR) headsets.

前提条件Prerequisites

注意

このチュートリアルは、Unity を使用した基本的な経験がある開発者向けに設計およびC#します。This tutorial is designed for developers who have basic experience with Unity and C#. また、前提条件やこのドキュメント内の書面の手順を表すテストおよび (2018 年 7 月) の書き込み時に検証されたがどのようなことに注意してください。Please also be aware that the prerequisites and written instructions within this document represent what has been tested and verified at the time of writing (July 2018). 内に一覧表示するには自由に最新のソフトウェアを使用して、ツールをインストールするにする必要がありますが想定されていなかったことについては、このコースでとまったく同じで記載されているものよりも新しいソフトウェアで表示されますが、記事以下に。You are free to use the latest software, as listed within the install the tools article, though it should not be assumed that the information in this course will perfectly match what you will find in newer software than what is listed below.

次のハードウェアとソフトウェアこのコースをお勧めします。We recommend the following hardware and software for this course:

開始前の作業Before you start

  1. このプロジェクトのビルドの問題の発生を避けるため、強くお勧めのルートまたはルート近くフォルダーでこのチュートリアルで説明したようにプロジェクトを作成すること (長いフォルダー パスはビルド時に問題を発生できます)。To avoid encountering issues building this project, it is strongly suggested that you create the project mentioned in this tutorial in a root or near-root folder (long folder paths can cause issues at build-time).
  2. 設定して、HoloLens をテストします。Set up and test your HoloLens. 場合は、HoloLens の設定をサポートする必要があるHoloLens のセットアップ記事を参照してください。 確認します。If you need support setting up your HoloLens, make sure to visit the HoloLens setup article.
  3. (場合によって役立ちますユーザーごとにこれらのタスクを実行する) 新しい HoloLens アプリの開発を始めるときに、調整とセンサーのチューニングを実行することをお勧めします。It is a good idea to perform Calibration and Sensor Tuning when beginning developing a new HoloLens app (sometimes it can help to perform those tasks for each user).

調整に関するヘルプを参照するに従ってくださいこのHoloLens 調整記事へのリンクします。For help on Calibration, please follow this link to the HoloLens Calibration article.

センサーの調整に関する詳細についてに従ってくださいこのHoloLens センサー チューニング記事へのリンクします。For help on Sensor Tuning, please follow this link to the HoloLens Sensor Tuning article.

第 1 章 - Custom Vision Service ポータルChapter 1 - The Custom Vision Service Portal

使用する、 Custom Vision Service Azure では、アプリケーションに使用可能にするサービスのインスタンスを構成する必要があります。To use the Custom Vision Service in Azure, you will need to configure an instance of the Service to be made available to your application.

  1. 最初に、に移動し、 Custom Vision Serviceメイン ページします。First, navigate to the Custom Vision Service main page.

  2. [Get Started] (開始) ボタンをクリックします。Click on the Get Started button.

  3. サインイン、 Custom Vision Serviceポータル。Sign in to the Custom Vision Service Portal.

    注意

    Azure アカウントがいない場合は、1 つを作成する必要があります。If you do not already have an Azure account, you will need to create one. クラスルームまたはラボのような状況では、このチュートリアルをフォローしている場合は、講師または新しいアカウントのセットアップについて proctors のいずれかにお問い合わせください。If you are following this tutorial in a classroom or lab situation, ask your instructor or one of the proctors for help setting up your new account.

  4. 求められます初めてログインした後、サービス利用規約パネル。Once you are logged in for the first time, you will be prompted with the Terms of Service panel. 条項に同意する チェック ボックスをクリックします。Click on the checkbox to agree to the terms. をクリックして同意します。Then click on I agree.

  5. 条項に同意したことに移動する、プロジェクトポータルのセクション。Having agreed to the Terms, you will be navigated to the Projects section of the Portal. をクリックして新しいプロジェクトします。Click on New Project.

  6. プロジェクトの一部のフィールドを指定するように求められますが、右側にあるタブが表示されます。A tab will appear on the right-hand side, which will prompt you to specify some fields for the project.

    1. 挿入、名前プロジェクト用。Insert a Name for your project.

    2. 挿入、説明プロジェクト用 (省略可能な)。Insert a Description for your project (optional).

    3. 選択、リソース グループか新規に作成します。Choose a Resource Group or create a new one. リソース グループは、監視、プロビジョニングのアクセスを制御および Azure の資産のコレクションの課金を管理する方法を提供します。A resource group provides a way to monitor, control access, provision and manage billing for a collection of Azure assets. 勧めします (例: これらのコース) などの 1 つのプロジェクトに共通のリソース グループの下の Azure サービスに関連付けられているすべて保持する)。It is recommended to keep all the Azure Services associated with a single project (e.g. such as these courses) under a common resource group).

    4. 設定、プロジェクトの種類分類Set the Project Types to Classification

    5. 設定、ドメインとして全般します。Set the Domains as General.

      詳細にする場合、Azure リソース グループについてのごリソース グループの記事を参照してください。します。If you wish to read more about Azure Resource Groups, please visit the resource group article.

  7. をクリックしたら後、プロジェクトの作成、Custom Vision Service で、プロジェクトのページにリダイレクトされます。Once you are finished, click on Create project, you will be redirected to the Custom Vision Service, project page.

第 2 章 – Custom Vision プロジェクトのトレーニングChapter 2 - Training your Custom Vision project

1 回、Custom Vision ポータルの主な目的はイメージ内の特定のオブジェクトを認識するようにプロジェクトのトレーニングには。Once in the Custom Vision portal, your primary objective is to train your project to recognize specific objects in images. イメージには少なくとも 5 つ (5) 必要がありますが 10 (10) が、アプリケーションを認識したい各オブジェクトで、優先されます。You need at least five (5) images, though ten (10) is preferred, for each object that you would like your application to recognize. (コンピューターのマウスとキーボード) は、このコースで提供されるイメージを使用するします。You can use the images provided with this course (a computer mouse and a keyboard).

Custom Vision Service プロジェクトのトレーニング。To train your Custom Vision Service project:

  1. をクリックして、 + 横にタグ。Click on the + button next to Tags.

  2. 追加、名前オブジェクトを認識したいのです。Add the name of the object you would like to recognize. をクリックして保存します。Click on Save.

  3. タグが追加されました (表示するページを再読み込みする必要があります)。You will notice your Tag has been added (you may need to reload your page for it to appear). チェックされていない場合は、新しいタグと共にチェック ボックスをクリックします。Click the checkbox alongside your new tag, if it is not already checked.

  4. をクリックしての画像の追加ページの中央にします。Click on Add Images in the center of the page.

  5. をクリックしてローカル ファイルを参照を検索し、最小の中で、アップロードするイメージを選択します。 5 (5)。Click on Browse local files, and search, then select, the images you would like to upload, with the minimum being five (5). これらのイメージはすべてトレーニングは、オブジェクトを含める必要がありますに注意してください。Remember all of these images should contain the object which you are training.

    注意

    一度にアップロードするいくつかのイメージを選択できます。You can select several images at a time, to upload.

  6. 該当するタグを選択 タブで、イメージを確認できます、マイ タグボックス。Once you can see the images in the tab, select the appropriate tag in the My Tags box.

  7. をクリックしてファイルをアップロードします。Click on Upload files. ファイル アップロードが開始されます。The files will begin uploading. アップロードの確認したら、クリックして完了します。Once you have confirmation of the upload, click Done.

  8. 新たに作成するのと同じプロセスを繰り返します タグ という名前の キーボード の適切な写真をアップロードします。Repeat the same process to create a new Tag named Keyboard and upload the appropriate photos for it. 必ず をオフに マウス を表示するために、新しいタグを作成したら、 イメージを追加 ウィンドウ。Make sure to uncheck Mouse once you have created the new tags, so to show the Add images window.

  9. 両方のタグを設定したら、クリックしてトレーニング、最初のトレーニングのイテレーションを始めましょう。Once you have both Tags set up, click on Train, and the first training iteration will start building.

  10. ビルドされたらという 2 つのボタンを表示できるが既定予測 URLします。Once it is built, you will be able to see two buttons called Make default and Prediction URL. をクリックして既定でクリックし、最初に、予測 URLします。Click on Make default first, then click on Prediction URL.

    注意

    ここから、提供されているエンドポイントの URL どちらに設定されてイテレーションが既定としてマークされました。The endpoint URL which is provided from this, is set to whichever Iteration has been marked as default. このため、後で行った場合、新しいイテレーションと既定値として更新して、コードを変更する必要はありません。As such, if you later make a new Iteration and update it as default, you will not need to change your code.

  11. クリックすると予測 URL開き、メモ帳、コピーして貼り付け、 URL予測キーできるように、コードの後半で必要なときに取得します。Once you have clicked on Prediction URL, open Notepad, and copy and paste the URL and the Prediction-Key, so that you can retrieve it when you need it later in the code.

  12. をクリックして、歯車上部にある画面の右。Click on the Cog at the top right of the screen.

  13. コピー、トレーニング キー貼り付けます、メモ帳、後で使用します。Copy the Training Key and paste it into a Notepad, for later use.

  14. コピーも、プロジェクト Idに貼り付けることも、メモ帳ファイルは、後で使用します。Also copy your Project Id, and also paste it into your Notepad file, for later use.

第 3 章 - Unity プロジェクトの設定Chapter 3 - Set up the Unity project

次のコード例が複合現実での開発の一般的な設定して、そのため、他のプロジェクトの適切なテンプレートには。The following is a typical set up for developing with mixed reality, and as such, is a good template for other projects.

  1. 開いているUnityクリック新規します。Open Unity and click New.

  2. これで、Unity プロジェクトの名前を指定する必要があります。You will now need to provide a Unity project name. 挿入AzureCustomVision します。Insert AzureCustomVision. 必ず、プロジェクト テンプレートに設定されて3Dします。Make sure the project template is set to 3D. 設定、場所に該当する別の場所 (ただし、ルート ディレクトリに近づけるためのより良い)。Set the Location to somewhere appropriate for you (remember, closer to root directories is better). をクリックし、プロジェクトの作成です。Then, click Create project.

  3. 既定値を確認する必要が開いている Unity、スクリプト エディターに設定されているVisual Studioします。With Unity open, it is worth checking the default Script Editor is set to Visual Studio. 移動して 編集 > 設定 し、新しいウィンドウに移動 外部ツール します。Go to Edit > Preferences and then from the new window, navigate to External Tools. 変更External Script EditorVisual Studio 2017します。Change External Script Editor to Visual Studio 2017. 閉じる、設定ウィンドウ。Close the Preferences window.

  4. 次に移動ファイル > Build Settingsを選択し、ユニバーサル Windows プラットフォーム、をクリックして、スイッチ プラットフォーム選択内容を適用するボタンをクリックします。Next, go to File > Build Settings and select Universal Windows Platform, then click on the Switch Platform button to apply your selection.

  5. ファイル > Build Settingsことを確認してください。While still in File > Build Settings and make sure that:

    1. デバイスを対象にに設定されているHololensTarget Device is set to Hololens

      イマーシブ ヘッドセット、設定ターゲット デバイス任意のデバイスします。For the immersive headsets, set Target Device to Any Device.

    2. ビルドの種類に設定されているD3DBuild Type is set to D3D

    3. SDKに設定されているインストールされている最新SDK is set to Latest installed

    4. Visual Studio バージョンに設定されているインストールされている最新Visual Studio Version is set to Latest installed

    5. ビルドおよび実行に設定されているローカル マシンBuild and Run is set to Local Machine

    6. シーンを保存し、ビルドに追加します。Save the scene and add it to the build.

      1. これには、選択開くシーンを追加します。Do this by selecting Add Open Scenes. 保存ウィンドウが表示されます。A save window will appear.

      2. 新しいフォルダーを作成と、任意の将来、シーン、し、選択、新しいフォルダーボタンは、新しいフォルダーを作成する名前を付けますシーンします。Create a new folder for this, and any future, scene, then select the New folder button, to create a new folder, name it Scenes.

      3. 新たに作成した開くシーンフォルダー、し、ファイル名: テキスト フィールドに「 CustomVisionScene、[] をクリック保存Open your newly created Scenes folder, and then in the File name: text field, type CustomVisionScene, then click on Save.

        注意してください、内の Unity シーンを保存する必要があります、資産フォルダー、Unity プロジェクトに関連付けられている必要があります。Be aware, you must save your Unity scenes within the Assets folder, as they must be associated with the Unity project. Unity プロジェクトの構造の一般的な方法は、シーン フォルダー (およびその他の同様のフォルダー) を作成します。Creating the scenes folder (and other similar folders) is a typical way of structuring a Unity project.

    7. 設定に残っているBuild Settings、ここでは既定値として残しておく必要があります。The remaining settings, in Build Settings, should be left as default for now.

  6. Build Settingsウィンドウのプレーヤー設定ボタン、領域に関連するパネルが開き、インスペクターが配置されています。In the Build Settings window, click on the Player Settings button, this will open the related panel in the space where the Inspector is located.

  7. このパネルは、いくつかの設定を確認する必要があります。In this panel, a few settings need to be verified:

    1. その他の設定 タブ。In the Other Settings tab:

      1. ランタイム バージョンをスクリプトする必要があります試験的 (.NET 4.6 Equivalent) エディターを再起動する必要があるします。Scripting Runtime Version should be Experimental (.NET 4.6 Equivalent), which will trigger a need to restart the Editor.

      2. バックエンドの scriptingべき .NETScripting Backend should be .NET

      3. API の互換性レベルべき .NET 4.6API Compatibility Level should be .NET 4.6

    2. 内で、発行の設定] タブの [機能、確認してください。Within the Publishing Settings tab, under Capabilities, check:

      1. InternetClientInternetClient

      2. Web カメラWebcam

      3. マイクMicrophone

    3. パネル、下の方にXR 設定(次に示します発行設定)、ティック仮想現実サポート、ことを確認、 Windows Mixed Reality SDKが追加されます。Further down the panel, in XR Settings (found below Publish Settings), tick Virtual Reality Supported, make sure the Windows Mixed Reality SDK is added.

  8. 戻りBuild Settings Unity C#プロジェクトが不要になったグレー; これの横にあるチェック ボックスをオンにします。Back in Build Settings Unity C# Projects is no longer greyed out; tick the checkbox next to this.

  9. ビルド設定ウィンドウを閉じます。Close the Build Settings window.

  10. シーンとプロジェクトを保存 (ファイル > SAVE SCENE/ファイル > プロジェクトの保存)。Save your Scene and project (FILE > SAVE SCENE / FILE > SAVE PROJECT).

第 4 章 - Unity で Newtonsoft DLL のインポートChapter 4 - Importing the Newtonsoft DLL in Unity

重要

スキップする場合、 Unity を設定するコンポーネントのこのコースで、コードにまっすぐコンティニュし、自由にこれをダウンロード302b.unitypackage MR-Azure の、としてプロジェクトにインポート、 カスタム パッケージから続けて第 6 章します。If you wish to skip the Unity Set up component of this course, and continue straight into code, feel free to download this Azure-MR-302b.unitypackage, import it into your project as a Custom Package, and then continue from Chapter 6.

このコースの使用を要求する、 Newtonsoftライブラリで、アセットに DLL として追加することができます。This course requires the use of the Newtonsoft library, which you can add as a DLL to your assets. パッケージを含むこのライブラリは、このリンクからダウンロードできます。します。The package containing this library can be downloaded from this Link. プロジェクトに Newtonsoft ライブラリをインポートするには、このコースに付属する Unity パッケージを使用します。To import the Newtonsoft library into your project, use the Unity Package which came with this course.

  1. 追加、 .unitypackage に Unity を使用して、 資産 > インポート パッケージ > カスタム パッケージ メニュー オプション。Add the .unitypackage to Unity by using the Assets > Import Package > Custom Package menu option.

  2. Unity パッケージのインポートその pop をボックスで、(およびなど)、すべてのことを確認プラグインが選択されています。In the Import Unity Package box that pops up, ensure everything under (and including) Plugins is selected.

  3. をクリックして、インポートをプロジェクトにアイテムを追加するボタンをクリックします。Click the Import button to add the items to your project.

  4. 移動して、 Newtonsoftの下のフォルダープラグインプロジェクト ビューを選び、 Newtonsoft.Json プラグインします。Go to the Newtonsoft folder under Plugins in the project view and select the Newtonsoft.Json plugin.

  5. Newtonsoft.Json プラグインように選択すると、 Any プラットフォームunchecked、ことを確認しますWSAPlayerunchecked、 をクリックし、適用します。With the Newtonsoft.Json plugin selected, ensure that Any Platform is unchecked, then ensure that WSAPlayer is also unchecked, then click Apply. これは、ファイルが正しく構成されていることを確認するだけです。This is just to confirm that the files are configured correctly.

    注意

    これらのプラグインをマークする Unity エディターでのみ使用することを構成します。Marking these plugins configures them to only be used in the Unity Editor. これらのプロジェクトは Unity からエクスポートした後に使用される、WSA フォルダー内の異なるセットがあります。There are a different set of them in the WSA folder which will be used after the project is exported from Unity.

  6. 次を開く必要があります、 WSAフォルダー内で、 Newtonsoftフォルダー。Next, you need to open the WSA folder, within the Newtonsoft folder. 構成した同じファイルのコピーが表示されます。You will see a copy of the same file you just configured. ファイルを選択し、インスペクターのことを確認しますSelect the file, and then in the inspector, ensure that

    • 任意のプラットフォームオフAny Platform is unchecked
    • のみ WSAPlayerチェックonly WSAPlayer is checked
    • 処理されないようにチェックDont process is checked

第 5 章 - カメラのセットアップChapter 5 - Camera setup

  1. [階層] パネルで、選択、 Main Cameraします。In the Hierarchy Panel, select the Main Camera.

  2. すべてのコンポーネントを参照してください。 選択すると、ができる、 Main Cameraで、インスペクター パネルします。Once selected, you will be able to see all the components of the Main Camera in the Inspector Panel.

    1. カメラオブジェクトを指定する必要がありますMain Camera (スペルに注意してください)。The camera object must be named Main Camera (note the spelling!)

    2. Main Cameraタグに設定する必要がありますMainCamera (スペルに注意してください)。The Main Camera Tag must be set to MainCamera (note the spelling!)

    3. 必ず、変換位置に設定されている0, 0, 0Make sure the Transform Position is set to 0, 0, 0

    4. 設定フラグをクリア単色(イマーシブ ヘッドセットの無視) します。Set Clear Flags to Solid Color (ignore this for immersive headset).

    5. 設定、バック グラウンド、カメラの色コンポーネントを黒、アルファ 0 (16 進コード: #00000000) (イマーシブ ヘッドセットの無視) します。Set the Background Color of the camera Component to Black, Alpha 0 (Hex Code: #00000000) (ignore this for immersive headset).

第 6 章 - CustomVisionAnalyser クラスを作成します。Chapter 6 - Create the CustomVisionAnalyser class.

この時点でコードを記述する準備が整いました。At this point you are ready to write some code.

開始するが、 CustomVisionAnalyserクラス。You will begin with the CustomVisionAnalyser class.

注意

呼び出し、 Custom Vision Serviceに示すコードで行われた以下を使用して作成、 Custom Vision REST APIします。The calls to the Custom Vision Service made in the code shown below are made using the Custom Vision REST API. これを使用して、実装して (ような画面が独自に実装する方法を理解するために役立ちます) この API を使用する方法が表示されます。Through using this, you will see how to implement and make use of this API (useful for understanding how to implement something similar on your own). 対応しており、Microsoft が提供する、 Custom Vision Service SDKをサービスを呼び出すことにも使用できます。Be aware, that Microsoft offers a Custom Vision Service SDK that can also be used to make calls to the Service. 詳細については、次を参照してください。、 Custom Vision Service SDK記事。For more information visit the Custom Vision Service SDK article.

このクラスは、責任を負います。This class is responsible for:

  • バイト配列としてキャプチャされた最新のイメージを読み込んでいます。Loading the latest image captured as an array of bytes.

  • バイト配列を Azure に送信するCustom Vision Service分析のインスタンス。Sending the byte array to your Azure Custom Vision Service instance for analysis.

  • JSON 文字列としての応答を受信します。Receiving the response as a JSON string.

  • 応答を逆シリアル化し、その結果を渡して予測SceneOrganiserクラスは、応答の表示方法の考慮されます。Deserializing the response and passing the resulting Prediction to the SceneOrganiser class, which will take care of how the response should be displayed.

このクラスを作成します。To create this class:

  1. 右クリックし、アセット フォルダー内にある、プロジェクト パネル、順にクリックします作成 > フォルダーします。Right-click in the Asset Folder located in the Project Panel, then click Create > Folder. フォルダーを呼び出すスクリプトします。Call the folder Scripts.

  2. 先ほど作成した、開くフォルダーをダブルクリックします。Double-click on the folder just created, to open it.

  3. フォルダー内を右クリックし、をクリックして作成 > C#スクリプトします。Right-click inside the folder, then click Create > C# Script. スクリプトの名前CustomVisionAnalyserします。Name the script CustomVisionAnalyser.

  4. ダブルクリックして、新しいCustomVisionAnalyserスクリプト ファイルを開くVisual Studioします。Double-click on the new CustomVisionAnalyser script to open it with Visual Studio.

  5. 次のように、ファイルの上部にある名前空間を更新します。Update the namespaces at the top of your file to match the following:

    using System.Collections;
    using System.IO;
    using UnityEngine;
    using UnityEngine.Networking;
    using Newtonsoft.Json;
    
  6. CustomVisionAnalyserクラスで、次の変数を追加します。In the CustomVisionAnalyser class, add the following variables:

        /// <summary>
        /// Unique instance of this class
        /// </summary>
        public static CustomVisionAnalyser Instance;
    
        /// <summary>
        /// Insert your Prediction Key here
        /// </summary>
        private string predictionKey = "- Insert your key here -";
    
        /// <summary>
        /// Insert your prediction endpoint here
        /// </summary>
        private string predictionEndpoint = "Insert your prediction endpoint here";
    
        /// <summary>
        /// Byte array of the image to submit for analysis
        /// </summary>
        [HideInInspector] public byte[] imageBytes;
    

    注意

    挿入することを確認、予測キーに、 predictionKey変数、および予測エンドポイントに、 predictionEndpoint変数。Make sure you insert your Prediction Key into the predictionKey variable and your Prediction Endpoint into the predictionEndpoint variable. これらをコピーしたメモ帳コースで以前。You copied these to Notepad earlier in the course.

  7. コードをAwake() インスタンス変数を初期化するために追加する必要があります。Code for Awake() now needs to be added to initialize the Instance variable:

        /// <summary>
        /// Initialises this class
        /// </summary>
        private void Awake()
        {
            // Allows this instance to behave like a singleton
            Instance = this;
        }
    
  8. メソッドを削除Start()Update() します。Delete the methods Start() and Update().

  9. コルーチンを次に、追加 (静的でGetImageAsByteArray() 下にあるメソッド)、によってキャプチャされたイメージの分析の結果を取得するが、 ImageCaptureクラス。Next, add the coroutine (with the static GetImageAsByteArray() method below it), which will obtain the results of the analysis of the image captured by the ImageCapture class.

    注意

    AnalyseImageCaptureコルーチンへの呼び出しがある、 SceneOrganiserクラスを作成することはまだです。In the AnalyseImageCapture coroutine, there is a call to the SceneOrganiser class that you are yet to create. そのため、は省略します線は、ここではコメントします。Therefore, leave those lines commented for now.

        /// <summary>
        /// Call the Computer Vision Service to submit the image.
        /// </summary>
        public IEnumerator AnalyseLastImageCaptured(string imagePath)
        {
            WWWForm webForm = new WWWForm();
            using (UnityWebRequest unityWebRequest = UnityWebRequest.Post(predictionEndpoint, webForm))
            {
                // Gets a byte array out of the saved image
                imageBytes = GetImageAsByteArray(imagePath);
    
                unityWebRequest.SetRequestHeader("Content-Type", "application/octet-stream");
                unityWebRequest.SetRequestHeader("Prediction-Key", predictionKey);
    
                // The upload handler will help uploading the byte array with the request
                unityWebRequest.uploadHandler = new UploadHandlerRaw(imageBytes);
                unityWebRequest.uploadHandler.contentType = "application/octet-stream";
    
                // The download handler will help receiving the analysis from Azure
                unityWebRequest.downloadHandler = new DownloadHandlerBuffer();
    
                // Send the request
                yield return unityWebRequest.SendWebRequest();
    
                string jsonResponse = unityWebRequest.downloadHandler.text;
    
                // The response will be in JSON format, therefore it needs to be deserialized    
    
                // The following lines refers to a class that you will build in later Chapters
                // Wait until then to uncomment these lines
    
                //AnalysisObject analysisObject = new AnalysisObject();
                //analysisObject = JsonConvert.DeserializeObject<AnalysisObject>(jsonResponse);
                //SceneOrganiser.Instance.SetTagsToLastLabel(analysisObject);
            }
        }
    
        /// <summary>
        /// Returns the contents of the specified image 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);
        }
    
  10. 変更を保存することを確認するVisual Studioに戻る前にUnityします。Be sure to save your changes in Visual Studio before returning to Unity.

7 - 章 CustomVisionObjects クラスを作成します。Chapter 7 - Create the CustomVisionObjects class

クラスの作成はここでは、 CustomVisionObjectsクラス。The class you will create now is the CustomVisionObjects class.

このスクリプトにはへの呼び出しを逆シリアル化およびシリアル化する他のクラスによって使用されるオブジェクト数が含まれています、 Custom Vision Serviceします。This script contains a number of objects used by other classes to serialize and deserialize the calls made to the Custom Vision Service.

警告

として、Custom Vision Service が提供するエンドポイントをメモしてを実行することが重要では、次の JSON 構造体がされている設定を使用する Custom Vision 予測 v2.0します。It is important that you take note of the endpoint that the Custom Vision Service provides you, as the below JSON structure has been set up to work with Custom Vision Prediction v2.0. 別のバージョンがあれば、更新する必要があります、以下の構造体。If you have a different version, you may need to update the below structure.

このクラスを作成します。To create this class:

  1. 内で右クリック、スクリプトフォルダー、 をクリックし、作成 > C#スクリプトします。Right-click inside the Scripts folder, then click Create > C# Script. スクリプトを呼び出すCustomVisionObjectsします。Call the script CustomVisionObjects.

  2. ダブルクリックして、新しいCustomVisionObjectsスクリプト ファイルを開くVisual Studioします。Double-click on the new CustomVisionObjects script to open it with Visual Studio.

  3. ファイルの先頭には、次の名前空間を追加します。Add the following namespaces to the top of the file:

    using System;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Networking;
    
  4. 削除、 Start()Update() 内のメソッド、 CustomVisionObjectsクラスです。 このクラスを空にする必要がありますするようになりました。Delete the Start() and Update() methods inside the CustomVisionObjects class; this class should now be empty.

  5. 次のクラスを追加CustomVisionObjectsクラス。Add the following classes outside the CustomVisionObjects class. これらのオブジェクトを使って、 Newtonsoftおよび応答データを逆シリアル化するライブラリ。These objects are used by the Newtonsoft library to serialize and deserialize the response data:

    // The objects contained in this script represent the deserialized version
    // of the objects used by this application 
    
    /// <summary>
    /// Web request object for image data
    /// </summary>
    class MultipartObject : IMultipartFormSection
    {
        public string sectionName { get; set; }
    
        public byte[] sectionData { get; set; }
    
        public string fileName { get; set; }
    
        public string contentType { get; set; }
    }
    
    /// <summary>
    /// JSON of all Tags existing within the project
    /// contains the list of Tags
    /// </summary> 
    public class Tags_RootObject
    {
        public List<TagOfProject> Tags { get; set; }
        public int TotalTaggedImages { get; set; }
        public int TotalUntaggedImages { get; set; }
    }
    
    public class TagOfProject
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public int ImageCount { get; set; }
    }
    
    /// <summary>
    /// JSON of Tag to associate to an image
    /// Contains a list of hosting the tags,
    /// since multiple tags can be associated with one image
    /// </summary> 
    public class Tag_RootObject
    {
        public List<Tag> Tags { get; set; }
    }
    
    public class Tag
    {
        public string ImageId { get; set; }
        public string TagId { get; set; }
    }
    
    /// <summary>
    /// JSON of Images submitted
    /// Contains objects that host detailed information about one or more images
    /// </summary> 
    public class ImageRootObject
    {
        public bool IsBatchSuccessful { get; set; }
        public List<SubmittedImage> Images { get; set; }
    }
    
    public class SubmittedImage
    {
        public string SourceUrl { get; set; }
        public string Status { get; set; }
        public ImageObject Image { get; set; }
    }
    
    public class ImageObject
    {
        public string Id { get; set; }
        public DateTime Created { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }
        public string ImageUri { get; set; }
        public string ThumbnailUri { get; set; }
    }
    
    /// <summary>
    /// JSON of Service Iteration
    /// </summary> 
    public class Iteration
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public bool IsDefault { get; set; }
        public string Status { get; set; }
        public string Created { get; set; }
        public string LastModified { get; set; }
        public string TrainedAt { get; set; }
        public string ProjectId { get; set; }
        public bool Exportable { get; set; }
        public string DomainId { get; set; }
    }
    
    /// <summary>
    /// Predictions received by the Service after submitting an image for analysis
    /// </summary> 
    [Serializable]
    public class AnalysisObject
    {
        public List<Prediction> Predictions { get; set; }
    }
    
    [Serializable]
    public class Prediction
    {
        public string TagName { get; set; }
        public double Probability { get; set; }
    }
    

8 - 章 VoiceRecognizer クラスを作成します。Chapter 8 - Create the VoiceRecognizer class

このクラスは、ユーザーからの音声入力を認識します。This class will recognize the voice input from the user.

このクラスを作成します。To create this class:

  1. 内で右クリック、スクリプトフォルダー、 をクリックし、作成 > C#スクリプトします。Right-click inside the Scripts folder, then click Create > C# Script. スクリプトを呼び出すVoiceRecognizerします。Call the script VoiceRecognizer.

  2. ダブルクリックして、新しいVoiceRecognizerスクリプト ファイルを開くVisual Studioします。Double-click on the new VoiceRecognizer script to open it with Visual Studio.

  3. 上記の次の名前空間を追加、 VoiceRecognizerクラス。Add the following namespaces above the VoiceRecognizer class:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using UnityEngine;
    using UnityEngine.Windows.Speech;
    
  4. 内で、次の変数を追加し、 VoiceRecognizerクラス上、 Start() メソッド。Then add the following variables inside the VoiceRecognizer class, above the Start() method:

        /// <summary>
        /// Allows this class to behave like a singleton
        /// </summary>
        public static VoiceRecognizer Instance;
    
        /// <summary>
        /// Recognizer class for voice recognition
        /// </summary>
        internal KeywordRecognizer keywordRecognizer;
    
        /// <summary>
        /// List of Keywords registered
        /// </summary>
        private Dictionary<string, Action> _keywords = new Dictionary<string, Action>();
    
  5. 追加、 Awake()Start() メソッド後者は、ユーザーの設定キーワードイメージにタグを関連付けるときに認識されるようにします。Add the Awake() and Start() methods, the latter of which will set up the user keywords to be recognized when associating a tag to an image:

        /// <summary>
        /// Called on initialization
        /// </summary>
        private void Awake()
        {
            Instance = this;
        }
    
        /// <summary>
        /// Runs at initialization right after Awake method
        /// </summary>
        void Start ()
        {
    
            Array tagsArray = Enum.GetValues(typeof(CustomVisionTrainer.Tags));
    
            foreach (object tagWord in tagsArray)
            {
                _keywords.Add(tagWord.ToString(), () =>
                {
                    // When a word is recognized, the following line will be called
                    CustomVisionTrainer.Instance.VerifyTag(tagWord.ToString());
                });
            }
    
            _keywords.Add("Discard", () =>
            {
                // When a word is recognized, the following line will be called
                // The user does not want to submit the image
                // therefore ignore and discard the process
                ImageCapture.Instance.ResetImageCapture();
                keywordRecognizer.Stop();
            });
    
            //Create the keyword recognizer 
            keywordRecognizer = new KeywordRecognizer(_keywords.Keys.ToArray());
    
            // Register for the OnPhraseRecognized event 
            keywordRecognizer.OnPhraseRecognized += KeywordRecognizer_OnPhraseRecognized;
        }
    
  6. 削除、 Update() メソッド。Delete the Update() method.

  7. 音声入力が認識されるたびに呼び出される次のハンドラーを追加します。Add the following handler, which is called whenever voice input is recognized:

        /// <summary>
        /// Handler called when a word is recognized
        /// </summary>
        private void KeywordRecognizer_OnPhraseRecognized(PhraseRecognizedEventArgs args)
        {
            Action keywordAction;
            // if the keyword recognized is in our dictionary, call that Action.
            if (_keywords.TryGetValue(args.text, out keywordAction))
            {
                keywordAction.Invoke();
            }
        }
    
  8. 変更を保存することを確認するVisual Studioに戻る前にUnityします。Be sure to save your changes in Visual Studio before returning to Unity.

注意

心配しないでコードはこれらを修正する、すぐにそれ以上のクラスを提供すると、エラーが表示される可能性があります。Do not worry about code which might appear to have an error, as you will provide further classes soon, which will fix these.

9 - 章 CustomVisionTrainer クラスを作成します。Chapter 9 - Create the CustomVisionTrainer class

このクラスは、一連のトレーニングに web の呼び出しをチェーン、 Custom Vision Serviceします。This class will chain a series of web calls to train the Custom Vision Service. 各呼び出しは、コードのすぐ上に詳しく説明されます。Each call will be explained in detail right above the code.

このクラスを作成します。To create this class:

  1. 内で右クリック、スクリプトフォルダー、 をクリックし、作成 > C#スクリプトします。Right-click inside the Scripts folder, then click Create > C# Script. スクリプトを呼び出すCustomVisionTrainerします。Call the script CustomVisionTrainer.

  2. ダブルクリックして、新しいCustomVisionTrainerスクリプト ファイルを開くVisual Studioします。Double-click on the new CustomVisionTrainer script to open it with Visual Studio.

  3. 上記の次の名前空間を追加、 CustomVisionTrainerクラス。Add the following namespaces above the CustomVisionTrainer class:

    using Newtonsoft.Json;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using UnityEngine;
    using UnityEngine.Networking;
    
  4. 内で、次の変数を追加し、 CustomVisionTrainerクラス上、 Start() メソッド。Then add the following variables inside the CustomVisionTrainer class, above the Start() method.

    注意

    ここで使用するトレーニングの URL は用意されている、 Custom Vision トレーニング 1.2ドキュメントの構造体であり。 https://southcentralus.api.cognitive.microsoft.com/customvision/v1.2/Training/projects/{projectId}/The training URL used here is provided within the Custom Vision Training 1.2 documentation, and has a structure of: https://southcentralus.api.cognitive.microsoft.com/customvision/v1.2/Training/projects/{projectId}/
    詳細については、次を参照してください。、 v1.2 リファレンスの Custom Vision トレーニング APIします。For more information, visit the Custom Vision Training v1.2 reference API.

    警告

    Custom Vision Service を提供するトレーニング モードで使用する JSON 構造体としてエンドポイントをメモしてを実行することが重要になります (内で、 CustomVisionObjectsクラス) を使用するように設定されている Custom Vision トレーニング v1.2します。It is important that you take note of the endpoint that the Custom Vision Service provides you for the training mode, as the JSON structure used (within the CustomVisionObjects class) has been set up to work with Custom Vision Training v1.2. 別のバージョンがあれば、更新する必要があります、オブジェクト構造体。If you have a different version, you may need to update the Objects structure.

        /// <summary>
        /// Allows this class to behave like a singleton
        /// </summary>
        public static CustomVisionTrainer Instance;
    
        /// <summary>
        /// Custom Vision Service URL root
        /// </summary>
        private string url = "https://southcentralus.api.cognitive.microsoft.com/customvision/v1.2/Training/projects/";
    
        /// <summary>
        /// Insert your prediction key here
        /// </summary>
        private string trainingKey = "- Insert your key here -";
    
        /// <summary>
        /// Insert your Project Id here
        /// </summary>
        private string projectId = "- Insert your Project Id here -";
    
        /// <summary>
        /// Byte array of the image to submit for analysis
        /// </summary>
        internal byte[] imageBytes;
    
        /// <summary>
        /// The Tags accepted
        /// </summary>
        internal enum Tags {Mouse, Keyboard}
    
        /// <summary>
        /// The UI displaying the training Chapters
        /// </summary>
        private TextMesh trainingUI_TextMesh;
    

    重要

    追加することを確認、サービス キー (トレーニング キー) の値とプロジェクト Id値、以前書き留めておいたこれらは、値をコース (前のポータルから収集された。第 2 章の手順 10 以降)します。Ensure that you add your Service Key (Training Key) value and Project Id value, which you noted down previous; these are the values you collected from the portal earlier in the course (Chapter 2, step 10 onwards).

  5. 次の追加Start()Awake() メソッド。Add the following Start() and Awake() methods. これらのメソッドは、初期化時にと呼ばれ、UI を設定する呼び出しを含めます。Those methods are called on initialization and contain the call to set up the UI:

        /// <summary>
        /// Called on initialization
        /// </summary>
        private void Awake()
        {
            Instance = this;
        }
    
        /// <summary>
        /// Runs at initialization right after Awake method
        /// </summary>
        private void Start()
        { 
            trainingUI_TextMesh = SceneOrganiser.Instance.CreateTrainingUI("TrainingUI", 0.04f, 0, 4, false);
        }
    
  6. 削除、 Update() メソッド。Delete the Update() method. このクラスでは、その必要はありません。This class will not need it.

  7. 追加、 RequestTagSelection() メソッド。Add the RequestTagSelection() method. このメソッドは、最初のイメージがキャプチャされ、デバイスに格納されているときに呼び出されるし、提出する準備ができて、 Custom Vision Service、トレーニングします。This method is the first to be called when an image has been captured and stored in the device and is now ready to be submitted to the Custom Vision Service, to train it. このメソッドの場合、トレーニング、UI、ユーザーが、キャプチャしたイメージにタグ付けに使用できるキーワードのセットが表示されます。This method displays, in the training UI, a set of keywords the user can use to tag the image that has been captured. 警告、 VoiceRecognizerクラスをユーザーに音声入力のリッスンを開始します。It also alerts the VoiceRecognizer class to begin listening to the user for voice input.

        internal void RequestTagSelection()
        {
            trainingUI_TextMesh.gameObject.SetActive(true);
            trainingUI_TextMesh.text = $" \nUse voice command \nto choose between the following tags: \nMouse\nKeyboard \nor say Discard";
    
            VoiceRecognizer.Instance.keywordRecognizer.Start();
        }
    
  8. 追加、 VerifyTag() メソッド。Add the VerifyTag() method. このメソッドによって認識される音声入力が表示されます、 VoiceRecognizerクラスし、その有効性を確認し、トレーニング プロセスを開始します。This method will receive the voice input recognized by the VoiceRecognizer class and verify its validity, and then begin the training process.

        /// <summary>
        /// Verify voice input against stored tags.
        /// If positive, it will begin the Service training process.
        /// </summary>
        internal void VerifyTag(string spokenTag)
        {
            if (spokenTag == Tags.Mouse.ToString() || spokenTag == Tags.Keyboard.ToString())
            {
                trainingUI_TextMesh.text = $"Tag chosen: {spokenTag}";
                VoiceRecognizer.Instance.keywordRecognizer.Stop();
                StartCoroutine(SubmitImageForTraining(ImageCapture.Instance.filePath, spokenTag));
            }
        }
    
  9. 追加、 SubmitImageForTraining() メソッド。Add the SubmitImageForTraining() method. このメソッドは Custom Vision Service トレーニング プロセスが開始されます。This method will begin the Custom Vision Service training process. 取得するには、まず、タグ Idユーザーからの検証済みの音声入力に関連付けられているサービスから。The first step is to retrieve the Tag Id from the Service which is associated with the validated speech input from the user. タグ Idし、イメージと一緒にアップロードされます。The Tag Id will then be uploaded along with the image.

        /// <summary>
        /// Call the Custom Vision Service to submit the image.
        /// </summary>
        public IEnumerator SubmitImageForTraining(string imagePath, string tag)
        {
            yield return new WaitForSeconds(2);
            trainingUI_TextMesh.text = $"Submitting Image \nwith tag: {tag} \nto Custom Vision Service";
            string imageId = string.Empty;
            string tagId = string.Empty;
    
            // Retrieving the Tag Id relative to the voice input
            string getTagIdEndpoint = string.Format("{0}{1}/tags", url, projectId);
            using (UnityWebRequest www = UnityWebRequest.Get(getTagIdEndpoint))
            {
                www.SetRequestHeader("Training-Key", trainingKey);
                www.downloadHandler = new DownloadHandlerBuffer();
                yield return www.SendWebRequest();
                string jsonResponse = www.downloadHandler.text;
    
                Tags_RootObject tagRootObject = JsonConvert.DeserializeObject<Tags_RootObject>(jsonResponse);
    
                foreach (TagOfProject tOP in tagRootObject.Tags)
                {
                    if (tOP.Name == tag)
                    {
                        tagId = tOP.Id;
                    }             
                }
            }
    
            // Creating the image object to send for training
            List<IMultipartFormSection> multipartList = new List<IMultipartFormSection>();
            MultipartObject multipartObject = new MultipartObject();
            multipartObject.contentType = "application/octet-stream";
            multipartObject.fileName = "";
            multipartObject.sectionData = GetImageAsByteArray(imagePath);
            multipartList.Add(multipartObject);
    
            string createImageFromDataEndpoint = string.Format("{0}{1}/images?tagIds={2}", url, projectId, tagId);
    
            using (UnityWebRequest www = UnityWebRequest.Post(createImageFromDataEndpoint, multipartList))
            {
                // Gets a byte array out of the saved image
                imageBytes = GetImageAsByteArray(imagePath);           
    
                //unityWebRequest.SetRequestHeader("Content-Type", "application/octet-stream");
                www.SetRequestHeader("Training-Key", trainingKey);
    
                // The upload handler will help uploading the byte array with the request
                www.uploadHandler = new UploadHandlerRaw(imageBytes);
    
                // The download handler will help receiving the analysis from Azure
                www.downloadHandler = new DownloadHandlerBuffer();
    
                // Send the request
                yield return www.SendWebRequest();
    
                string jsonResponse = www.downloadHandler.text;
    
                ImageRootObject m = JsonConvert.DeserializeObject<ImageRootObject>(jsonResponse);
                imageId = m.Images[0].Image.Id;
            }
            trainingUI_TextMesh.text = "Image uploaded";
            StartCoroutine(TrainCustomVisionProject());
        }
    
  10. 追加、 TrainCustomVisionProject() メソッド。Add the TrainCustomVisionProject() method. イメージは、送信し、タグ付けされていますが、このメソッドが呼び出されます。Once the image has been submitted and tagged, this method will be called. サービスと、イメージに送信されたすべての前イメージとトレーニングは新しいイテレーションを作成しますだけアップロードします。It will create a new Iteration that will be trained with all the previous images submitted to the Service plus the image just uploaded. このメソッドは、新しく作成したを設定するメソッドを呼び出す、トレーニングが完了したら、イテレーションとして既定分析を使用しているエンドポイントが最新のトレーニング済み反復処理するようにします。Once the training has been completed, this method will call a method to set the newly created Iteration as Default, so that the endpoint you are using for analysis is the latest trained iteration.

        /// <summary>
        /// Call the Custom Vision Service to train the Service.
        /// It will generate a new Iteration in the Service
        /// </summary>
        public IEnumerator TrainCustomVisionProject()
        {
            yield return new WaitForSeconds(2);
    
            trainingUI_TextMesh.text = "Training Custom Vision Service";
    
            WWWForm webForm = new WWWForm();
    
            string trainProjectEndpoint = string.Format("{0}{1}/train", url, projectId);
    
            using (UnityWebRequest www = UnityWebRequest.Post(trainProjectEndpoint, webForm))
            {
                www.SetRequestHeader("Training-Key", trainingKey);
                www.downloadHandler = new DownloadHandlerBuffer();
                yield return www.SendWebRequest();
                string jsonResponse = www.downloadHandler.text;
                Debug.Log($"Training - JSON Response: {jsonResponse}");
    
                // A new iteration that has just been created and trained
                Iteration iteration = new Iteration();
                iteration = JsonConvert.DeserializeObject<Iteration>(jsonResponse);
    
                if (www.isDone)
                {
                    trainingUI_TextMesh.text = "Custom Vision Trained";
    
                    // Since the Service has a limited number of iterations available,
                    // we need to set the last trained iteration as default
                    // and delete all the iterations you dont need anymore
                    StartCoroutine(SetDefaultIteration(iteration)); 
                }
            }
        }
    
  11. 追加、 SetDefaultIteration() メソッド。Add the SetDefaultIteration() method. このメソッドは、以前に作成して、トレーニング済みのイテレーションとして設定は既定します。This method will set the previously created and trained iteration as Default. 完了すると、このメソッドは、既存のサービスで、前のイテレーションを削除する必要があります。Once completed, this method will have to delete the previous iteration existing in the Service. このコースの作成時は、イテレーションの最大 10 数、サービスで同時に存在できるの制限があります。At the time of writing this course, there is a limit of a maximum ten (10) iterations allowed to exist at the same time in the Service.

        /// <summary>
        /// Set the newly created iteration as Default
        /// </summary>
        private IEnumerator SetDefaultIteration(Iteration iteration)
        {
            yield return new WaitForSeconds(5);
            trainingUI_TextMesh.text = "Setting default iteration";
    
            // Set the last trained iteration to default
            iteration.IsDefault = true;
    
            // Convert the iteration object as JSON
            string iterationAsJson = JsonConvert.SerializeObject(iteration);
            byte[] bytes = Encoding.UTF8.GetBytes(iterationAsJson);
    
            string setDefaultIterationEndpoint = string.Format("{0}{1}/iterations/{2}", 
                                                            url, projectId, iteration.Id);
    
            using (UnityWebRequest www = UnityWebRequest.Put(setDefaultIterationEndpoint, bytes))
            {
                www.method = "PATCH";
                www.SetRequestHeader("Training-Key", trainingKey);
                www.SetRequestHeader("Content-Type", "application/json");
                www.downloadHandler = new DownloadHandlerBuffer();
    
                yield return www.SendWebRequest();
    
                string jsonResponse = www.downloadHandler.text;
    
                if (www.isDone)
                {
                    trainingUI_TextMesh.text = "Default iteration is set \nDeleting Unused Iteration";
                    StartCoroutine(DeletePreviousIteration(iteration));
                }
            }
        }
    
  12. 追加、 DeletePreviousIteration() メソッド。Add the DeletePreviousIteration() method. このメソッドを検索し、前の既定以外のイテレーションを削除します。This method will find and delete the previous non-default iteration:

        /// <summary>
        /// Delete the previous non-default iteration.
        /// </summary>
        public IEnumerator DeletePreviousIteration(Iteration iteration)
        {
            yield return new WaitForSeconds(5);
    
            trainingUI_TextMesh.text = "Deleting Unused \nIteration";
    
            string iterationToDeleteId = string.Empty;
    
            string findAllIterationsEndpoint = string.Format("{0}{1}/iterations", url, projectId);
    
            using (UnityWebRequest www = UnityWebRequest.Get(findAllIterationsEndpoint))
            {
                www.SetRequestHeader("Training-Key", trainingKey);
                www.downloadHandler = new DownloadHandlerBuffer();
                yield return www.SendWebRequest();
    
                string jsonResponse = www.downloadHandler.text;
    
                // The iteration that has just been trained
                List<Iteration> iterationsList = new List<Iteration>();
                iterationsList = JsonConvert.DeserializeObject<List<Iteration>>(jsonResponse);
    
                foreach (Iteration i in iterationsList)
                {
                    if (i.IsDefault != true)
                    {
                        Debug.Log($"Cleaning - Deleting iteration: {i.Name}, {i.Id}");
                        iterationToDeleteId = i.Id;
                        break;
                    }
                }
            }
    
            string deleteEndpoint = string.Format("{0}{1}/iterations/{2}", url, projectId, iterationToDeleteId);
    
            using (UnityWebRequest www2 = UnityWebRequest.Delete(deleteEndpoint))
            {
                www2.SetRequestHeader("Training-Key", trainingKey);
                www2.downloadHandler = new DownloadHandlerBuffer();
                yield return www2.SendWebRequest();
                string jsonResponse = www2.downloadHandler.text;
    
                trainingUI_TextMesh.text = "Iteration Deleted";
                yield return new WaitForSeconds(2);
                trainingUI_TextMesh.text = "Ready for next \ncapture";
    
                yield return new WaitForSeconds(2);
                trainingUI_TextMesh.text = "";
                ImageCapture.Instance.ResetImageCapture();
            }
        }
    
  13. このクラスに追加する最後のメソッド、 GetImageAsByteArray() メソッド、web の呼び出しでバイト配列にキャプチャされたイメージを変換するために使用します。The last method to add in this class is the GetImageAsByteArray() method, used on the web calls to convert the image captured into a byte array.

        /// <summary>
        /// Returns the contents of the specified image 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);
        }
    
  14. 変更を保存することを確認するVisual Studioに戻る前にUnityします。Be sure to save your changes in Visual Studio before returning to Unity.

10 - 章 SceneOrganiser クラスを作成します。Chapter 10 - Create the SceneOrganiser class

このクラスは。This class will:

  • 作成、カーソルMain Camera にアタッチするオブジェクト。Create a Cursor object to attach to the Main Camera.

  • 作成、ラベルサービスが現実世界のオブジェクトを認識しているときに表示されるオブジェクト。Create a Label object that will appear when the Service recognizes the real-world objects.

  • 適切なコンポーネントにアタッチすることにより、メイン カメラを設定します。Set up the Main Camera by attaching the appropriate components to it.

  • 場合に分析モード、メイン カメラの位置を基準とした適切なワールド空間における、実行時にラベルを生成、および、Custom Vision Service から受信したデータを表示します。When in Analysis Mode, spawn the Labels at runtime, in the appropriate world space relative to the position of the Main Camera, and display the data received from the Custom Vision Service.

  • 場合にトレーニング モード、トレーニング プロセスのさまざまな段階を表示する UI を起動します。When in Training Mode, spawn the UI that will display the different stages of the training process.

このクラスを作成します。To create this class:

  1. 内で右クリック、スクリプトフォルダー、 をクリックし、作成 > C#スクリプトします。Right-click inside the Scripts folder, then click Create > C# Script. スクリプトの名前SceneOrganiserします。Name the script SceneOrganiser.

  2. ダブルクリックして、新しいSceneOrganiserスクリプト ファイルを開くVisual Studioします。Double-click on the new SceneOrganiser script to open it with Visual Studio.

  3. 1 つの名前空間は必要がありますのみ、上記の他の削除、 SceneOrganiserクラス。You will only need one namespace, remove the others from above the SceneOrganiser class:

    using UnityEngine;
    
  4. 内で、次の変数を追加し、 SceneOrganiserクラス上、 Start() メソッド。Then add the following variables inside the SceneOrganiser class, above the Start() method:

        /// <summary>
        /// Allows this class to behave like a singleton
        /// </summary>
        public static SceneOrganiser Instance;
    
        /// <summary>
        /// The cursor object attached to the camera
        /// </summary>
        internal GameObject cursor;
    
        /// <summary>
        /// The label used to display the analysis on the objects in the real world
        /// </summary>
        internal GameObject label;
    
        /// <summary>
        /// Object providing the current status of the camera.
        /// </summary>
        internal TextMesh cameraStatusIndicator;
    
        /// <summary>
        /// Reference to the last label positioned
        /// </summary>
        internal Transform lastLabelPlaced;
    
        /// <summary>
        /// Reference to the last label positioned
        /// </summary>
        internal TextMesh lastLabelPlacedText;
    
        /// <summary>
        /// Current threshold accepted for displaying the label
        /// Reduce this value to display the recognition more often
        /// </summary>
        internal float probabilityThreshold = 0.5f;
    
  5. 削除、 Start()Update() メソッド。Delete the Start() and Update() methods.

  6. 変数の右下にある追加のAwake() メソッドはクラスを初期化し、シーンを設定します。Right underneath the variables, add the Awake() method, which will initialize the class and set up the scene.

        /// <summary>
        /// Called on initialization
        /// </summary>
        private void Awake()
        {
            // Use this class instance as singleton
            Instance = this;
    
            // Add the ImageCapture class to this GameObject
            gameObject.AddComponent<ImageCapture>();
    
            // Add the CustomVisionAnalyser class to this GameObject
            gameObject.AddComponent<CustomVisionAnalyser>();
    
            // Add the CustomVisionTrainer class to this GameObject
            gameObject.AddComponent<CustomVisionTrainer>();
    
            // Add the VoiceRecogniser class to this GameObject
            gameObject.AddComponent<VoiceRecognizer>();
    
            // Add the CustomVisionObjects class to this GameObject
            gameObject.AddComponent<CustomVisionObjects>();
    
            // Create the camera Cursor
            cursor = CreateCameraCursor();
    
            // Load the label prefab as reference
            label = CreateLabel();
    
            // Create the camera status indicator label, and place it above where predictions
            // and training UI will appear.
            cameraStatusIndicator = CreateTrainingUI("Status Indicator", 0.02f, 0.2f, 3, true);
    
            // Set camera status indicator to loading.
            SetCameraStatus("Loading");
        }
    
  7. ここで追加、 CreateCameraCursor() メソッドを作成して、メイン カメラ、カーソルを配置して、 CreateLabel() メソッドで、作成、分析ラベルオブジェクト.Now add the CreateCameraCursor() method that creates and positions the Main Camera cursor, and the CreateLabel() method, which creates the Analysis Label object.

        /// <summary>
        /// Spawns cursor for the Main Camera
        /// </summary>
        private GameObject CreateCameraCursor()
        {
            // Create a sphere as new cursor
            GameObject newCursor = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    
            // Attach it to the camera
            newCursor.transform.parent = gameObject.transform;
    
            // Resize the new cursor
            newCursor.transform.localScale = new Vector3(0.02f, 0.02f, 0.02f);
    
            // Move it to the correct position
            newCursor.transform.localPosition = new Vector3(0, 0, 4);
    
            // Set the cursor color to red
            newCursor.GetComponent<Renderer>().material = new Material(Shader.Find("Diffuse"));
            newCursor.GetComponent<Renderer>().material.color = Color.green;
    
            return newCursor;
        }
    
        /// <summary>
        /// Create the analysis label object
        /// </summary>
        private GameObject CreateLabel()
        {
            // Create a sphere as new cursor
            GameObject newLabel = new GameObject();
    
            // Resize the new cursor
            newLabel.transform.localScale = new Vector3(0.01f, 0.01f, 0.01f);
    
            // Creating the text of the label
            TextMesh t = newLabel.AddComponent<TextMesh>();
            t.anchor = TextAnchor.MiddleCenter;
            t.alignment = TextAlignment.Center;
            t.fontSize = 50;
            t.text = "";
    
            return newLabel;
        }
    
  8. 追加、 SetCameraStatus() メソッドで、メッセージのテキスト メッシュ、カメラの状態を提供するためのものを処理します。Add the SetCameraStatus() method, which will handle messages intended for the text mesh providing the status of the camera.

        /// <summary>
        /// Set the camera status to a provided string. Will be coloured if it matches a keyword.
        /// </summary>
        /// <param name="statusText">Input string</param>
        public void SetCameraStatus(string statusText)
        {
            if (string.IsNullOrEmpty(statusText) == false)
            {
                string message = "white";
    
                switch (statusText.ToLower())
                {
                    case "loading":
                        message = "yellow";
                        break;
    
                    case "ready":
                        message = "green";
                        break;
    
                    case "uploading image":
                        message = "red";
                        break;
    
                    case "looping capture":
                        message = "yellow";
                        break;
    
                    case "analysis":
                        message = "red";
                        break;
                }
    
                cameraStatusIndicator.GetComponent<TextMesh>().text = $"Camera Status:\n<color={message}>{statusText}..</color>";
            }
        }
    
  9. 追加、 PlaceAnalysisLabel()SetTagsToLastLabel() メソッドが生成されをシーンに Custom Vision Service からデータを表示します。Add the PlaceAnalysisLabel() and SetTagsToLastLabel() methods, which will spawn and display the data from the Custom Vision Service into the scene.

        /// <summary>
        /// Instantiate a label in the appropriate location relative to the Main Camera.
        /// </summary>
        public void PlaceAnalysisLabel()
        {
            lastLabelPlaced = Instantiate(label.transform, cursor.transform.position, transform.rotation);
            lastLabelPlacedText = lastLabelPlaced.GetComponent<TextMesh>();
        }
    
        /// <summary>
        /// Set the Tags as Text of the last label created. 
        /// </summary>
        public void SetTagsToLastLabel(AnalysisObject analysisObject)
        {
            lastLabelPlacedText = lastLabelPlaced.GetComponent<TextMesh>();
    
            if (analysisObject.Predictions != null)
            {
                foreach (Prediction p in analysisObject.Predictions)
                {
                    if (p.Probability > 0.02)
                    {
                        lastLabelPlacedText.text += $"Detected: {p.TagName} {p.Probability.ToString("0.00 \n")}";
                        Debug.Log($"Detected: {p.TagName} {p.Probability.ToString("0.00 \n")}");
                    }
                }
            }
        }
    
  10. 最後に、追加、 CreateTrainingUI() メソッドで、アプリケーションがトレーニング モードの場合、トレーニング プロセスの複数のステージを表示する UI が生成されます。Lastly, add the CreateTrainingUI() method, which will spawn the UI displaying the multiple stages of the training process when the application is in Training Mode. このメソッドは、カメラ状態オブジェクトの作成にも利用されています。This method will also be harnessed to create the camera status object.

        /// <summary>
        /// Create a 3D Text Mesh in scene, with various parameters.
        /// </summary>
        /// <param name="name">name of object</param>
        /// <param name="scale">scale of object (i.e. 0.04f)</param>
        /// <param name="yPos">height above the cursor (i.e. 0.3f</param>
        /// <param name="zPos">distance from the camera</param>
        /// <param name="setActive">whether the text mesh should be visible when it has been created</param>
        /// <returns>Returns a 3D text mesh within the scene</returns>
        internal TextMesh CreateTrainingUI(string name, float scale, float yPos, float zPos, bool setActive)
        {
            GameObject display = new GameObject(name, typeof(TextMesh));
            display.transform.parent = Camera.main.transform;
            display.transform.localPosition = new Vector3(0, yPos, zPos);
            display.SetActive(setActive);
            display.transform.localScale = new Vector3(scale, scale, scale);
            display.transform.rotation = new Quaternion();
            TextMesh textMesh = display.GetComponent<TextMesh>();
            textMesh.anchor = TextAnchor.MiddleCenter;
            textMesh.alignment = TextAlignment.Center;
            return textMesh;
        }
    
  11. 変更を保存することを確認するVisual Studioに戻る前にUnityします。Be sure to save your changes in Visual Studio before returning to Unity.

重要

続行する前に開いて、 CustomVisionAnalyserクラス内で、 AnalyseLastImageCaptured() メソッド、をコメント解除します次の行。Before you continue, open the CustomVisionAnalyser class, and within the AnalyseLastImageCaptured() method, uncomment the following lines:

  AnalysisObject analysisObject = new AnalysisObject();
  analysisObject = JsonConvert.DeserializeObject<AnalysisObject>(jsonResponse);
  SceneOrganiser.Instance.SetTagsToLastLabel(analysisObject);

11 - 章 ImageCapture クラスを作成します。Chapter 11 - Create the ImageCapture class

次のクラスを作成することには、 ImageCaptureクラス。The next class you are going to create is the ImageCapture class.

このクラスは、責任を負います。This class is responsible for:

  • HoloLens のカメラを使用して、格納することでイメージのキャプチャ、アプリフォルダー。Capturing an image using the HoloLens camera and storing it in the App Folder.

  • ユーザーからのタップ ジェスチャを処理します。Handling Tap gestures from the user.

  • 保守、 Enumかどうか、アプリケーションは実行を決定する値Analysisモードまたはトレーニングモード。Maintaining the Enum value that determines if the application will run in Analysis mode or Training Mode.

このクラスを作成します。To create this class:

  1. 移動して、スクリプト以前に作成したフォルダーです。Go to the Scripts folder you created previously.

  2. フォルダー内を右クリックし、をクリックして作成 > C#スクリプトします。Right-click inside the folder, then click Create > C# Script. スクリプトの名前ImageCaptureします。Name the script ImageCapture.

  3. ダブルクリックして、新しいImageCaptureスクリプト ファイルを開くVisual Studioします。Double-click on the new ImageCapture script to open it with Visual Studio.

  4. 次のように、ファイルの上部にある名前空間に置き換えます。Replace the namespaces at the top of the file with the following:

    using System;
    using System.IO;
    using System.Linq;
    using UnityEngine;
    using UnityEngine.XR.WSA.Input;
    using UnityEngine.XR.WSA.WebCam;
    
  5. 内で、次の変数を追加し、 ImageCaptureクラス上、 Start() メソッド。Then add the following variables inside the ImageCapture class, above the Start() method:

        /// <summary>
        /// Allows this class to behave like a singleton
        /// </summary>
        public static ImageCapture Instance;
    
        /// <summary>
        /// Keep counts of the taps for image renaming
        /// </summary>
        private int captureCount = 0;
    
        /// <summary>
        /// Photo Capture object
        /// </summary>
        private PhotoCapture photoCaptureObject = null;
    
        /// <summary>
        /// Allows gestures recognition in HoloLens
        /// </summary>
        private GestureRecognizer recognizer;
    
        /// <summary>
        /// Loop timer
        /// </summary>
        private float secondsBetweenCaptures = 10f;
    
        /// <summary>
        /// Application main functionalities switch
        /// </summary>
        internal enum AppModes {Analysis, Training }
    
        /// <summary>
        /// Local variable for current AppMode
        /// </summary>
        internal AppModes AppMode { get; private set; }
    
        /// <summary>
        /// Flagging if the capture loop is running
        /// </summary>
        internal bool captureIsActive;
    
        /// <summary>
        /// File path of current analysed photo
        /// </summary>
        internal string filePath = string.Empty;
    
  6. コードをAwake()Start() 今すぐメソッドを追加する必要があります。Code for Awake() and Start() methods now needs to be added:

        /// <summary>
        /// Called on initialization
        /// </summary>
        private void Awake()
        {
            Instance = this;
    
            // Change this flag to switch between Analysis Mode and Training Mode 
            AppMode = AppModes.Training;
        }
    
        /// <summary>
        /// Runs at initialization right after Awake method
        /// </summary>
        void Start()
        {
            // Clean up the LocalState folder of this application from all photos stored
            DirectoryInfo info = new DirectoryInfo(Application.persistentDataPath);
            var fileInfo = info.GetFiles();
            foreach (var file in fileInfo)
            {
                try
                {
                    file.Delete();
                }
                catch (Exception)
                {
                    Debug.LogFormat("Cannot delete file: ", file.Name);
                }
            } 
    
            // Subscribing to the Hololens API gesture recognizer to track user gestures
            recognizer = new GestureRecognizer();
            recognizer.SetRecognizableGestures(GestureSettings.Tap);
            recognizer.Tapped += TapHandler;
            recognizer.StartCapturingGestures();
    
            SceneOrganiser.Instance.SetCameraStatus("Ready");
        }
    
  7. タップ ジェスチャが発生したときに呼び出されるハンドラーを実装します。Implement a handler that will be called when a Tap gesture occurs.

        /// <summary>
        /// Respond to Tap Input.
        /// </summary>
        private void TapHandler(TappedEventArgs obj)
        {
            switch (AppMode)
            {
                case AppModes.Analysis:
                    if (!captureIsActive)
                    {
                        captureIsActive = true;
    
                        // Set the cursor color to red
                        SceneOrganiser.Instance.cursor.GetComponent<Renderer>().material.color = Color.red;
    
                        // Update camera status to looping capture.
                        SceneOrganiser.Instance.SetCameraStatus("Looping Capture");
    
                        // Begin the capture loop
                        InvokeRepeating("ExecuteImageCaptureAndAnalysis", 0, secondsBetweenCaptures);
                    }
                    else
                    {
                        // The user tapped while the app was analyzing 
                        // therefore stop the analysis process
                        ResetImageCapture();
                    }
                    break;
    
                case AppModes.Training:
                    if (!captureIsActive)
                    {
                        captureIsActive = true;
    
                        // Call the image capture
                        ExecuteImageCaptureAndAnalysis();
    
                        // Set the cursor color to red
                        SceneOrganiser.Instance.cursor.GetComponent<Renderer>().material.color = Color.red;
    
                        // Update camera status to uploading image.
                        SceneOrganiser.Instance.SetCameraStatus("Uploading Image");
                    }              
                    break;
            }     
        }
    

    注意

    Analysisモード、 TapHandlerメソッドを開始または写真キャプチャのループを停止するためのスイッチとして機能します。In Analysis mode, the TapHandler method acts as a switch to start or stop the photo capture loop.

    トレーニングモードでは、カメラからのイメージがキャプチャされます。In Training mode, it will capture an image from the camera.

    カーソルが緑色の場合、カメラは、イメージを使用できることを示します。When the cursor is green, it means the camera is available to take the image.

    カーソルが赤の場合は、カメラがビジー状態を意味します。When the cursor is red, it means the camera is busy.

  8. イメージのキャプチャ プロセスを開始し、イメージを格納するアプリケーションが使用するメソッドを追加します。Add the method that the application uses to start the image capture process and store the image.

        /// <summary>
        /// Begin process of Image Capturing and send To Azure Custom Vision Service.
        /// </summary>
        private void ExecuteImageCaptureAndAnalysis()
        {
            // Update camera status to analysis.
            SceneOrganiser.Instance.SetCameraStatus("Analysis");
    
            // Create a label in world space using the SceneOrganiser class 
            // Invisible at this point but correctly positioned where the image was taken
            SceneOrganiser.Instance.PlaceAnalysisLabel();
    
            // 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
                {
                    hologramOpacity = 0.0f,
                    cameraResolutionWidth = targetTexture.width,
                    cameraResolutionHeight = targetTexture.height,
                    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", captureCount);
                    filePath = Path.Combine(Application.persistentDataPath, filename);          
                    captureCount++;              
                    photoCaptureObject.TakePhotoAsync(filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);              
                });
            });   
        }
    
  9. 写真をキャプチャおよび分析する準備ができ次第の呼び出されるハンドラーを追加します。Add the handlers that will be called when the photo has been captured and for when it is ready to be analyzed. 渡されますが、結果、 CustomVisionAnalyserまたはCustomVisionTrainerモードによって、コードに設定します。The result is then passed to the CustomVisionAnalyser or the CustomVisionTrainer depending on which mode the code is set on.

        /// <summary>
        /// Register the full execution of the Photo Capture. 
        /// </summary>
        void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
        {
                // Call StopPhotoMode once the image has successfully captured
                photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
        }
    
    
        /// <summary>
        /// The camera photo mode has stopped after the capture.
        /// Begin the Image Analysis process.
        /// </summary>
        void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
        {
            Debug.LogFormat("Stopped Photo Mode");
    
            // Dispose from the object in memory and request the image analysis 
            photoCaptureObject.Dispose();
            photoCaptureObject = null;
    
            switch (AppMode)
            {
                case AppModes.Analysis:
                    // Call the image analysis
                    StartCoroutine(CustomVisionAnalyser.Instance.AnalyseLastImageCaptured(filePath));
                    break;
    
                case AppModes.Training:
                    // Call training using captured image
                    CustomVisionTrainer.Instance.RequestTagSelection();
                    break;
            }
        }
    
        /// <summary>
        /// Stops all capture pending actions
        /// </summary>
        internal void ResetImageCapture()
        {
            captureIsActive = false;
    
            // Set the cursor color to green
            SceneOrganiser.Instance.cursor.GetComponent<Renderer>().material.color = Color.green;
    
            // Update camera status to ready.
            SceneOrganiser.Instance.SetCameraStatus("Ready");
    
            // Stop the capture loop if active
            CancelInvoke();
        }
    
  10. 変更を保存することを確認するVisual Studioに戻る前にUnityします。Be sure to save your changes in Visual Studio before returning to Unity.

  11. これで、すべてのスクリプトが完了したら、Unity エディターでは、戻ってクリックしてアンド ドラッグ、 SceneOrganiserクラスから、スクリプトフォルダーをMain Cameraオブジェクトに、階層パネルします。Now that all the scripts have been completed, go back in the Unity Editor, then click and drag the SceneOrganiser class from the Scripts folder to the Main Camera object in the Hierarchy Panel.

第 12 章 - ビルドの前にChapter 12 - Before building

アプリケーションの徹底的なテストを実行するには、必要がありますをサイドロードすること、HoloLens にします。To perform a thorough test of your application you will need to sideload it onto your HoloLens.

実行する前にいることを確認します。Before you do, ensure that:

  • 説明されているすべての設定、第 2 章が正しく設定されています。All the settings mentioned in the Chapter 2 are set correctly.

  • 内のすべてのフィールド、 Main Cameraインスペクターのパネルが適切に割り当てられます。All the fields in the Main Camera, Inspector Panel, are assigned properly.

  • スクリプトSceneOrganiserにアタッチされて、 Main Cameraオブジェクト。The script SceneOrganiser is attached to the Main Camera object.

  • 挿入することを確認、予測キーに、 predictionKey変数。Make sure you insert your Prediction Key into the predictionKey variable.

  • 挿入した、予測エンドポイントに、 predictionEndpoint変数。You have inserted your Prediction Endpoint into the predictionEndpoint variable.

  • 挿入した、トレーニング キーに、 trainingKeyの変数、 CustomVisionTrainerクラス。You have inserted your Training Key into the trainingKey variable, of the CustomVisionTrainer class.

  • 挿入した、プロジェクト IDに、 projectIdの変数、 CustomVisionTrainerクラス。You have inserted your Project ID into the projectId variable, of the CustomVisionTrainer class.

第 13 章 - ビルドおよびサイドロード アプリChapter 13 - Build and sideload your application

開始する、ビルドプロセス。To begin the Build process:

  1. 移動してファイル > のビルド設定します。Go to File > Build Settings.

  2. ティックUnity C#プロジェクトします。Tick Unity C# Projects.

  3. [Build] をクリックします。Click Build. Unity を起動、ファイル エクスプ ローラーウィンドウを作成しにアプリをビルドするフォルダーを選択する必要があります。Unity will launch a File Explorer window, where you need to create and then select a folder to build the app into. ここで、そのフォルダーを作成し、名前アプリします。Create that folder now, and name it App. 使用し、アプリフォルダーを選択すると、クリックしてフォルダーの選択します。Then with the App folder selected, click on Select Folder.

  4. Unity にプロジェクトをビルドを開始、アプリフォルダー。Unity will begin building your project to the App folder.

  5. 1 回 Unity には、(少し時間がかかる場合があります) ビルドが完了したが開き、ファイル エクスプ ローラービルドの位置にあるウィンドウ (上の windows では、常に表示されないの新しい追加の通知をタスク バーを確認ウィンドウ)。Once Unity has finished building (it might take some time), it will open a File Explorer window at the location of your build (check your task bar, as it may not always appear above your windows, but will notify you of the addition of a new window).

HoloLens の展開。To deploy on HoloLens:

  1. 必要になります、HoloLens の IP アドレス (リモート) を展開し、HoloLens をことを確認するには開発者モードします。You will need the IP Address of your HoloLens (for Remote Deploy), and to ensure your HoloLens is in Developer Mode. これには、次の手順を実行します。To do this:

    1. ソックスを着けずに、HoloLens 中を開く、設定します。Whilst wearing your HoloLens, open the Settings.

    2. 移動してネットワークとインターネット > Wi-fi > 詳細オプションGo to Network & Internet > Wi-Fi > Advanced Options

    3. 注、 IPv4アドレス。Note the IPv4 address.

    4. 次に移動します設定、し更新とセキュリティ > 開発者向けNext, navigate back to Settings, and then to Update & Security > For Developers

    5. 設定で開発者モードします。Set Developer Mode On.

  2. 新しい Unity ビルドに移動します (、アプリフォルダー) とソリューション ファイルを開くとVisual Studioします。Navigate to your new Unity build (the App folder) and open the solution file with Visual Studio.

  3. ソリューション構成選択デバッグします。In the Solution Configuration select Debug.

  4. ソリューション プラットフォームx86、リモート コンピューターします。In the Solution Platform, select x86, Remote Machine. 挿入を求め、 IP アドレスのリモート デバイス (、HoloLens、ここでは、メモしたもの)。You will be prompted to insert the IP address of a remote device (the HoloLens, in this case, which you noted).

  5. 移動してビルドメニューをクリックしますソリューションの配置サイドロード、HoloLens をアプリケーションにします。Go to Build menu and click on Deploy Solution to sideload the application to your HoloLens.

  6. アプリが、起動する準備ができて、HoloLens にインストールされているアプリの一覧に表示されます。Your app should now appear in the list of installed apps on your HoloLens, ready to be launched!

注意

イマーシブ ヘッドセットを展開するには、設定、ソリューション プラットフォームローカル マシン、設定と、構成デバッグx86として、プラットフォームします。To deploy to immersive headset, set the Solution Platform to Local Machine, and set the Configuration to Debug, with x86 as the Platform. ローカルにデプロイし、machine を使用して、ビルドメニュー項目を選択するとソリューションの配置します。Then deploy to the local machine, using the Build menu item, selecting Deploy Solution.

アプリケーションを使用します。To use the application:

アプリの機能との間を切り替えるトレーニングモードと予測モードを更新する必要がある、 AppMode変数にある、 Awake() 内にあるメソッド、 ImageCaptureクラス。To switch the app functionality between Training mode and Prediction mode you need to update the AppMode variable, located in the Awake() method located within the ImageCapture class.

        // Change this flag to switch between Analysis mode and Training mode 
        AppMode = AppModes.Training;

またはor

        // Change this flag to switch between Analysis mode and Training mode 
        AppMode = AppModes.Analysis;

トレーニングモード。In Training mode:

  • 見てマウスまたはキーボードを使用して、タップ ジェスチャします。Look at Mouse or Keyboard and use the Tap gesture.

  • 次に、テキストは、タグを指定するように求める表示されます。Next, text will appear asking you to provide a tag.

  • どちらかマウスまたはキーボードします。Say either Mouse or Keyboard.

予測モード。In Prediction mode:

  • オブジェクトを確認し、使用、タップ ジェスチャします。Look at an object and use the Tap gesture.

  • 検出されると、確率が最も高い (これは正規化されます) オブジェクトを提供するテキストが表示されます。Text will appear providing the object detected, with the highest probability (this is normalized).

14 -」の章を評価し、カスタム ビジョン モデルを改善Chapter 14 - Evaluate and improve your Custom Vision model

サービスをより正確なことには、予測に使用するモデルのトレーニングに続行する必要があります。To make your Service more accurate, you will need to continue to train the model used for prediction. 両方で、新しいアプリケーションを使用して、これは、トレーニング予測モード、後者を必要とすると、ポータルでは、この章の内容を参照してください。This is accomplished through using your new application, with both the training and prediction modes, with the latter requiring you to visit the portal, which is what is covered in this Chapter. 何度も、ポータルを見直し、モデルを継続的に向上させるために準備してください。Be prepared to revisit your portal many times, to continually improve your model.

  1. Azure Custom Vision ポータルにもう一度、head し、プロジェクトでは、選択、予測(からページの上部中央) タブ。Head to your Azure Custom Vision Portal again, and once you are in your project, select the Predictions tab (from the top center of the page):

  2. アプリケーションの実行中に、サービスに送信されたすべてのイメージが表示されます。You will see all the images which were sent to your Service whilst your application was running. イメージをポイントする場合は、そのイメージに対して行われた予測の提供は。If you hover over the images, they will provide you with the predictions that were made for that image:

  3. イメージを開くことのいずれかを選択します。Select one of your images to open it. 開いている場合とは、そのイメージの右側に行われた予測が表示されます。Once open, you will see the predictions made for that image to the right. 予測が正しいこと、およびサービスのモデルのトレーニングにこのイメージを追加するには、をクリックした場合、マイ タグ入力ボックス、およびに関連付けるタグを選択します。If you the predictions were correct, and you wish to add this image to your Service's training model, click the My Tags input box, and select the tag you wish to associate. 完了したら、クリックして、を保存して閉じます右、下にボタンをクリックし、次のイメージを続行します。When you are finished, click the Save and close button to the bottom right, and continue on to the next image.

  4. イメージのグリッドに表示されたら、イメージにタグを追加 (して保存した)、これが表示されますは削除されます。Once you are back to the grid of images, you will notice the images which you have added tags to (and saved), will be removed. それらに含まれるタグが付けられた、項目がないと思われる任意のイメージを検索する場合は、(ようイメージがいくつかの) そのイメージに目盛りをクリックし、をクリックして削除することは、できる削除グリッド ページの右上隅にします。If you find any images which you think do not have your tagged item within them, you can delete them, by clicking the tick on that image (can do this for several images) and then clicking Delete in the upper right corner of the grid page. 次のポップアップで、いずれかをクリックできますはい、削除またはいいえ削除の確認またはキャンセルするか、それぞれをします。On the popup that follows, you can click either Yes, delete or No, to confirm the deletion or cancel it, respectively.

  5. 続行する準備ができたら、緑をクリックします。トレーニング右上のボタンをクリックします。When you are ready to proceed, click the green Train button in the top right. すべてのイメージと指定したようになりましたが (これによりより正確な)、サービス モデルがトレーニングされます。Your Service model will be trained with all the images which you have now provided (which will make it more accurate). トレーニングが完了すると作成 をクリックすることを確認して、既定、もう一度ボタンをクリックしてように、予測 URLは、サービスの最新のイテレーションを使用し続けます。Once the training is complete, make sure to click the Make default button once more, so that your Prediction URL continues to use the most up-to-date iteration of your Service.

完成した Custom Vision API アプリケーションYour finished Custom Vision API application

これで、現実世界のオブジェクトを認識する、サービス モデルのトレーニングおよび内容は、発生の信頼度を表示する Azure の Custom Vision API を利用している mixed reality アプリを構築します。Congratulations, you built a mixed reality app that leverages the Azure Custom Vision API to recognize real world objects, train the Service model, and display confidence of what has been seen.

ボーナスの演習Bonus exercises

手順 1Exercise 1

トレーニング、 Custom Vision Serviceを複数のオブジェクトを認識します。Train your Custom Vision Service to recognize more objects.

手順 2Exercise 2

学習した内容を展開する方法、として次の演習を行います。As a way to expand on what you have learned, complete the following exercises:

オブジェクトが認識されると、サウンドを再生します。Play a sound when an object is recognized.

手順 3Exercise 3

API を使用して、アプリの分析は、同じイメージのサービスの再トレーニングに、そのため、サービスをより正確に (予測と同時にトレーニングを行う)。Use the API to re-train your Service with the same images your app is analyzing, so to make the Service more accurate (do both prediction and training simultaneously).