Mr und Azure 310: ObjekterkennungMr and Azure 310: Object detection

Hinweis

Die Tutorials der Mixed Reality Academy wurden im Hinblick auf HoloLens (1. Gen.) und immersive Mixed Reality-Headsets entworfen.The Mixed Reality Academy tutorials were designed with HoloLens (1st gen) and Mixed Reality Immersive Headsets in mind. Daher halten wir es für wichtig, diese Tutorials für Entwickler verfügbar zu halten, die noch nach Anleitung beim Entwickeln für diese Geräte suchen.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. Diese Tutorials werden nicht mit den neuesten Toolsets oder Interaktionen aktualisiert, die für HoloLens 2 verwendet werden.These tutorials will not be updated with the latest toolsets or interactions being used for HoloLens 2. Sie werden gewartet, um weiterhin auf den unterstützten Geräten zu funktionieren.They will be maintained to continue working on the supported devices. Es gibt eine neue Reihe von Tutorials, die in Zukunft veröffentlicht werden, um die Entwicklung für hololens 2 zu veranschaulichen.There will be a new series of tutorials that will be posted in the future that will demonstrate how to develop for HoloLens 2. Dieser Hinweis wird mit einem Link zu diesen Tutorials aktualisiert, wenn diese veröffentlicht werden.This notice will be updated with a link to those tutorials when they are posted.


In diesem Kurs erfahren Sie, wie Sie benutzerdefinierte visuelle Inhalte und deren räumliche Position in einem bereitgestellten Image erkennen können, indem Sie Azure Custom Vision "Objekt Erkennungsfunktionen" in einer Mixed Reality-Anwendung verwenden.In this course, you will learn how to recognize custom visual content and its spatial position within a provided image, using Azure Custom Vision "Object Detection" capabilities in a mixed reality application.

Mit diesem Dienst können Sie ein Machine Learning-Modell mithilfe von Objekt Images trainieren.This service will allow you to train a machine learning model using object images. Anschließend verwenden Sie das trainierte Modell, um ähnliche Objekte zu erkennen und einander in der realen Welt zu erkennen, wie von der Kamera Erfassung von Microsoft hololens oder einer Kamera mit einem PC für immersive (VR)-Headsets bereitgestellt wird.You will then use the trained model to recognize similar objects and approximate their location in the real world, as provided by the camera capture of Microsoft HoloLens or a camera connect to a PC for immersive (VR) headsets.

Kurs Ergebnis

Azure-Custom Vision, Objekterkennung ist ein Microsoft-Dienst, mit dem Entwickler benutzerdefinierte Abbild Klassifizierungen erstellen können.Azure Custom Vision, Object Detection is a Microsoft Service which allows developers to build custom image classifiers. Diese Klassifizierungen können dann mit neuen Bildern verwendet werden, um Objekte innerhalb dieses neuen Bilds zu erkennen, indem Sie die Feld Begrenzungen innerhalb des Bilds selbst bereitstellen.These classifiers can then be used with new images to detect objects within that new image, by providing Box Boundaries within the image itself. Der Dienst bietet ein einfaches, leicht zu verwendende Onlineportal, um diesen Prozess zu optimieren.The Service provides a simple, easy to use, online portal to streamline this process. Weitere Informationen finden Sie unter den folgenden Links:For more information, visit the following links:

Nach Abschluss dieses Kurses verfügen Sie über eine Mixed Reality-Anwendung, die Folgendes ausführen kann:Upon completion of this course, you will have a mixed reality application which will be able to do the following:

  1. Der Benutzer ist in der Lage, ein Objekt zu sehen , das Sie mithilfe des Azure-Custom Vision Service (Objekterkennung) trainiert haben.The user will be able to gaze at an object, which they have trained using the Azure Custom Vision Service, Object Detection.
  2. Der Benutzer verwendet die Tap -Geste, um ein Bild von dem zu erfassenden Bild zu erfassen.The user will use the Tap gesture to capture an image of what they are looking at.
  3. Die APP sendet das Image an den Azure-Custom Vision Service.The app will send the image to the Azure Custom Vision Service.
  4. Es wird eine Antwort vom Dienst angezeigt, die das Ergebnis der Erkennung als Welt Raum Text anzeigt.There will be a reply from the Service which will display the result of the recognition as world-space text. Dies wird durch die Verwendung der räumlichen Nachverfolgung von Microsoft hololens erreicht, um die Weltposition des erkannten Objekts zu verstehen, und dann das Tag zu verwenden, das den im Bild erkannten Werten zugeordnet ist, um den Bezeichnungs Text bereitzustellen.This will be accomplished through utilizing the Microsoft HoloLens' Spatial Tracking, as a way of understanding the world position of the recognized object, and then using the Tag associated with what is detected in the image, to provide the label text.

Der Kurs umfasst auch das manuelle Hochladen von Bildern, das Erstellen von Tags und das Trainieren des Dienstanbieter, um verschiedene Objekte (im bereitgestellten Beispiel a Cup) zu erkennen, indem das Begrenzungsfeld innerhalb des Abbilds festgelegt wird, das Sie senden.The course will also cover manually uploading images, creating tags, and training the Service, to recognize different objects (in the provided example, a cup), by setting the Boundary Box within the image you submit.

Wichtig

Nach der Erstellung und Verwendung der APP sollte der Entwickler zurück zum Azure-Custom Vision Service navigieren, die vom Dienst vorgenommenen Vorhersagen ermitteln und ermitteln, ob Sie richtig waren, oder nicht (durch Tagging, was der Dienst verpasst hat, und Anpassen der Begrenzungs Felder).Following the creation and use of the app, the developer should navigate back to the Azure Custom Vision Service, and identify the predictions made by the Service, and determine whether they were correct or not (through tagging anything the Service missed, and adjusting the Bounding Boxes). Der Dienst kann dann neu trainiert werden, wodurch die Wahrscheinlichkeit erhöht wird, dass reale Objekte erkannt werden.The Service can then be re-trained, which will increase the likelihood of it recognizing real world objects.

In diesem Kurs erfahren Sie, wie Sie die Ergebnisse aus dem Azure-Custom Vision Service, Objekterkennung, in einer Unity-basierten Beispielanwendung erhalten.This course will teach you how to get the results from the Azure Custom Vision Service, Object Detection, into a Unity-based sample application. Sie müssen diese Konzepte auf eine benutzerdefinierte Anwendung anwenden, die Sie möglicherweise aufbauen.It will be up to you to apply these concepts to a custom application you might be building.

GeräteunterstützungDevice support

KursCourse HoloLensHoloLens Immersive HeadsetsImmersive headsets
MR und Azure 310: ObjekterkennungMR and Azure 310: Object detection ✔️✔️

VoraussetzungenPrerequisites

Hinweis

Dieses Tutorial richtet sich an Entwickler, die über grundlegende Kenntnisse in Unity und c# verfügen.This tutorial is designed for developers who have basic experience with Unity and C#. Beachten Sie auch, dass die Voraussetzungen und Anweisungen in diesem Dokument darstellen, was zum Zeitpunkt des Schreibens getestet und überprüft wurde (Juli 2018).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). Sie können die neueste Software verwenden, die im Artikel Installieren der Tools aufgeführt ist. es sollte jedoch nicht davon ausgegangen werden, dass die Informationen in diesem Kurs genau mit den Informationen in neueren Software vergleichen, als im folgenden aufgeführt werden.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.

Für diesen Kurs empfehlen wir die folgende Hardware und Software:We recommend the following hardware and software for this course:

VorbereitungBefore you start

  1. Um Probleme zu vermeiden, die beim Erstellen dieses Projekts auftreten, wird dringend empfohlen, dass Sie das in diesem Tutorial erwähnte Projekt in einem Stamm Ordner oder in einem Ordner mit einem Stamm Ordner erstellen (lange Ordner Pfade können zur Buildzeit Probleme verursachen).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. Richten Sie Ihre hololens ein, und testen Sie Sie.Set up and test your HoloLens. Wenn Sie Unterstützung für die Einrichtung ihrer hololens benötigen, besuchen Sie den Artikel zum Einrichten von hololens.If you need support setting up your HoloLens, make sure to visit the HoloLens setup article.
  3. Es empfiehlt sich, eine Kalibrierung und Sensor Optimierung durchzuführen, wenn Sie mit der Entwicklung einer neuen hololens-App beginnen (manchmal kann es hilfreich sein, diese Aufgaben für jeden Benutzer auszuführen).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).

Hilfe zur Kalibrierung finden Sie unter diesem Link zum Artikel zur hololens-Kalibrierung.For help on Calibration, please follow this link to the HoloLens Calibration article.

Hilfe zur Sensor Optimierung finden Sie unter diesem Link zum Artikel zur Überwachung von hololens-Sensoren.For help on Sensor Tuning, please follow this link to the HoloLens Sensor Tuning article.

Kapitel 1: das Custom Vision-PortalChapter 1 - The Custom Vision Portal

Um das Azure-Custom Vision Service verwenden zu können, müssen Sie eine Instanz von der Anwendung so konfigurieren, dass Sie Ihrer Anwendung zur Verfügung gestellt wird.To use the Azure Custom Vision Service, you will need to configure an instance of it to be made available to your application.

  1. Navigieren Sie zur Custom Vision Service Hauptseite.Navigate to the Custom Vision Service main page.

  2. Klicken Sie auf " Getting Started".Click on Getting Started.

  3. Melden Sie sich beim Custom Vision-Portal an.Sign in to the Custom Vision Portal.

  4. Wenn Sie noch nicht über ein Azure-Konto verfügen, müssen Sie eines erstellen.If you do not already have an Azure account, you will need to create one. Wenn Sie dieses Tutorial in einer Classroom-oder Lab-Situation befolgen, bitten Sie Ihren Dozenten oder einen der Proctors, Hilfe beim Einrichten Ihres neuen Kontos zu erhalten.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.

  5. Wenn Sie sich zum ersten Mal angemeldet haben, werden Sie im Bereich mit den Nutzungsbedingungen aufgefordert.Once you are logged in for the first time, you will be prompted with the Terms of Service panel. Aktivieren Sie das Kontrollkästchen, um den Bedingungen zuzustimmen.Click the checkbox to agree to the terms. Klicken Sie dann auf Ich stimme zu.Then click I agree.

  6. Nachdem Sie die Bedingungen zugestimmt haben, befinden Sie sich jetzt im Abschnitt " Meine Projekte ".Having agreed to the terms, you are now in the My Projects section. Klicken Sie auf Neues Projekt.Click on New Project.

  7. Eine Registerkarte wird auf der rechten Seite angezeigt, auf der Sie aufgefordert werden, einige Felder für das Projekt anzugeben.A tab will appear on the right-hand side, which will prompt you to specify some fields for the project.

    1. Fügen Sie einen Namen für Ihr Projekt ein.Insert a name for your project

    2. Fügen Sie eine Beschreibung für das Projekt ein (optional).Insert a description for your project (Optional)

    3. Wählen Sie eine Ressourcengruppe aus, oder erstellen Sie eine neue Ressourcengruppe .Choose a Resource Group or create a new one. Eine Ressourcengruppe bietet eine Möglichkeit zum überwachen, Steuern des Zugriffs, bereitstellen und Verwalten der Abrechnung für eine Sammlung von Azure-Ressourcen.A resource group provides a way to monitor, control access, provision and manage billing for a collection of Azure assets. Es wird empfohlen, alle Azure-Dienste, die einem einzelnen Projekt (z. b. diesen Kursen) zugeordnet sind, in einer gemeinsamen Ressourcengruppe zu speichern.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. Legen Sie die Projekttypen als Objekterkennung (Vorschauversion) fest.Set the Project Types as Object Detection (preview).

  8. Wenn Sie fertig sind, klicken Sie auf Projekt erstellen, und Sie werden auf die Seite Custom Vision Service Projekt umgeleitet.Once you are finished, click on Create project, and you will be redirected to the Custom Vision Service project page.

Kapitel 2: trainieren Ihres Custom Vision ProjektsChapter 2 - Training your Custom Vision project

Wenn Sie sich im Custom Vision Portal befinden, besteht das Hauptziel darin, das Projekt zu trainieren, um bestimmte Objekte in Bildern zu erkennen.Once in the Custom Vision Portal, your primary objective is to train your project to recognize specific objects in images.

Sie benötigen mindestens 15 (15) Images für jedes Objekt, das von Ihrer Anwendung erkannt werden soll.You need at least fifteen (15) images for each object that you would like your application to recognize. Sie können die Bilder verwenden, die mit diesem Kurs bereitgestellt werden (eine Reihe von Tassen).You can use the images provided with this course (a series of cups).

So trainieren Sie das Custom Vision Projekt:To train your Custom Vision project:

  1. Klicken Sie auf die + Schaltfläche neben Tags.Click on the + button next to Tags.

  2. Fügen Sie einen Namen für das Tag hinzu, mit dem die Bilder verknüpft werden.Add a name for the tag that will be used to associate your images with. In diesem Beispiel verwenden wir Bilder von Tassen für die Erkennung, benennen Sie also das-Tag für this, Cup.In this example we are using images of cups for recognition, so have named the tag for this, Cup. Klicken Sie abschließend auf Speichern .Click Save once finished.

  3. Sie werden feststellen, dass Ihr Tag hinzugefügt wurde (möglicherweise müssen Sie die Seite erneut laden, damit es angezeigt wird).You will notice your Tag has been added (you may need to reload your page for it to appear).

  4. Klicken Sie in der Mitte der Seite auf Bilder hinzufügen .Click on Add images in the center of the page.

  5. Klicken Sie auf lokale Dateien durchsuchen, und navigieren Sie zu den Images, die Sie für ein Objekt hochladen möchten, das mindestens 15 (15) ist.Click on Browse local files, and browse to the images you would like to upload for one object, with the minimum being fifteen (15).

    Tipp

    Sie können mehrere Bilder gleichzeitig zum Hochladen auswählen.You can select several images at a time, to upload.

  6. Wenn Sie alle Images ausgewählt haben, mit denen Sie das Projekt trainieren möchten, klicken Sie auf Dateien hochladen .Press Upload files once you have selected all the images you would like to train the project with. Die Dateien werden hochgeladen.The files will begin uploading. Nachdem Sie den Upload bestätigt haben, klicken Sie auf done.Once you have confirmation of the upload, click Done.

  7. An diesem Punkt werden die Images hochgeladen, aber nicht markiert.At this point your images are uploaded, but not tagged.

  8. Verwenden Sie die Maus, um die Bilder zu markieren.To tag your images, use your mouse. Wenn Sie mit dem Mauszeiger auf das Bild zeigen, werden Sie durch eine Auswahl Markierung unterstützt, indem Sie automatisch eine Auswahl um das Objekt ziehen.As you hover over your image, a selection highlight will aid you by automatically drawing a selection around your object. Wenn dies nicht zutrifft, können Sie eigene zeichnen.If it is not accurate, you can draw your own. Dies wird erreicht, indem Sie mit der linken Maustaste auf die Maus klicken und den Auswahlbereich auf das Objekt ziehen.This is accomplished by holding left-click on the mouse, and dragging the selection region to encompass your object.

  9. Nach der Auswahl des Objekts innerhalb des Bilds wird eine kleine Aufforderung aufgefordert, das Regions- Tag hinzuzufügen.Following the selection of your object within the image, a small prompt will ask for you to Add Region Tag. Wählen Sie das zuvor erstellte Tag ("Cup", im obigen Beispiel) aus, oder wenn Sie weitere Tags hinzufügen, geben Sie dieses in ein, und klicken Sie auf die Schaltfläche + (plus) .Select your previously created tag ('Cup', in the above example), or if you are adding more tags, type that in and click the + (plus) button.

  10. Um das nächste Bild zu markieren, klicken Sie auf den Pfeil rechts neben dem Blatt, oder schließen Sie das Tag-Blatt (durch Klicken auf das X in der oberen rechten Ecke des Blatts), und klicken Sie dann auf das nächste Bild.To tag the next image, you can click the arrow to the right of the blade, or close the tag blade (by clicking the X in the top-right corner of the blade) and then click the next image. Wenn Sie das nächste Bild bereit haben, wiederholen Sie das gleiche Verfahren.Once you have the next image ready, repeat the same procedure. Führen Sie diese Schritte für alle Images aus, die Sie hochgeladen haben, bis Sie alle gekennzeichnet sind.Do this for all the images you have uploaded, until they are all tagged.

    Hinweis

    Sie können mehrere Objekte im gleichen Bild auswählen, wie in der folgenden Abbildung dargestellt:You can select several objects in the same image, like the image below:

  11. Wenn Sie alle markiert haben, klicken Sie auf der linken Seite des Bildschirms auf die markierte Schaltfläche, um die markierten Bilder anzuzeigen.Once you have tagged them all, click on the tagged button, on the left of the screen, to reveal the tagged images.

  12. Sie sind jetzt bereit, ihren Dienst zu trainieren.You are now ready to train your Service. Klicken Sie auf die Schaltfläche trainieren , und die erste Trainings Iterationen wird gestartet.Click the Train button, and the first training iteration will begin.

  13. Nachdem Sie erstellt wurde, können Sie zwei Schaltflächen mit dem Namen " default " und die Vorhersage-URL anzeigen.Once it is built, you will be able to see two buttons called Make default and Prediction URL. Klicken Sie zuerst auf Standardwert erstellen , und klicken Sie dann auf Vorhersage-URL.Click on Make default first, then click on Prediction URL.

    Hinweis

    Der Endpunkt, der aus diesem bereitgestellt wird, wird auf den Wert festgelegt, welcher iterations Wert als Standard markiert wurde.The endpoint which is provided from this, is set to whichever Iteration has been marked as default. Wenn Sie später eine neue iterations Zeit erstellen und diese als Standard aktualisieren, müssen Sie den Code nicht ändern.As such, if you later make a new Iteration and update it as default, you will not need to change your code.

  14. Nachdem Sie auf die Vorhersage-URL geklickt haben, öffnen Sie den Editor, und kopieren Sie die URL (auch als Vorhersage Endpunkt bezeichnet) und den Dienst Vorhersage Schlüssel, um Sie abzurufen, wenn Sie Sie später im Code benötigen.Once you have clicked on Prediction URL, open Notepad, and copy and paste the URL (also called your Prediction-Endpoint) and the Service Prediction-Key, so that you can retrieve it when you need it later in the code.

Kapitel 3: Einrichten des Unity-ProjektsChapter 3 - Set up the Unity project

Folgendes ist eine typische Einrichtung für die Entwicklung mit gemischter Realität und ist daher eine gute Vorlage für andere Projekte.The following is a typical set up for developing with mixed reality, and as such, is a good template for other projects.

  1. Öffnen Sie Unity , und klicken Sie auf neu.Open Unity and click New.

  2. Sie müssen nun einen Unity-Projektnamen angeben.You will now need to provide a Unity project name. Fügen Sie customvisionobjerkennung ein.Insert CustomVisionObjDetection. Stellen Sie sicher, dass der Projekttyp auf 3D festgelegt ist, und legen Sie den Speicherort auf einen passenden Wert fest (denken Sie daran, dass die Stamm Verzeichnisse besser sind).Make sure the project type is set to 3D, and set the Location to somewhere appropriate for you (remember, closer to root directories is better). Klicken Sie dann auf Projekt erstellen.Then, click Create project.

  3. Wenn Unity geöffnet ist, sollten Sie überprüfen, dass der Standard Skript-Editor auf Visual Studio festgelegt ist.With Unity open, it is worth checking the default Script Editor is set to Visual Studio. Wechseln Sie zu * > Einstellungen bearbeiten* , und navigieren Sie dann im neuen Fenster zu externe Tools.Go to Edit > Preferences and then from the new window, navigate to External Tools. Ändern Sie den Editor für externe Skripts in Visual Studio.Change External Script Editor to Visual Studio. Schließen Sie das Fenster " Einstellungen ".Close the Preferences window.

  4. Navigieren Sie als nächstes zu Datei > Buildeinstellungen , und wechseln Sie zur Plattform universelle Windows-Plattform, und klicken Sie dann auf die Schaltfläche Plattform wechseln .Next, go to File > Build Settings and switch the Platform to Universal Windows Platform, and then clicking on the Switch Platform button.

  5. Vergewissern Sie sich, dass im gleichen Fenster mit den Buildeinstellungen Folgendes festgelegt ist:In the same Build Settings window, ensure the following are set:

    1. Zielgerät ist auf hololens festgelegtTarget Device is set to HoloLens

    2. Der Buildtyp ist auf D3D festgelegt.Build Type is set to D3D

    3. SDK ist auf neueste installierte Version festgelegt.SDK is set to Latest installed

    4. Visual Studio-Version ist auf neueste installierte Version festgelegt.Visual Studio Version is set to Latest installed

    5. Build und Run sind auf lokaler Computer festgelegt.Build and Run is set to Local Machine

    6. Die restlichen Einstellungen in den Buildeinstellungen sollten vorerst als Standard belassen werden.The remaining settings, in Build Settings, should be left as default for now.

  6. Klicken Sie im gleichen Fenster mit den Buildeinstellungen auf die Schaltfläche Player Einstellungen . Dadurch wird der entsprechende Bereich in dem Bereich geöffnet, in dem sich der Inspektor befindet.In the same 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 diesem Bereich müssen einige Einstellungen überprüft werden:In this panel, a few settings need to be verified:

    1. Auf der Registerkarte andere Einstellungen :In the Other Settings tab:

      1. Die CLR- Lauf Zeit Version sollte experimentell sein (.NET 4,6-Entsprechung), wodurch der Editor neu gestartet werden muss.Scripting Runtime Version should be Experimental (.NET 4.6 Equivalent), which will trigger a need to restart the Editor.

      2. Das Skript für die Skript Erstellung sollte .net sein.Scripting Backend should be .NET.

      3. Der API-Kompatibilitäts Grad sollte .NET 4,6 lauten.API Compatibility Level should be .NET 4.6.

    2. Überprüfen Sie auf der Registerkarte Veröffentlichungs Einstellungen unter Funktionen Folgendes:Within the Publishing Settings tab, under Capabilities, check:

      1. InternetClientInternetClient

      2. WebcamWebcam

      3. SpatialPerceptionSpatialPerception

    3. Weiter unten im Bereich können Sie in den XR-Einstellungen (siehe Veröffentlichungs Einstellungen) die unterstützte Tick Virtual Reality und dann sicherstellen, dass das Windows Mixed Reality SDK hinzugefügt wurde.Further down the panel, in XR Settings (found below Publish Settings), tick Virtual Reality Supported, then make sure the Windows Mixed Reality SDK is added.

  8. Zurück in den Buildeinstellungen: Unity C- # Projekte sind nicht mehr abgeblendet: Aktivieren Sie das Kontrollkästchen neben this.Back in Build Settings, Unity C# Projects is no longer greyed out: tick the checkbox next to this.

  9. Schließen Sie das Fenster Buildeinstellungen.Close the Build Settings window.

  10. Klicken Sie im Editor auf > Projekt Einstellungs > Grafik bearbeiten.In the Editor, click on Edit > Project Settings > Graphics.

  11. Im Inspektor -Bereich werden die Grafikeinstellungen geöffnet.In the Inspector Panel the Graphics Settings will be open. Scrollen Sie nach unten, bis Sie ein Array mit der Bezeichnung Always include-Shader sehen.Scroll down until you see an array called Always Include Shaders. Fügen Sie einen Slot hinzu, indem Sie die Größen Variable um eins erhöhen (in diesem Beispiel war es 8, daher haben wir es 9).Add a slot by increasing the Size variable by one (in this example, it was 8 so we made it 9). Ein neuer Slot wird an der letzten Position des Arrays angezeigt, wie unten dargestellt:A new slot will appear, in the last position of the array, as shown below:

  12. Klicken Sie im Slot auf den kleinen Zielkreis neben dem Slot, um eine Liste der Shader zu öffnen.In the slot, click on the small target circle next to the slot to open a list of shaders. Suchen Sie nach dem Legacy-Shader " Shaders/transparent/diffuser ", und doppelklicken Sie darauf.Look for the Legacy Shaders/Transparent/Diffuse shader and double-click it.

Kapitel 4: Importieren des Unity-Pakets "customvisionobjerkennung"Chapter 4 - Importing the CustomVisionObjDetection Unity package

Für diesen Kurs erhalten Sie ein Unity-Ressourcenpaket mit dem Namen " Azure-Mr-310. unitypackage".For this course you are provided with a Unity Asset Package called Azure-MR-310.unitypackage.

PP Alle Objekte, die von Unity unterstützt werden, einschließlich ganzer Szenen, können in eine . unitypackage -Datei gepackt und in andere Projekte exportiert/importiert werden.[TIP] Any objects supported by Unity, including entire scenes, can be packaged into a .unitypackage file, and exported / imported in other projects. Dies ist die sicherste und effizienteste Methode zum Verschieben von Ressourcen zwischen verschiedenen Unity- Projekten.It is the safest, and most efficient, way to move assets between different Unity projects.

Sie finden das Azure-Mr-310-Paket, das Sie hier herunterladen müssen.You can find the Azure-MR-310 package that you need to download here.

  1. Klicken Sie oben auf dem Bildschirm mit dem Unity-Dashboard auf Assets , und klicken Sie dann auf Paket > benutzerdefiniertes Paket importieren.With the Unity dashboard in front of you, click on Assets in the menu at the top of the screen, then click on Import Package > Custom Package.

  2. Wählen Sie mit der Dateiauswahl das Paket Azure-Mr-310. unitypackage aus, und klicken Sie auf Öffnen.Use the file picker to select the Azure-MR-310.unitypackage package and click Open. Eine Liste der Komponenten für dieses Asset wird angezeigt.A list of components for this asset will be displayed to you. Bestätigen Sie den Import, indem Sie auf die Schaltfläche importieren klicken.Confirm the import by clicking the Import button.

  3. Nachdem der Import abgeschlossen wurde, werden Sie feststellen, dass dem Ordner " Assets " nun Ordner aus dem Paket hinzugefügt wurden.Once it has finished importing, you will notice that folders from the package have now been added to your Assets folder. Diese Art von Ordnerstruktur ist typisch für ein Unity-Projekt.This kind of folder structure is typical for a Unity project.

    1. Der Material-Ordner enthält das Material, das vom Cursor Cursor verwendet wird.The Materials folder contains the material used by the Gaze Cursor.

    2. Der Ordner Plug -in enthält die newtonsoft-dll, die vom Code zum Deserialisieren der Webantwort des Diensts verwendet wird.The Plugins folder contains the Newtonsoft DLL used by the code to deserialize the Service web response. Die zwei (2) verschiedenen Versionen, die im Ordner und Unterordner enthalten sind, sind erforderlich, damit die Bibliothek vom Unity-Editor und dem UWP-Build verwendet und erstellt werden kann.The two (2) different versions contained in the folder, and sub-folder, are necessary to allow the library to be used and built by both the Unity Editor and the UWP build.

    3. Der Ordner " Prefabs " enthält die in der Szene enthaltenen Prefabs.The Prefabs folder contains the prefabs contained in the scene. Dazu zählen:Those are:

      1. Der gazecursor, der Cursor, der in der Anwendung verwendet wird.The GazeCursor, the cursor used in the application. Wird zusammen mit der spatialmapping-präfab verwendet, um auf der Grundlage physischer Objekte in der Szene platziert werden zu können.Will work together with the SpatialMapping prefab to be able to be placed in the scene on top of physical objects.
      2. Die Bezeichnung, die das UI-Objekt ist, das verwendet wird, um bei Bedarf das Objekttag in der Szene anzuzeigen.The Label, which is the UI object used to display the object tag in the scene when required.
      3. Die spatialmapping, bei der es sich um das Objekt handelt, das es der Anwendung ermöglicht, eine virtuelle Karte mithilfe der räumlichen Nachverfolgung von Microsoft hololens zu verwenden.The SpatialMapping, which is the object that enables the application to use create a virtual map, using the Microsoft HoloLens' spatial tracking.
    4. Der Ordner Szenen , der derzeit die vorgefertigte Szene für diesen Kurs enthält.The Scenes folder which currently contains the pre-built scene for this course.

  4. Öffnen Sie im Projekt Panel den Ordner Szenen , und doppelklicken Sie auf objdetectionscene, um die Szene zu laden, die Sie für diesen Kurs verwenden werden.Open the Scenes folder, in the Project Panel, and double-click on the ObjDetectionScene, to load the scene that you will use for this course.

    Hinweis

    Es ist kein Code enthalten. Sie schreiben den Code, indem Sie diesen Kurs befolgen.No code is included, you will write the code by following this course.

Kapitel 5: Erstellen der customvisionanalyser-Klasse.Chapter 5 - Create the CustomVisionAnalyser class.

An diesem Punkt können Sie Code schreiben.At this point you are ready to write some code. Sie beginnen mit der customvisionanalyser -Klasse.You will begin with the CustomVisionAnalyser class.

Hinweis

Die Aufrufe an die Custom Vision Service, die im unten gezeigten Code vorgenommen wurden, werden mithilfe der Custom Vision Rest-API vorgenommen.The calls to the Custom Vision Service, made in the code shown below, are made using the Custom Vision REST API. Durch die Verwendung dieser API sehen Sie, wie Sie diese API implementieren und nutzen können (nützlich, um zu verstehen, wie Sie etwas ähnliches implementieren können).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). Beachten Sie, dass Microsoft ein Custom Vision SDK bietet, das auch zum Aufrufen des Dienstanbieter verwendet werden kann.Be aware, that Microsoft offers a Custom Vision SDK that can also be used to make calls to the Service. Weitere Informationen finden Sie im Custom Vision SDK-Artikel.For more information visit the Custom Vision SDK article.

Diese Klasse ist für Folgendes zuständig:This class is responsible for:

  • Das letzte als Bytearray erfasste Bild wird geladen.Loading the latest image captured as an array of bytes.

  • Das Bytearray wird zur Analyse an Ihre Azure Custom Vision Service -Instanz gesendet.Sending the byte array to your Azure Custom Vision Service instance for analysis.

  • Die Antwort wird als JSON-Zeichenfolge empfangen.Receiving the response as a JSON string.

  • Deserialisieren der Antwort und übergeben der resultierenden Vorhersage an die sceneorganisator -Klasse, um die Anzeige der Antwort zu übernehmen.Deserializing the response and passing the resulting Prediction to the SceneOrganiser class, which will take care of how the response should be displayed.

So erstellen Sie diese Klasse:To create this class:

  1. Klicken Sie im Projekt Panel mit der rechten Maustaste in den Ordner Asset, und klicken Sie dann auf > Ordner erstellen.Right-click in the Asset Folder, located in the Project Panel, then click Create > Folder. Nennen Sie die Ordner Skripts.Call the folder Scripts.

  2. Doppelklicken Sie auf den neu erstellten Ordner, um ihn zu öffnen.Double-click on the newly created folder, to open it.

  3. Klicken Sie mit der rechten Maustaste in den Ordner , und klicken Sie dann auf > # Skript erstellen.Right-click inside the folder, then click Create > C# Script. Benennen Sie das Skript customvisionanalyser.Name the script CustomVisionAnalyser.

  4. Doppelklicken Sie auf das neue customvisionanalyser -Skript, um es in Visual Studio zu öffnen.Double-click on the new CustomVisionAnalyser script to open it with Visual Studio.

  5. Stellen Sie sicher, dass am Anfang der Datei die folgenden Namespaces referenziert sind:Make sure you have the following namespaces referenced at the top of the file:

    using Newtonsoft.Json;
    using System.Collections;
    using System.IO;
    using UnityEngine;
    using UnityEngine.Networking;
    
  6. Fügen Sie in der customvisionanalyser -Klasse die folgenden Variablen hinzu: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>
        /// Bite array of the image to submit for analysis
        /// </summary>
        [HideInInspector] public byte[] imageBytes;
    

    Hinweis

    Stellen Sie sicher, dass Sie den Dienst Vorhersage-Key in die " prätionkey "-Variable und ihren Vorhersage Endpunkt in die " prätionendpoint "-Variable einfügenMake sure you insert your Service Prediction-Key into the predictionKey variable and your Prediction-Endpoint into the predictionEndpoint variable. Sie haben diese zuvor in den Editor in Kapitel 2, Schritt 14kopiert.You copied these to Notepad earlier, in Chapter 2, Step 14.

  7. Code für Awa() muss nun hinzugefügt werden, um die Instanzvariable zu initialisieren:Code for Awake() now needs to be added to initialize the Instance variable:

        /// <summary>
        /// Initializes this class
        /// </summary>
        private void Awake()
        {
            // Allows this instance to behave like a singleton
            Instance = this;
        }
    
  8. Fügen Sie die Coroutine hinzu (mit der statischen getimageasbytearray () -Methode darunter), die die Ergebnisse der Analyse des Bilds erhält, die von der imagecapture -Klasse aufgezeichnet werden.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.

    Hinweis

    In der analyseimagecapture -Coroutine gibt es einen Aufrufen der sceneorganisator -Klasse, die Sie noch erstellen müssen.In the AnalyseImageCapture coroutine, there is a call to the SceneOrganiser class that you are yet to create. Deshalb sollten Sie diese Zeilen jetzt kommentiert lassen.Therefore, leave those lines commented for now.

        /// <summary>
        /// Call the Computer Vision Service to submit the image.
        /// </summary>
        public IEnumerator AnalyseLastImageCaptured(string imagePath)
        {
            Debug.Log("Analyzing...");
    
            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;
    
                Debug.Log("response: " + jsonResponse);
    
                // Create a texture. Texture size does not matter, since
                // LoadImage will replace with the incoming image size.
                //Texture2D tex = new Texture2D(1, 1);
                //tex.LoadImage(imageBytes);
                //SceneOrganiser.Instance.quadRenderer.material.SetTexture("_MainTex", tex);
    
                // The response will be in JSON format, therefore it needs to be deserialized
                //AnalysisRootObject analysisRootObject = new AnalysisRootObject();
                //analysisRootObject = JsonConvert.DeserializeObject<AnalysisRootObject>(jsonResponse);
    
                //SceneOrganiser.Instance.FinaliseLabel(analysisRootObject);
            }
        }
    
        /// <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);
        }
    
  9. Löschen Sie die Methoden " Start () " und " Update () ", da Sie nicht verwendet werden.Delete the Start() and Update() methods, as they will not be used.

  10. Stellen Sie sicher, dass Sie die Änderungen in Visual Studio speichern, bevor Sie zu Unity zurückkehren.Be sure to save your changes in Visual Studio, before returning to Unity.

Wichtig

Wie bereits erwähnt, machen Sie sich keine Gedanken über Code, der möglicherweise einen Fehler enthält, da Sie weitere Klassen bald bereitstellen werden, die diese beheben.As mentioned earlier, do not worry about code which might appear to have an error, as you will provide further classes soon, which will fix these.

Kapitel 6: Erstellen der customvisionobjects-KlasseChapter 6 - Create the CustomVisionObjects class

Die Klasse, die Sie jetzt erstellen, ist die customvisionobjects -Klasse.The class you will create now is the CustomVisionObjects class.

Dieses Skript enthält eine Reihe von Objekten, die von anderen Klassen zum Serialisieren und Deserialisieren der Aufrufe an die Custom Vision Service verwendet werden.This script contains a number of objects used by other classes to serialize and deserialize the calls made to the Custom Vision Service.

So erstellen Sie diese Klasse:To create this class:

  1. Klicken Sie mit der rechten Maustaste in den Ordner > # Skripts, und klicken Sie dann auf Skript erstellen.Right-click inside the Scripts folder, then click Create > C# Script. Nennen Sie das Skript customvisionobjects.Call the script CustomVisionObjects.

  2. Doppelklicken Sie auf das neue customvisionobjects -Skript, um es in Visual Studio zu öffnen.Double-click on the new CustomVisionObjects script to open it with Visual Studio.

  3. Stellen Sie sicher, dass am Anfang der Datei die folgenden Namespaces referenziert sind:Make sure you have the following namespaces referenced at the top of the file:

    using System;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Networking;
    
  4. Löschen Sie die Methoden " Start () " und " Update () " innerhalb der customvisionobjects -Klasse. diese Klasse sollte nun leer sein.Delete the Start() and Update() methods inside the CustomVisionObjects class, this class should now be empty.

    Warnung

    Es ist wichtig, dass Sie die nächste Anweisung sorgfältig befolgen.It is important you follow the next instruction carefully. Wenn Sie die neuen Klassen Deklarationen in der customvisionobjects -Klasse platzieren, erhalten Sie Kompilierungsfehler in Kapitel 10, in der angegeben wird, dass analysisrootobject und BoundingBox nicht gefunden werden.If you put the new class declarations inside the CustomVisionObjects class, you will get compile errors in chapter 10, stating that AnalysisRootObject and BoundingBox are not found.

  5. Fügen Sie die folgenden Klassen außerhalb der customvisionobjects -Klasse hinzu.Add the following classes outside the CustomVisionObjects class. Diese Objekte werden von der newtonsoft -Bibliothek verwendet, um die Antwortdaten zu serialisieren und zu deserialisieren: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
    /// Includes Bounding Box
    /// </summary>
    public class AnalysisRootObject
    {
        public string id { get; set; }
        public string project { get; set; }
        public string iteration { get; set; }
        public DateTime created { get; set; }
        public List<Prediction> predictions { get; set; }
    }
    
    public class BoundingBox
    {
        public double left { get; set; }
        public double top { get; set; }
        public double width { get; set; }
        public double height { get; set; }
    }
    
    public class Prediction
    {
        public double probability { get; set; }
        public string tagId { get; set; }
        public string tagName { get; set; }
        public BoundingBox boundingBox { get; set; }
    }
    
  6. Stellen Sie sicher, dass Sie die Änderungen in Visual Studio speichern, bevor Sie zu Unity zurückkehren.Be sure to save your changes in Visual Studio, before returning to Unity.

Kapitel 7: Erstellen der spatialmapping-KlasseChapter 7 - Create the SpatialMapping class

Mit dieser Klasse wird der Collider der räumlichen Zuordnung in der Szene so festgelegt, dass Konflikte zwischen virtuellen Objekten und echten Objekten erkannt werden können.This class will set the Spatial Mapping Collider in the scene so to be able to detect collisions between virtual objects and real objects.

So erstellen Sie diese Klasse:To create this class:

  1. Klicken Sie mit der rechten Maustaste in den Ordner > # Skripts, und klicken Sie dann auf Skript erstellen.Right-click inside the Scripts folder, then click Create > C# Script. Nennen Sie das Skript spatialmapping.Call the script SpatialMapping.

  2. Doppelklicken Sie auf das neue spatialmapping -Skript, um es in Visual Studio zu öffnen.Double-click on the new SpatialMapping script to open it with Visual Studio.

  3. Stellen Sie sicher, dass die folgenden Namespaces oberhalb der spatialmapping -Klasse referenziert sind:Make sure you have the following namespaces referenced above the SpatialMapping class:

    using UnityEngine;
    using UnityEngine.XR.WSA;
    
  4. Fügen Sie dann die folgenden Variablen in der spatialmapping -Klasse oberhalb der Start () -Methode hinzu:Then, add the following variables inside the SpatialMapping class, above the Start() method:

        /// <summary>
        /// Allows this class to behave like a singleton
        /// </summary>
        public static SpatialMapping Instance;
    
        /// <summary>
        /// Used by the GazeCursor as a property with the Raycast call
        /// </summary>
        internal static int PhysicsRaycastMask;
    
        /// <summary>
        /// The layer to use for spatial mapping collisions
        /// </summary>
        internal int physicsLayer = 31;
    
        /// <summary>
        /// Creates environment colliders to work with physics
        /// </summary>
        private SpatialMappingCollider spatialMappingCollider;
    
  5. Fügen Sie die " Awake () " und " Start ()" hinzuAdd the Awake() and Start():

        /// <summary>
        /// Initializes this class
        /// </summary>
        private void Awake()
        {
            // Allows this instance to behave like a singleton
            Instance = this;
        }
    
        /// <summary>
        /// Runs at initialization right after Awake method
        /// </summary>
        void Start()
        {
            // Initialize and configure the collider
            spatialMappingCollider = gameObject.GetComponent<SpatialMappingCollider>();
            spatialMappingCollider.surfaceParent = this.gameObject;
            spatialMappingCollider.freezeUpdates = false;
            spatialMappingCollider.layer = physicsLayer;
    
            // define the mask
            PhysicsRaycastMask = 1 << physicsLayer;
    
            // set the object as active one
            gameObject.SetActive(true);
        }
    
  6. Löschen Sie die Update () -Methode.Delete the Update() method.

  7. Stellen Sie sicher, dass Sie die Änderungen in Visual Studio speichern, bevor Sie zu Unity zurückkehren.Be sure to save your changes in Visual Studio, before returning to Unity.

Kapitel 8: Erstellen der "gazecursor"-KlasseChapter 8 - Create the GazeCursor class

Diese Klasse ist für das Einrichten des Cursors an der richtigen Position in einem echten Bereich verantwortlich, indem der spatialmappingcollider-Wert verwendet wird, der im vorherigen Kapitel erstellt wurde.This class is responsible for setting up the cursor in the correct location in real space, by making use of the SpatialMappingCollider, created in the previous chapter.

So erstellen Sie diese Klasse:To create this class:

  1. Klicken Sie mit der rechten Maustaste in den Ordner > # Skripts, und klicken Sie dann auf Skript erstellen.Right-click inside the Scripts folder, then click Create > C# Script. Skript für " gazecursor " abrufenCall the script GazeCursor

  2. Doppelklicken Sie auf das neue gazecursor -Skript, um es in Visual Studio zu öffnen.Double-click on the new GazeCursor script to open it with Visual Studio.

  3. Stellen Sie sicher, dass der folgende Namespace oberhalb der Klasse " gazecursor " referenziert ist:Make sure you have the following namespace referenced above the GazeCursor class:

    using UnityEngine;
    
  4. Fügen Sie dann die folgende Variable in der Klasse " gazecursor " oberhalb der Methode " Start () " ein.Then add the following variable inside the GazeCursor class, above the Start() method.

        /// <summary>
        /// The cursor (this object) mesh renderer
        /// </summary>
        private MeshRenderer meshRenderer;
    
  5. Aktualisieren Sie die Methode " Start () " mit dem folgenden Code:Update the Start() method with the following code:

        /// <summary>
        /// Runs at initialization right after the Awake method
        /// </summary>
        void Start()
        {
            // Grab the mesh renderer that is on the same object as this script.
            meshRenderer = gameObject.GetComponent<MeshRenderer>();
    
            // Set the cursor reference
            SceneOrganiser.Instance.cursor = gameObject;
            gameObject.GetComponent<Renderer>().material.color = Color.green;
    
            // If you wish to change the size of the cursor you can do so here
            gameObject.transform.localScale = new Vector3(0.01f, 0.01f, 0.01f);
        }
    
  6. Aktualisieren Sie die Update () -Methode mit dem folgenden Code:Update the Update() method with the following code:

        /// <summary>
        /// Update is called once per frame
        /// </summary>
        void Update()
        {
            // Do a raycast into the world based on the user's head position and orientation.
            Vector3 headPosition = Camera.main.transform.position;
            Vector3 gazeDirection = Camera.main.transform.forward;
    
            RaycastHit gazeHitInfo;
            if (Physics.Raycast(headPosition, gazeDirection, out gazeHitInfo, 30.0f, SpatialMapping.PhysicsRaycastMask))
            {
                // If the raycast hit a hologram, display the cursor mesh.
                meshRenderer.enabled = true;
                // Move the cursor to the point where the raycast hit.
                transform.position = gazeHitInfo.point;
                // Rotate the cursor to hug the surface of the hologram.
                transform.rotation = Quaternion.FromToRotation(Vector3.up, gazeHitInfo.normal);
            }
            else
            {
                // If the raycast did not hit a hologram, hide the cursor mesh.
                meshRenderer.enabled = false;
            }
        }
    

    Hinweis

    Machen Sie sich keine Sorgen, dass der Fehler für die sceneorganisator -Klasse nicht gefunden wird. Sie erstellen Sie im nächsten Kapitel.Do not worry about the error for the SceneOrganiser class not being found, you will create it in the next chapter.

  7. Stellen Sie sicher, dass Sie die Änderungen in Visual Studio speichern, bevor Sie zu Unity zurückkehren.Be sure to save your changes in Visual Studio, before returning to Unity.

Kapitel 9: Erstellen der sceneorganisator-KlasseChapter 9 - Create the SceneOrganiser class

Diese Klasse führt Folgendes aus:This class will:

  • Richten Sie die Hauptkamera ein, indem Sie die entsprechenden Komponenten an Sie anfügen.Set up the Main Camera by attaching the appropriate components to it.

  • Wenn ein Objekt erkannt wird, ist es dafür verantwortlich, seine Position in der realen Welt zu berechnen und eine tagbezeichnung in der Nähe des entsprechenden Tagnamens zu platzieren.When an object is detected, it will be responsible for calculating its position in the real world and place a Tag Label near it with the appropriate Tag Name.

So erstellen Sie diese Klasse:To create this class:

  1. Klicken Sie mit der rechten Maustaste in den Ordner > # Skripts, und klicken Sie dann auf Skript erstellen.Right-click inside the Scripts folder, then click Create > C# Script. Nennen Sie das Skript sceneorganisator.Name the script SceneOrganiser.

  2. Doppelklicken Sie auf das neue sceneorganisator -Skript, um es in Visual Studio zu öffnen.Double-click on the new SceneOrganiser script to open it with Visual Studio.

  3. Stellen Sie sicher, dass die folgenden Namespaces oberhalb der sceneorganisator -Klasse referenziert sind:Make sure you have the following namespaces referenced above the SceneOrganiser class:

    using System.Collections.Generic;
    using System.Linq;
    using UnityEngine;
    
  4. Fügen Sie dann die folgenden Variablen in der sceneorganisator -Klasse oberhalb der Start () -Methode hinzu: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 Main Camera
        /// </summary>
        internal GameObject cursor;
    
        /// <summary>
        /// The label used to display the analysis on the objects in the real world
        /// </summary>
        public GameObject label;
    
        /// <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.8f;
    
        /// <summary>
        /// The quad object hosting the imposed image captured
        /// </summary>
        private GameObject quad;
    
        /// <summary>
        /// Renderer of the quad object
        /// </summary>
        internal Renderer quadRenderer;
    
  5. Löschen Sie die Methoden " Start () " und " Update () ".Delete the Start() and Update() methods.

  6. Fügen Sie unterhalb der Variablen die Awa() -Methode hinzu, die die Klasse initialisiert und die Szene einrichtet.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 CustomVisionObjects class to this Gameobject
            gameObject.AddComponent<CustomVisionObjects>();
        }
    
  7. Fügen Sie die placeanalysislabel () -Methode hinzu, die die Bezeichnung in der Szene instanziiert (die zu diesem Zeitpunkt für den Benutzer unsichtbar ist).Add the PlaceAnalysisLabel() method, which will Instantiate the label in the scene (which at this point is invisible to the user). Außerdem wird das Quad (auch unsichtbar) platziert, wo das Bild platziert ist, und es wird mit der realen Welt überlappt.It also places the quad (also invisible) where the image is placed, and overlaps with the real world. Dies ist wichtig, da die Feld Koordinaten, die nach der Analyse vom Dienst abgerufen werden, wieder in dieses vierfache zurückgeführt werden, um die ungefähre Position des Objekts in der realen Welt zu ermitteln.This is important because the box coordinates retrieved from the Service after analysis are traced back into this quad to determined the approximate location of the object in the real world.

        /// <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>();
            lastLabelPlacedText.text = "";
            lastLabelPlaced.transform.localScale = new Vector3(0.005f,0.005f,0.005f);
    
            // Create a GameObject to which the texture can be applied
            quad = GameObject.CreatePrimitive(PrimitiveType.Quad);
            quadRenderer = quad.GetComponent<Renderer>() as Renderer;
            Material m = new Material(Shader.Find("Legacy Shaders/Transparent/Diffuse"));
            quadRenderer.material = m;
    
            // Here you can set the transparency of the quad. Useful for debugging
            float transparency = 0f;
            quadRenderer.material.color = new Color(1, 1, 1, transparency);
    
            // Set the position and scale of the quad depending on user position
            quad.transform.parent = transform;
            quad.transform.rotation = transform.rotation;
    
            // The quad is positioned slightly forward in font of the user
            quad.transform.localPosition = new Vector3(0.0f, 0.0f, 3.0f);
    
            // The quad scale as been set with the following value following experimentation,  
            // to allow the image on the quad to be as precisely imposed to the real world as possible
            quad.transform.localScale = new Vector3(3f, 1.65f, 1f);
            quad.transform.parent = null;
        }
    
  8. Fügen Sie die finaliselabel () -Methode hinzu.Add the FinaliseLabel() method. IISConfigurator ist für Folgendes zuständig:It is responsible for:

    • Der Bezeichnungs Text wird mit dem Tag der Vorhersage mit dem höchsten Vertrauen festgelegt.Setting the Label text with the Tag of the Prediction with the highest confidence.
    • Aufrufen der Berechnung des umgebenden Felds auf dem Quad-Objekt, das zuvor positioniert wurde, und Platzieren der Bezeichnung in der Szene.Calling the calculation of the Bounding Box on the quad object, positioned previously, and placing the label in the scene.
    • Anpassung der Bezeichnungs Tiefe mithilfe eines Raycasts in das umgebende Feld, das mit dem Objekt in der realen Welt kollidieren soll.Adjusting the label depth by using a Raycast towards the Bounding Box, which should collide against the object in the real world.
    • Zurücksetzen des Aufzeichnungsprozesses, um dem Benutzer zu ermöglichen, ein anderes Bild zu erfassen.Resetting the capture process to allow the user to capture another image.
        /// <summary>
        /// Set the Tags as Text of the last label created. 
        /// </summary>
        public void FinaliseLabel(AnalysisRootObject analysisObject)
        {
            if (analysisObject.predictions != null)
            {
                lastLabelPlacedText = lastLabelPlaced.GetComponent<TextMesh>();
                // Sort the predictions to locate the highest one
                List<Prediction> sortedPredictions = new List<Prediction>();
                sortedPredictions = analysisObject.predictions.OrderBy(p => p.probability).ToList();
                Prediction bestPrediction = new Prediction();
                bestPrediction = sortedPredictions[sortedPredictions.Count - 1];
    
                if (bestPrediction.probability > probabilityThreshold)
                {
                    quadRenderer = quad.GetComponent<Renderer>() as Renderer;
                    Bounds quadBounds = quadRenderer.bounds;
    
                    // Position the label as close as possible to the Bounding Box of the prediction 
                    // At this point it will not consider depth
                    lastLabelPlaced.transform.parent = quad.transform;
                    lastLabelPlaced.transform.localPosition = CalculateBoundingBoxPosition(quadBounds, bestPrediction.boundingBox);
    
                    // Set the tag text
                    lastLabelPlacedText.text = bestPrediction.tagName;
    
                    // Cast a ray from the user's head to the currently placed label, it should hit the object detected by the Service.
                    // At that point it will reposition the label where the ray HL sensor collides with the object,
                    // (using the HL spatial tracking)
                    Debug.Log("Repositioning Label");
                    Vector3 headPosition = Camera.main.transform.position;
                    RaycastHit objHitInfo;
                    Vector3 objDirection = lastLabelPlaced.position;
                    if (Physics.Raycast(headPosition, objDirection, out objHitInfo, 30.0f,   SpatialMapping.PhysicsRaycastMask))
                    {
                        lastLabelPlaced.position = objHitInfo.point;
                    }
                }
            }
            // Reset the color of the cursor
            cursor.GetComponent<Renderer>().material.color = Color.green;
    
            // Stop the analysis process
            ImageCapture.Instance.ResetImageCapture();        
        }
    
  9. Fügen Sie die calculateboundingboxposition () -Methode hinzu, die eine Reihe von Berechnungen hostet, die erforderlich sind, um die vom Dienst abgerufenen umgebenden Feld Koordinaten zu übersetzen und diese proportional zum Quad neu zu erstellen.Add the CalculateBoundingBoxPosition() method, which hosts a number of calculations necessary to translate the Bounding Box coordinates retrieved from the Service and recreate them proportionally on the quad.

        /// <summary>
        /// This method hosts a series of calculations to determine the position 
        /// of the Bounding Box on the quad created in the real world
        /// by using the Bounding Box received back alongside the Best Prediction
        /// </summary>
        public Vector3 CalculateBoundingBoxPosition(Bounds b, BoundingBox boundingBox)
        {
            Debug.Log($"BB: left {boundingBox.left}, top {boundingBox.top}, width {boundingBox.width}, height {boundingBox.height}");
    
            double centerFromLeft = boundingBox.left + (boundingBox.width / 2);
            double centerFromTop = boundingBox.top + (boundingBox.height / 2);
            Debug.Log($"BB CenterFromLeft {centerFromLeft}, CenterFromTop {centerFromTop}");
    
            double quadWidth = b.size.normalized.x;
            double quadHeight = b.size.normalized.y;
            Debug.Log($"Quad Width {b.size.normalized.x}, Quad Height {b.size.normalized.y}");
    
            double normalisedPos_X = (quadWidth * centerFromLeft) - (quadWidth/2);
            double normalisedPos_Y = (quadHeight * centerFromTop) - (quadHeight/2);
    
            return new Vector3((float)normalisedPos_X, (float)normalisedPos_Y, 0);
        }
    
  10. Stellen Sie sicher, dass Sie die Änderungen in Visual Studio speichern, bevor Sie zu Unity zurückkehren.Be sure to save your changes in Visual Studio, before returning to Unity.

    Wichtig

    Bevor Sie fortfahren, öffnen Sie die customvisionanalyser -Klasse, und heben Sie die Auskommentierung der folgenden Zeilen innerhalb der analyselastimageaufgezeichnet () -Methode auf:Before you continue, open the CustomVisionAnalyser class, and within the AnalyseLastImageCaptured() method, uncomment the following lines:

    // Create a texture. Texture size does not matter, since 
    // LoadImage will replace with the incoming image size.
    Texture2D tex = new Texture2D(1, 1);
    tex.LoadImage(imageBytes);
    SceneOrganiser.Instance.quadRenderer.material.SetTexture("_MainTex", tex);
    
    // The response will be in JSON format, therefore it needs to be deserialized
    AnalysisRootObject analysisRootObject = new AnalysisRootObject();
    analysisRootObject = JsonConvert.DeserializeObject<AnalysisRootObject>(jsonResponse);
    
    SceneOrganiser.Instance.FinaliseLabel(analysisRootObject);
    

Hinweis

Machen Sie sich keine Gedanken über die Meldung "die imagecapture -Klasse wurde nicht gefunden", Sie erstellen Sie im nächsten Kapitel.Do not worry about the ImageCapture class 'could not be found' message, you will create it in the next chapter.

Kapitel 10: Erstellen der imagecapture-KlasseChapter 10 - Create the ImageCapture class

Die nächste Klasse, die Sie erstellen, ist die imagecapture -Klasse.The next class you are going to create is the ImageCapture class.

Diese Klasse ist für Folgendes zuständig:This class is responsible for:

  • Erfassen eines Bilds mithilfe der hololens-Kamera und speichern im App -Ordner.Capturing an image using the HoloLens camera and storing it in the App folder.
  • Behandlung von Tap -Gesten vom Benutzer.Handling Tap gestures from the user.

So erstellen Sie diese Klasse:To create this class:

  1. Wechseln Sie zum Ordner " Scripts ", den Sie zuvor erstellt haben.Go to the Scripts folder you created previously.

  2. Klicken Sie mit der rechten Maustaste in den Ordner , und klicken Sie dann auf > # Skript erstellen.Right-click inside the folder, then click Create > C# Script. Benennen Sie das Skript mit imagecapture.Name the script ImageCapture.

  3. Doppelklicken Sie auf das neue imagecapture -Skript, um es in Visual Studio zu öffnen.Double-click on the new ImageCapture script to open it with Visual Studio.

  4. Ersetzen Sie die Namespaces am Anfang der Datei durch Folgendes: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. Fügen Sie dann die folgenden Variablen in der imagecapture -Klasse oberhalb der Start () -Methode hinzu: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>
        /// 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. Der Code für die Methoden " Awake () " und " Start () " muss nun hinzugefügt werden:Code for Awake() and Start() methods now needs to be added:

        /// <summary>
        /// Called on initialization
        /// </summary>
        private void Awake()
        {
            Instance = this;
        }
    
        /// <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 Microsoft HoloLens API gesture recognizer to track user gestures
            recognizer = new GestureRecognizer();
            recognizer.SetRecognizableGestures(GestureSettings.Tap);
            recognizer.Tapped += TapHandler;
            recognizer.StartCapturingGestures();
        }
    
  7. Implementieren Sie einen Handler, der aufgerufen wird, wenn eine Tap-Geste auftritt:Implement a handler that will be called when a Tap gesture occurs:

        /// <summary>
        /// Respond to Tap Input.
        /// </summary>
        private void TapHandler(TappedEventArgs obj)
        {
            if (!captureIsActive)
            {
                captureIsActive = true;
    
                // Set the cursor color to red
                SceneOrganiser.Instance.cursor.GetComponent<Renderer>().material.color = Color.red;
    
                // Begin the capture loop
                Invoke("ExecuteImageCaptureAndAnalysis", 0);
            }
        }
    

    Wichtig

    Wenn der Cursor grün ist, bedeutet dies, dass die Kamera verfügbar ist, um das Bild zu übernehmen.When the cursor is green, it means the camera is available to take the image. Wenn der Cursor rot ist, bedeutet dies, dass die Kamera ausgelastet ist.When the cursor is red, it means the camera is busy.

  8. Fügen Sie die Methode hinzu, die die Anwendung verwendet, um den Bild Aufzeichnungsprozess zu starten und das Image zu speichern: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()
        {
            // Create a label in world space using the ResultsLabel 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(true, delegate (PhotoCapture captureObject)
            {
                photoCaptureObject = captureObject;
    
                CameraParameters camParameters = new CameraParameters
                {
                    hologramOpacity = 1.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. Fügen Sie die Handler hinzu, die aufgerufen werden, wenn das Foto aufgezeichnet wurde und für die Analyse bereit ist.Add the handlers that will be called when the photo has been captured and for when it is ready to be analyzed. Das Ergebnis wird dann zur Analyse an customvisionanalyser weitergegeben.The result is then passed to the CustomVisionAnalyser for analysis.

        /// <summary>
        /// Register the full execution of the Photo Capture. 
        /// </summary>
        void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
        {
            try
            {
                // Call StopPhotoMode once the image has successfully captured
                photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
            }
            catch (Exception e)
            {
                Debug.LogFormat("Exception capturing photo to disk: {0}", e.Message);
            }
        }
    
        /// <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;
    
            // Call the image analysis
            StartCoroutine(CustomVisionAnalyser.Instance.AnalyseLastImageCaptured(filePath)); 
        }
    
        /// <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;
    
            // Stop the capture loop if active
            CancelInvoke();
        }
    
  10. Stellen Sie sicher, dass Sie die Änderungen in Visual Studio speichern, bevor Sie zu Unity zurückkehren.Be sure to save your changes in Visual Studio, before returning to Unity.

Kapitel 11: Einrichten der Skripts in der SzeneChapter 11 - Setting up the scripts in the scene

Nachdem Sie den gesamten für dieses Projekt erforderlichen Code geschrieben haben, können Sie nun die Skripts in der Szene und in den Prefabs einrichten, damit Sie ordnungsgemäß Verhalten.Now that you have written all of the code necessary for this project, is time to set up the scripts in the scene, and on the prefabs, for them to behave correctly.

  1. Wählen Sie im Unity-Editor im Bereich Hierarchie die Hauptkamera aus.Within the Unity Editor, in the Hierarchy Panel, select the Main Camera.

  2. Klicken Sie im Inspektor-Panel mit ausgewählter Hauptkamera auf Komponente hinzufügen, suchen Sie nach sceneorganisator -Skript, und doppelklicken Sie darauf, um es hinzuzufügen.In the Inspector Panel, with the Main Camera selected, click on Add Component, then search for SceneOrganiser script and double-click, to add it.

  3. Öffnen Sie im Projekt Panel den Ordner "Prefabs", und ziehen Sie die Bezeichnung "Prefab" in das Eingabefeld für das leere Verweis Ziel der Bezeichnung , wie in der folgenden Abbildung gezeigt:In the Project Panel, open the Prefabs folder, drag the Label prefab into the Label empty reference target input area, in the SceneOrganiser script that you have just added to the Main Camera, as shown in the image below:

  4. Wählen Sie im Bereich Hierarchie das untergeordnete Element gazecursor der Hauptkamera aus.In the Hierarchy Panel, select the GazeCursor child of the Main Camera.

  5. Klicken Sie im Inspektor-Panel mit ausgewähltem gazecursor auf Komponente hinzufügen, suchen Sie nach dem gazecursor -Skript, und doppelklicken Sie darauf, um es hinzuzufügen.In the Inspector Panel, with the GazeCursor selected, click on Add Component, then search for GazeCursor script and double-click, to add it.

  6. Wählen Sie im Bereich Hierarchie das untergeordnete spatialmapping -Element der Hauptkamera aus.Again, in the Hierarchy Panel, select the SpatialMapping child of the Main Camera.

  7. Klicken Sie im Inspektor-Panel bei ausgewähltem spatialmapping auf Komponente hinzufügen, suchen Sie nach dem spatialmapping -Skript, und doppelklicken Sie darauf, um es hinzuzufügen.In the Inspector Panel, with the SpatialMapping selected, click on Add Component, then search for SpatialMapping script and double-click, to add it.

Die übrigen Skripts, die Sie nicht festgelegt haben, werden während der Laufzeit vom Code im sceneorganisator -Skript hinzugefügt.The remaining scripts thats you have not set will be added by the code in the SceneOrganiser script, during runtime.

Kapitel 12: vor dem AufbauChapter 12 - Before building

Wenn Sie Ihre Anwendung gründlich testen möchten, müssen Sie Sie per querladen auf Ihre Microsoft hololens anwenden.To perform a thorough test of your application you will need to sideload it onto your Microsoft HoloLens.

Bevor Sie vorgehen, stellen Sie Folgendes sicher:Before you do, ensure that:

  • Alle im Kapitel 3 erwähnten Einstellungen sind richtig festgelegt.All the settings mentioned in the Chapter 3 are set correctly.

  • Das Skript sceneorganisator ist an das Hauptkamera Objekt angefügt.The script SceneOrganiser is attached to the Main Camera object.

  • Das Skript " gazecursor " ist an das Objekt " gazecursor " angefügt.The script GazeCursor is attached to the GazeCursor object.

  • Das Skript spatialmapping ist an das spatialmapping -Objekt angefügt.The script SpatialMapping is attached to the SpatialMapping object.

  • In Kapitel 5, Schritt 6:In Chapter 5, Step 6:

    • Stellen Sie sicher, dass Sie den Dienst Vorhersage Schlüssel in die " prätionkey "-Variable einfügen.Make sure you insert your Service Prediction Key into the predictionKey variable.
    • Sie haben ihren Vorhersage Endpunkt in die " vorhertionendpoint "-Klasse eingefügt.You have inserted your Prediction Endpoint into the predictionEndpoint class.

Kapitel 13: Erstellen der UWP-Lösung und querladen der AnwendungChapter 13 - Build the UWP solution and sideload your application

Sie können nun Ihre Anwendung als UWP-Lösung erstellen, die Sie auf den Microsoft hololens bereitstellen können.You are now ready to build you application as a UWP Solution that you will be able to deploy on to the Microsoft HoloLens. So beginnen Sie den Buildprozess:To begin the build process:

  1. Wechseln Sie zu Datei > Buildeinstellungen.Go to File > Build Settings.

  2. Teil Strich Unity-C- # Projekte.Tick Unity C# Projects.

  3. Klicken Sie auf offene Szenen hinzufügen.Click on Add Open Scenes. Dadurch wird dem Build die aktuell geöffnete Szene hinzugefügt.This will add the currently open scene to the build.

  4. Klicken Sie auf Erstellen.Click Build. Unity startet ein Datei-Explorer -Fenster, in dem Sie einen Ordner erstellen und auswählen müssen, in dem die App erstellt wird.Unity will launch a File Explorer window, where you need to create and then select a folder to build the app into. Erstellen Sie diesen Ordner jetzt, und nennen Sie ihn " App".Create that folder now, and name it App. Klicken Sie dann mit ausgewähltem App -Ordner auf Ordner auswählen.Then with the App folder selected, click Select Folder.

  5. Unity startet das Projekt in den App -Ordner.Unity will begin building your project to the App folder.

  6. Nachdem die Erstellung von Unity abgeschlossen ist (Dies kann einige Zeit in Anspruch nehmen), wird ein Datei-Explorer -Fenster am Speicherort des Builds geöffnet (überprüfen Sie die Taskleiste, da Sie möglicherweise nicht immer über Ihrem Fenster angezeigt wird, sondern Sie über das Hinzufügen eines neuen Fensters benachrichtigt).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).

  7. Zum Bereitstellen von auf Microsoft hololens benötigen Sie die IP-Adresse dieses Geräts (für die Remote Bereitstellung) und, um sicherzustellen, dass der Entwicklermodus ebenfalls festgelegt ist.To deploy on to Microsoft HoloLens, you will need the IP Address of that device (for Remote Deploy), and to ensure that it also has Developer Mode set. Gehen Sie dazu wie folgt vor:To do this:

    1. Öffnen Sie die Einstellungen, während Sie die hololens- Einstellungen durch tragen.Whilst wearing your HoloLens, open the Settings.

    2. Navigieren Sie zu Netzwerk & > Erweiterte Wi-Fi- > Optionen für das Internet.Go to Network & Internet > Wi-Fi > Advanced Options

    3. Notieren Sie sich die IPv4 -Adresse.Note the IPv4 address.

    4. Navigieren Sie als nächstes wieder zu Einstellungen, und aktualisieren Sie die & Sicherheit > für Entwickler .Next, navigate back to Settings, and then to Update & Security > For Developers

    5. Legen Sie den Entwicklermodus auf fest.Set Developer Mode On.

  8. Navigieren Sie zu Ihrem neuen Unity-Build ( App -Ordner), und öffnen Sie die Projektmappendatei mit Visual Studio.Navigate to your new Unity build (the App folder) and open the solution file with Visual Studio.

  9. Wählen Sie in der Projektmappenkonfiguration Debuggen.In the Solution Configuration select Debug.

  10. Wählen Sie auf der Projektmappenplattform die Option x86, Remote Computer aus.In the Solution Platform, select x86, Remote Machine. Sie werden aufgefordert, die IP-Adresse eines Remote Geräts (in diesem Fall die von Ihnen notierten Microsoft hololens) einzufügen.You will be prompted to insert the IP address of a remote device (the Microsoft HoloLens, in this case, which you noted).

  11. Wechseln Sie zum Menü Erstellen , und klicken Sie auf Lösung bereitstellen, um die Anwendung auf die hololens quer zuladen.Go to the Build menu and click on Deploy Solution to sideload the application to your HoloLens.

  12. Ihre APP sollte nun in der Liste der installierten apps auf Ihren Microsoft hololens angezeigt werden, die bereit sind, gestartet zu werden!Your app should now appear in the list of installed apps on your Microsoft HoloLens, ready to be launched!

So verwenden Sie die Anwendung:To use the application:

  • Sehen Sie sich ein Objekt an, das Sie mit Ihrer Azure-Custom Vision Service trainiert haben, Objekterkennung, und verwenden Sie die Tap-Geste.Look at an object, which you have trained with your Azure Custom Vision Service, Object Detection, and use the Tap gesture.
  • Wenn das Objekt erfolgreich erkannt wird, wird ein Text der Bezeichnung "World-Space" mit dem Tagnamen angezeigt.If the object is successfully detected, a world-space Label Text will appear with the tag name.

Wichtig

Jedes Mal, wenn Sie ein Foto erfassen und an den Dienst senden, können Sie zur Dienst Seite zurückkehren und den Dienst mit den neu aufgezeichneten Images neu trainieren.Every time you capture a photo and send it to the Service, you can go back to the Service page and retrain the Service with the newly captured images. Zu Beginn müssen Sie wahrscheinlich auch die Begrenzungs Felder korrigieren, um präziser zu werden und den Dienst erneut zu trainieren.At the beginning, you will probably also have to correct the Bounding Boxes to be more accurate and retrain the Service.

Hinweis

Der Bezeichnungs Text wird möglicherweise nicht in der Nähe des Objekts angezeigt, wenn die Microsoft hololens-Sensoren und/oder die spatialtrackingcomponent in Unity die entsprechenden Kollisionen relativ zu den realen Objekten nicht platzieren.The Label Text placed might not appear near the object when the Microsoft HoloLens sensors and/or the SpatialTrackingComponent in Unity fails to place the appropriate colliders, relative to the real world objects. Versuchen Sie, die Anwendung auf einer anderen Oberfläche zu verwenden, wenn dies der Fall ist.Try to use the application on a different surface if that is the case.

Ihre Custom Vision, Objekt Erkennungs AnwendungYour Custom Vision, Object Detection application

Herzlichen Glückwunsch, Sie haben eine Mixed Reality-App erstellt, die das Azure-Custom Vision, Objekterkennungs-API nutzt, das ein Objekt aus einem Image erkennen kann, und dann eine ungefähre Position für dieses Objekt im 3D-Raum bereitstellen.Congratulations, you built a mixed reality app that leverages the Azure Custom Vision, Object Detection API, which can recognize an object from an image, and then provide an approximate position for that object in 3D space.

ZusatzübungenBonus exercises

Übung 1Exercise 1

Wenn Sie der Text Bezeichnung hinzufügen, verwenden Sie einen semitransparenten Cube, um das echte Objekt in einem umgebenden 3D- Feld zu schließen.Adding to the Text Label, use a semi-transparent cube to wrap the real object in a 3D Bounding Box.

Übung 2Exercise 2

Trainieren Sie Ihre Custom Vision Service, um weitere Objekte zu erkennen.Train your Custom Vision Service to recognize more objects.

Übung 3Exercise 3

Spielen Sie einen Sound wieder, wenn ein Objekt erkannt wird.Play a sound when an object is recognized.

Übung 4Exercise 4

Verwenden Sie die API zum erneuten trainieren Ihres diensmit denselben Images, die von Ihrer APP analysiert werden, um den Dienst genauer zu gestalten (führen Sie sowohl Vorhersagen als auch Schulungen gleichzeitig aus).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).