HoloLens (prima generazione) e Azure 304: riconoscimento dei visi


Nota

Le esercitazioni di Mixed Reality Academy sono state progettate in base a HoloLens (prima generazione) e ai visori VR immersive di realtà mista. Pertanto, riteniamo importante lasciarle a disposizione degli sviluppatori a cui serve ancora materiale sussidiario per lo sviluppo di questi dispositivi. Queste esercitazioni non verranno aggiornate con i set di strumenti o le interazioni più recenti usati per HoloLens 2. Rimarranno invariate per consentire di continuare a lavorare sui dispositivi supportati. Ci sarà una nuova serie di esercitazioni che verranno pubblicate in futuro che dimostreranno come sviluppare per HoloLens 2. Questo avviso verrà aggiornato con un collegamento a tali esercitazioni quando vengono pubblicate.


risultato del completamento di questo corso

In questo corso si apprenderà come aggiungere funzionalità di riconoscimento dei visi a un'applicazione di realtà mista, usando Servizi cognitivi di Azure, con l'API Viso Microsoft.

L'API Viso di Azure è un servizio Microsoft, che offre agli sviluppatori gli algoritmi viso più avanzati, tutti nel cloud. L'API Viso ha due funzioni principali: rilevamento viso con attributi e riconoscimento del viso. In questo modo gli sviluppatori possono semplicemente impostare un set di gruppi per i visi e quindi inviare immagini di query al servizio in un secondo momento, per determinare a chi appartiene un viso. Per altre informazioni, visitare la pagina Riconoscimento viso di Azure.

Dopo aver completato questo corso, si avrà un'applicazione HoloLens di realtà mista, che sarà in grado di eseguire le operazioni seguenti:

  1. Usa un movimento di tocco per avviare l'acquisizione di un'immagine usando la fotocamera HoloLens a bordo.
  2. Inviare l'immagine acquisita al servizio API Viso di Azure .
  3. Ricevere i risultati dell'algoritmo DELL'API Viso .
  4. Usare un'interfaccia utente semplice per visualizzare il nome delle persone corrispondenti.

Verrà illustrato come ottenere i risultati dal servizio API Viso nell'applicazione di realtà mista basata su Unity.

Nell'applicazione spetta all'utente come integrare i risultati con la progettazione. Questo corso è progettato per illustrare come integrare un servizio di Azure con il progetto Unity. È il compito di usare le conoscenze acquisite da questo corso per migliorare l'applicazione di realtà mista.

Supporto di dispositivi

Corso HoloLens Visori VR immersive
MR e Azure 304: Riconoscimento del volto ✔️

Nota

Anche se questo corso è incentrato principalmente su HoloLens, è anche possibile applicare ciò che si impara in questo corso per Windows Mixed Reality visori VR immersive. Poiché i visori VR immersive non dispongono di fotocamere accessibili, è necessaria una fotocamera esterna connessa al PC. Mentre segui il corso, vedrai note su eventuali modifiche che potresti dover usare per supportare visori VR immersive.

Prerequisiti

Nota

Questa esercitazione è progettata per gli sviluppatori che hanno esperienza di base con Unity e C#. Tenere presente anche che i prerequisiti e le istruzioni scritte all'interno di questo documento rappresentano ciò che è stato testato e verificato al momento della stesura del documento (maggio 2018). Si è liberi di usare il software più recente, come elencato all'interno dell'articolo installare gli strumenti , anche se non si deve presupporre che le informazioni in questo corso corrisponderanno perfettamente a ciò che troverete nel software più recente rispetto a quello elencato di seguito.

Per questo corso è consigliabile usare l'hardware e il software seguenti:

Prima di iniziare

  1. Per evitare di riscontrare problemi durante la compilazione di questo progetto, è consigliabile creare il progetto menzionato in questa esercitazione in una cartella radice o quasi radice (i percorsi di cartelle lunghi possono causare problemi in fase di compilazione).
  2. Configurare e testare HoloLens. Se è necessario supportare la configurazione di HoloLens, vedere l'articolo relativo alla configurazione di HoloLens.
  3. È consigliabile eseguire la calibrazione e l'ottimizzazione dei sensori quando si inizia a sviluppare una nuova app HoloLens (talvolta può essere utile per eseguire tali attività per ogni utente).

Per informazioni sulla calibrazione, seguire questo collegamento all'articolo Calibrazione di HoloLens.

Per informazioni sull'ottimizzazione dei sensori, seguire questo collegamento all'articolo Ottimizzazione del sensore HoloLens.

Capitolo 1 - Portale di Azure

Per usare il servizio API Viso in Azure, è necessario configurare un'istanza del servizio da rendere disponibile per l'applicazione.

  1. Per prima cosa, accedere al portale di Azure.

    Nota

    Se non si ha già un account Azure, è necessario crearne uno. Se si segue questa esercitazione in una classe o in una situazione di laboratorio, chiedere all'insegnante o a uno dei proctor di assistenza per configurare il nuovo account.

  2. Dopo aver eseguito l'accesso, fare clic su Nuovo nell'angolo in alto a sinistra e cercare API Viso, premere INVIO.

    cercare l'API Viso

    Nota

    La parola Nuovo potrebbe essere stata sostituita con Crea una risorsa, nei portali più recenti.

  3. La nuova pagina fornirà una descrizione del servizio API Viso . Nella parte inferiore sinistra di questa richiesta selezionare il pulsante Crea per creare un'associazione con questo servizio.

    Informazioni sull'API viso

  4. Dopo aver fatto clic su Crea:

    1. Inserire il nome desiderato per questa istanza del servizio.

    2. Selezionare una sottoscrizione.

    3. Selezionare il piano tariffario appropriato, se questa è la prima volta che si crea un servizio API Viso, dovrebbe essere disponibile un livello gratuito (denominato F0).

    4. Scegliere un gruppo di risorse o crearne uno nuovo. Un gruppo di risorse consente di monitorare, controllare l'accesso, effettuare il provisioning e gestire la fatturazione per una raccolta di asset di Azure. È consigliabile mantenere tutti i servizi di Azure associati a un singolo progetto ,ad esempio questi lab, in un gruppo di risorse comune.

      Per altre informazioni sui gruppi di risorse di Azure, vedere l'articolo sul gruppo di risorse.

    5. L'app UWP Person Maker, che verrà usata in un secondo momento, richiede l'uso di "Stati Uniti occidentali" per la località.

    6. Sarà anche necessario verificare di aver compreso le condizioni e le condizioni applicate al servizio.

    7. Selezionare Crea.*

      creare il servizio API Viso

  5. Dopo aver fatto clic su Crea,* è necessario attendere che il servizio venga creato, l'operazione potrebbe richiedere un minuto.

  6. Una notifica verrà visualizzata nel portale dopo la creazione dell'istanza del servizio.

    notifica di creazione del servizio

  7. Fare clic sulle notifiche per esplorare la nuova istanza del servizio.

    passare alla notifica delle risorse

  8. Quando si è pronti, fare clic sul pulsante Vai alla risorsa nella notifica per esplorare la nuova istanza del servizio.

    Accedere alle chiavi API viso

  9. In questa esercitazione, l'applicazione dovrà effettuare chiamate al servizio, che viene eseguita tramite l'uso della "chiave" della sottoscrizione del servizio. Dalla pagina Avvio rapido del servizio API Viso , il primo punto è il numero 1, per afferrare le chiavi.

  10. Nella pagina Servizio selezionare il collegamento ipertestuale Chiavi blu (se nella pagina Avvio rapido) o il collegamento Chiavi nel menu di spostamento dei servizi (a sinistra, indicato dall'icona "chiave"), per visualizzare le chiavi.

    Nota

    Prendere nota di una delle chiavi e proteggerla, perché sarà necessaria in un secondo momento.

Capitolo 2 - Uso dell'applicazione UWP "Person Maker"

Assicurati di scaricare l'applicazione UWP predefinita denominata Person Maker. Questa app non è il prodotto finale per questo corso, ma solo uno strumento per creare le voci di Azure, su cui si basa il progetto successivo.

Person Maker consente di creare voci di Azure, associate a persone e gruppi di persone. L'applicazione inserisce tutte le informazioni necessarie in un formato che può quindi essere usato in un secondo momento da FaceAPI, per riconoscere i visi delle persone aggiunte.

[IMPORTANTE] Person Maker usa alcune limitazioni di base per garantire che non si superi il numero di chiamate di servizio al minuto per il livello di sottoscrizione gratuito. Il testo verde nella parte superiore cambierà in rosso e aggiornerà come "ATTIVO" quando si verifica la limitazione; se si tratta del caso, è sufficiente attendere l'applicazione (attendere fino a quando non può continuare a accedere al servizio viso, aggiornandolo come "IN-ACTIVE" quando è possibile usarlo di nuovo).

Questa applicazione usa le librerie Microsoft.ProjectOxford.Face , che consentono di usare completamente l'API Viso. Questa libreria è disponibile gratuitamente come pacchetto NuGet. Per altre informazioni su questo e simili, le API assicurarsi di visitare l'articolo di riferimento sull'API.

Nota

Questi sono solo i passaggi necessari, le istruzioni per come eseguire queste operazioni sono più avanti nel documento. L'app Person Maker ti consentirà di:

  • Creare un gruppo person, costituito da diverse persone che si desidera associare. Con l'account Azure è possibile ospitare più gruppi di persone.

  • Creare una persona, membro di un gruppo person. Ogni persona ha un numero di immagini viso associate a esso.

  • Assegnare immagini viso a una persona per consentire al servizio API Viso di Azure di riconoscere una persona dal viso corrispondente.

  • Eseguire il training del servizio API Viso di Azure.

Tieni presente, quindi per eseguire il training di questa app per riconoscere le persone, dovrai avere dieci (10) foto di chiusura di ogni persona che vuoi aggiungere al tuo gruppo di persone. L'app cam Windows 10 può aiutarti a prenderli. È necessario assicurarsi che ogni foto sia chiara (evitare sfocatura, offuscamento o troppo lontano, dal soggetto), avere la foto in formato jpg o png, con le dimensioni del file immagine non più grandi di 4 MB e non meno di 1 KB.

Nota

Se si sta seguendo questa esercitazione, non usare il proprio viso per il training, come quando si mette HoloLens su, non è possibile guardare se stessi. Usare il volto di un collega o di un compagno di studio.

Esecuzione di Person Maker:

  1. Aprire la cartella PersonMaker e fare doppio clic sulla soluzione PersonMaker per aprirla con Visual Studio.

  2. Dopo aver aperto la soluzione PersonMaker , assicurarsi che:

    1. La configurazione della soluzione è impostata su Debug.

    2. La piattaforma della soluzione è impostata su x86

    3. La piattaforma di destinazione è il computer locale.

    4. Potrebbe anche essere necessario ripristinare i pacchetti NuGet (fare clic con il pulsante destro del mouse sulla soluzione e selezionare Ripristina pacchetti NuGet).

  3. Fare clic su Computer locale e l'applicazione verrà avviata. Tenere presente che, su schermi più piccoli, tutto il contenuto potrebbe non essere visibile, anche se è possibile scorrere ulteriormente verso il basso per visualizzarlo.

    interfaccia utente di person maker

  4. Inserire la chiave di autenticazione di Azure, che dovrebbe essere disponibile, dal servizio API Viso in Azure.

  5. Inserisci:

    1. ID che si vuole assegnare al gruppo Person. L'ID deve essere minuscolo, senza spazi. Prendere nota di questo ID, perché sarà necessario più avanti nel progetto Unity.
    2. Nome che si vuole assegnare al gruppo person (può avere spazi).
  6. Premere Il pulsante Crea gruppo persona . Verrà visualizzato un messaggio di conferma sotto il pulsante.

Nota

Se si verifica un errore "Accesso negato", controllare il percorso impostato per il servizio di Azure. Come indicato sopra, questa app è progettata per "Stati Uniti occidentali".

Importante

Si noterà che è anche possibile fare clic sul pulsante Recupera un gruppo noto : questo è per se è già stato creato un gruppo di persone e si desidera usarlo, anziché crearne uno nuovo. Tenere presente che, se si fa clic su Crea un gruppo persona con un gruppo noto, verrà recuperato anche un gruppo.

  1. Inserire il nome della persona da creare.

    1. Fare clic sul pulsante Crea persona .

    2. Verrà visualizzato un messaggio di conferma sotto il pulsante.

    3. Se si vuole eliminare una persona creata in precedenza, è possibile scrivere il nome nella casella di testo e premere Elimina persona

  2. Assicurati di conoscere la posizione di dieci (10) foto della persona che vuoi aggiungere al tuo gruppo.

  3. Premere Crea e apri cartella per aprire Esplora risorse nella cartella associata alla persona. Aggiungere le dieci immagini (10) nella cartella. Questi devono essere di formato di file JPG o PNG .

  4. Fare clic su Invia ad Azure. Un contatore mostrerà lo stato dell'invio, seguito da un messaggio al termine dell'invio.

  5. Al termine del contatore e viene visualizzato un messaggio di conferma su Train per eseguire il training del servizio.

Al termine del processo, è possibile passare a Unity.

Capitolo 3 - Configurare il progetto Unity

Di seguito è riportata una configurazione tipica per lo sviluppo con realtà mista e, di conseguenza, è un modello valido per altri progetti.

  1. Aprire Unity e fare clic su Nuovo.

    Avviare un nuovo progetto Unity.

  2. Sarà ora necessario specificare un nome di progetto Unity. Inserire MR_FaceRecognition. Assicurarsi che il tipo di progetto sia impostato su 3D. Impostare La posizione su un punto appropriato per l'utente (ricordarsi, più vicino alle directory radice è meglio). Fare quindi clic su Crea progetto.

    Specificare i dettagli per il nuovo progetto Unity.

  3. Con Unity aperto, vale la pena verificare che l'editor di script predefinito sia impostato su Visual Studio. Passare a Modifica > preferenze e quindi dalla nuova finestra passare a Strumenti esterni. Modificare l'editor script esterno in Visual Studio 2017. Chiudere la finestra Preferenze .

    Aggiornare le preferenze dell'editor di script.

  4. Passare quindi a Impostazioni di compilazione file > e passare alla piattaforma in piattaforma UWP (Universal Windows Platform) facendo clic sul pulsante Cambia piattaforma.

    Finestra Impostazioni di compilazione, passare alla piattaforma UWP.

  5. Passare a Impostazioni di compilazione file > e assicurarsi che:

    1. Dispositivo di destinazione è impostato su HoloLens

      Per i visori vr immersivi, impostare Dispositivo di destinazione su Qualsiasi dispositivo.

    2. Il tipo di compilazione è impostato su D3D

    3. SDK è impostato su Più recente installato

    4. La versione di Visual Studio è impostata su Più recente installata

    5. Compilare ed eseguire è impostato su Computer locale

    6. Salvare la scena e aggiungerla alla compilazione.

      1. Eseguire questa operazione selezionando Aggiungi scene aperte. Verrà visualizzata una finestra di salvataggio.

        Fare clic sul pulsante Aggiungi scene aperte

      2. Selezionare il pulsante Nuova cartella per creare una nuova cartella, denominarla Scene.

        Creare una nuova cartella script

      3. Aprire la cartella Scene appena creata e quindi nel campo Nome file: testo, digitare FaceRecScene e quindi premere Salva.

        Assegnare una nuova scena a un nome.

    7. Le impostazioni rimanenti, in Impostazioni di compilazione, devono essere lasciate come predefinite per il momento.

  6. Nella finestra Impostazioni di compilazione fare clic sul pulsante Impostazioni lettore , verrà aperto il pannello correlato nello spazio in cui si trova Il controllo .

    Aprire le impostazioni del lettore.

  7. In questo pannello è necessario verificare alcune impostazioni:

    1. Nella scheda Altre impostazioni :

      1. La versione del runtimedi script deve essere sperimentale (equivalente.NET 4.6). La modifica di questo attiva una necessità di riavviare l'editor.

      2. Scripting Back-end deve essere .NET

      3. Il livello di compatibilità api deve essere .NET 4.6

        Aggiornare altre impostazioni.

    2. Nella scheda Impostazioni di pubblicazione , in Funzionalità selezionare:

      • InternetClient

      • Webcam

        Aggiornamento delle impostazioni di pubblicazione.

    3. Più avanti nel pannello, in Impostazioni XR (trovate sotto Le impostazioni di pubblicazione), selezionare Virtual Reality Supportato, assicurarsi che l'SDK di Windows Mixed Reality venga aggiunto.

      Aggiornare le impostazioni X R.

  8. Torna in Impostazioni di compilazione, i progetti C# di Unity non sono più disattivati; selezionare la casella di controllo accanto a questa.

  9. Chiudere la finestra Build Settings (Impostazioni di compilazione).

  10. Salvare la scena e il progetto (>FILE SAVE SCENE/FILE > SAVE PROJECT).

Capitolo 4 - Configurazione della fotocamera principale

Importante

Se si vuole ignorare il componente Di configurazione di Unity di questo corso e continuare direttamente nel codice, è possibile scaricare questo pacchetto unitypackage e importarlo nel progetto come pacchetto personalizzato. Tenere presente che questo pacchetto include anche l'importazione della DLL Newtonsoft, illustrata nel capitolo 5. Con questa operazione importata, è possibile continuare dal capitolo 6.

  1. Nel pannello gerarchia selezionare la fotocamera principale.

  2. Dopo aver selezionato, sarà possibile visualizzare tutti i componenti della fotocamera principale nel pannello di controllo.

    1. L'oggetto Camera deve essere denominato Main Camera (nota l'ortografia!)

    2. Il tag della fotocamera principale deve essere impostato su MainCamera (nota l'ortografia!)

    3. Assicurarsi che la posizione di trasformazione sia impostata su 0, 0, 0

    4. Impostare flag cancella su colore a tinta unita

    5. Impostare il colore di sfondo del componente fotocamera su nero, alfa 0 (codice esadecimale: #000000000)

      configurare i componenti della fotocamera

Capitolo 5 : Importare la libreria Newtonsoft.Json

Importante

Se è stato importato il pacchetto '.unitypackage' nell'ultimo capitolo, è possibile ignorare questo capitolo.

Per facilitare la deserializzazione e la serializzazione degli oggetti ricevuti e inviati alla servizio Bot è necessario scaricare la libreria Newtonsoft.Json. È disponibile una versione compatibile già organizzata con la struttura della cartella Unity corretta in questo file di pacchetto Unity.

Per importare la libreria:

  1. Scaricare il pacchetto Unity.

  2. Fare clic su Asset, Importa pacchetto, pacchetto personalizzato.

    Importa Newtonsoft.Json

  3. Cercare il pacchetto Unity scaricato e fare clic su Apri.

  4. Assicurarsi che tutti i componenti del pacchetto siano selezionati e fare clic su Importa.

    Importare gli asset Newtonsoft.Json

Capitolo 6 - Creare la classe FaceAnalysis

Lo scopo della classe FaceAnalysis è ospitare i metodi necessari per comunicare con il servizio Riconoscimento viso di Azure.

  • Dopo aver inviato il servizio un'immagine di acquisizione, la analizza e identifica i visi all'interno e determina se appartiene a una persona nota.
  • Se viene trovata una persona nota, questa classe visualizzerà il nome come testo dell'interfaccia utente nella scena.

Per creare la classe FaceAnalysis :

  1. Fare clic con il pulsante destro del mouse sulla cartella Asset disponibile nel pannello di progetto, quindi scegliere Crea>cartella. Chiamare script della cartella.

    Creare la classe FaceAnalysis.

  2. Fare doppio clic sulla cartella appena creata per aprirla.

  3. Fare clic con il pulsante destro del mouse all'interno della cartella, quindi fare clic su Crea>script C#. Chiamare lo script FaceAnalysis.

  4. Fare doppio clic sul nuovo script FaceAnalysis per aprirlo con Visual Studio 2017.

  5. Immettere gli spazi dei nomi seguenti sopra la classe FaceAnalysis :

        using Newtonsoft.Json;
        using System.Collections;
        using System.Collections.Generic;
        using System.IO;
        using System.Text;
        using UnityEngine;
        using UnityEngine.Networking;
    
  6. È ora necessario aggiungere tutti gli oggetti usati per deserializzare. Questi oggetti devono essere aggiunti all'esterno dello script FaceAnalysis (sotto la parentesi curly inferiore).

        /// <summary>
        /// The Person Group object
        /// </summary>
        public class Group_RootObject
        {
            public string personGroupId { get; set; }
            public string name { get; set; }
            public object userData { get; set; }
        }
    
        /// <summary>
        /// The Person Face object
        /// </summary>
        public class Face_RootObject
        {
            public string faceId { get; set; }
        }
    
        /// <summary>
        /// Collection of faces that needs to be identified
        /// </summary>
        public class FacesToIdentify_RootObject
        {
            public string personGroupId { get; set; }
            public List<string> faceIds { get; set; }
            public int maxNumOfCandidatesReturned { get; set; }
            public double confidenceThreshold { get; set; }
        }
    
        /// <summary>
        /// Collection of Candidates for the face
        /// </summary>
        public class Candidate_RootObject
        {
            public string faceId { get; set; }
            public List<Candidate> candidates { get; set; }
        }
    
        public class Candidate
        {
            public string personId { get; set; }
            public double confidence { get; set; }
        }
    
        /// <summary>
        /// Name and Id of the identified Person
        /// </summary>
        public class IdentifiedPerson_RootObject
        {
            public string personId { get; set; }
            public string name { get; set; }
        }
    
  7. I metodi Start() e Update() non verranno usati, quindi eliminarli ora.

  8. All'interno della classe FaceAnalysis aggiungere le variabili seguenti:

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

    Nota

    Sostituire la chiave e il personGroupId con la chiave di servizio e l'ID del gruppo creato in precedenza.

  9. Aggiungere il metodo Awake() che inizializza la classe, aggiungendo la classe ImageCapture alla fotocamera main e chiama il metodo di creazione Label:

        /// <summary>
        /// Initialises this class
        /// </summary>
        private void Awake()
        {
            // Allows this instance to behave like a singleton
            Instance = this;
    
            // Add the ImageCapture Class to this Game Object
            gameObject.AddComponent<ImageCapture>();
    
            // Create the text label in the scene
            CreateLabel();
        }
    
  10. Aggiungere il metodo CreateLabel() che crea l'oggetto Label per visualizzare il risultato dell'analisi:

        /// <summary>
        /// Spawns cursor for the Main Camera
        /// </summary>
        private void CreateLabel()
        {
            // Create a sphere as new cursor
            GameObject newLabel = new GameObject();
    
            // Attach the label to the Main Camera
            newLabel.transform.parent = gameObject.transform;
    
            // Resize and position the new cursor
            newLabel.transform.localScale = new Vector3(0.4f, 0.4f, 0.4f);
            newLabel.transform.position = new Vector3(0f, 3f, 60f);
    
            // Creating the text of the Label
            labelText = newLabel.AddComponent<TextMesh>();
            labelText.anchor = TextAnchor.MiddleCenter;
            labelText.alignment = TextAlignment.Center;
            labelText.tabSize = 4;
            labelText.fontSize = 50;
            labelText.text = ".";       
        }
    
  11. Aggiungere il metodo DetectFacesFromImage() e GetImageAsByteArray(). Il precedente richiederà al servizio Riconoscimento viso di rilevare eventuali possibili volti nell'immagine inviata, mentre quest'ultimo è necessario per convertire l'immagine acquisita in una matrice di byte:

        /// <summary>
        /// Detect faces from a submitted image
        /// </summary>
        internal IEnumerator DetectFacesFromImage()
        {
            WWWForm webForm = new WWWForm();
            string detectFacesEndpoint = $"{baseEndpoint}detect";
    
            // Change the image into a bytes array
            imageBytes = GetImageAsByteArray(imagePath);
    
            using (UnityWebRequest www = 
                UnityWebRequest.Post(detectFacesEndpoint, webForm))
            {
                www.SetRequestHeader("Ocp-Apim-Subscription-Key", key);
                www.SetRequestHeader("Content-Type", "application/octet-stream");
                www.uploadHandler.contentType = "application/octet-stream";
                www.uploadHandler = new UploadHandlerRaw(imageBytes);
                www.downloadHandler = new DownloadHandlerBuffer();
    
                yield return www.SendWebRequest();
                string jsonResponse = www.downloadHandler.text;
                Face_RootObject[] face_RootObject = 
                    JsonConvert.DeserializeObject<Face_RootObject[]>(jsonResponse);
    
                List<string> facesIdList = new List<string>();
                // Create a list with the face Ids of faces detected in image
                foreach (Face_RootObject faceRO in face_RootObject)
                {
                    facesIdList.Add(faceRO.faceId);
                    Debug.Log($"Detected face - Id: {faceRO.faceId}");
                }
    
                StartCoroutine(IdentifyFaces(facesIdList));
            }
        }
    
        /// <summary>
        /// Returns the contents of the specified file as a byte array.
        /// </summary>
        static byte[] GetImageAsByteArray(string imageFilePath)
        {
            FileStream fileStream = new FileStream(imageFilePath, FileMode.Open, FileAccess.Read);
            BinaryReader binaryReader = new BinaryReader(fileStream);
            return binaryReader.ReadBytes((int)fileStream.Length);
        }
    
  12. Aggiungere il metodoIdentifiFaces() che richiede al servizio Riconoscimento viso di identificare qualsiasi viso noto rilevato in precedenza nell'immagine inviata. La richiesta restituirà un ID della persona identificata, ma non il nome:

        /// <summary>
        /// Identify the faces found in the image within the person group
        /// </summary>
        internal IEnumerator IdentifyFaces(List<string> listOfFacesIdToIdentify)
        {
            // Create the object hosting the faces to identify
            FacesToIdentify_RootObject facesToIdentify = new FacesToIdentify_RootObject();
            facesToIdentify.faceIds = new List<string>();
            facesToIdentify.personGroupId = personGroupId;
            foreach (string facesId in listOfFacesIdToIdentify)
            {
                facesToIdentify.faceIds.Add(facesId);
            }
            facesToIdentify.maxNumOfCandidatesReturned = 1;
            facesToIdentify.confidenceThreshold = 0.5;
    
            // Serialize to Json format
            string facesToIdentifyJson = JsonConvert.SerializeObject(facesToIdentify);
            // Change the object into a bytes array
            byte[] facesData = Encoding.UTF8.GetBytes(facesToIdentifyJson);
    
            WWWForm webForm = new WWWForm();
            string detectFacesEndpoint = $"{baseEndpoint}identify";
    
            using (UnityWebRequest www = UnityWebRequest.Post(detectFacesEndpoint, webForm))
            {
                www.SetRequestHeader("Ocp-Apim-Subscription-Key", key);
                www.SetRequestHeader("Content-Type", "application/json");
                www.uploadHandler.contentType = "application/json";
                www.uploadHandler = new UploadHandlerRaw(facesData);
                www.downloadHandler = new DownloadHandlerBuffer();
    
                yield return www.SendWebRequest();
                string jsonResponse = www.downloadHandler.text;
                Debug.Log($"Get Person - jsonResponse: {jsonResponse}");
                Candidate_RootObject [] candidate_RootObject = JsonConvert.DeserializeObject<Candidate_RootObject[]>(jsonResponse);
    
                // For each face to identify that ahs been submitted, display its candidate
                foreach (Candidate_RootObject candidateRO in candidate_RootObject)
                {
                    StartCoroutine(GetPerson(candidateRO.candidates[0].personId));
    
                    // Delay the next "GetPerson" call, so all faces candidate are displayed properly
                    yield return new WaitForSeconds(3);
                }           
            }
        }
    
  13. Aggiungere il metodo GetPerson(). Specificando l'ID persona, questo metodo richiede quindi al servizio Riconoscimento viso di restituire il nome della persona identificata:

        /// <summary>
        /// Provided a personId, retrieve the person name associated with it
        /// </summary>
        internal IEnumerator GetPerson(string personId)
        {
            string getGroupEndpoint = $"{baseEndpoint}persongroups/{personGroupId}/persons/{personId}?";
            WWWForm webForm = new WWWForm();
    
            using (UnityWebRequest www = UnityWebRequest.Get(getGroupEndpoint))
            {
                www.SetRequestHeader("Ocp-Apim-Subscription-Key", key);
                www.downloadHandler = new DownloadHandlerBuffer();
                yield return www.SendWebRequest();
                string jsonResponse = www.downloadHandler.text;
    
                Debug.Log($"Get Person - jsonResponse: {jsonResponse}");
                IdentifiedPerson_RootObject identifiedPerson_RootObject = JsonConvert.DeserializeObject<IdentifiedPerson_RootObject>(jsonResponse);
    
                // Display the name of the person in the UI
                labelText.text = identifiedPerson_RootObject.name;
            }
        }
    
  14. Ricordarsi di salvare le modifiche prima di tornare all'editor di Unity.

  15. Nell'editor di Unity trascinare lo script FaceAnalysis dalla cartella Script nel pannello Progetto all'oggetto Main Camera nel pannello Gerarchia. Il nuovo componente script verrà quindi aggiunto alla fotocamera principale.

Posizionare FaceAnalysis nella fotocamera principale

Capitolo 7 - Creare la classe ImageCapture

Lo scopo della classe ImageCapture è ospitare i metodi necessari per comunicare con il servizio Riconoscimento viso di Azure per analizzare l'immagine acquisita, identificare i visi in esso e determinare se appartiene a una persona nota. Se viene trovata una persona nota, questa classe visualizzerà il nome come testo dell'interfaccia utente nella scena.

Per creare la classe ImageCapture :

  1. Fare clic con il pulsante destro del mouse all'interno della cartella Script creato in precedenza, quindi fare clic su Creascript C#. Chiamare lo script ImageCapture.

  2. Fare doppio clic sul nuovo script ImageCapture per aprirlo con Visual Studio 2017.

  3. Immettere gli spazi dei nomi seguenti sopra la classe ImageCapture:

        using System.IO;
        using System.Linq;
        using UnityEngine;
        using UnityEngine.XR.WSA.Input;
        using UnityEngine.XR.WSA.WebCam;
    
  4. All'interno della classe ImageCapture aggiungere le variabili seguenti:

        /// <summary>
        /// Allows this class to behave like a singleton
        /// </summary>
        public static ImageCapture instance;
    
        /// <summary>
        /// Keeps track of tapCounts to name the captured images 
        /// </summary>
        private int tapsCount;
    
        /// <summary>
        /// PhotoCapture object used to capture images on HoloLens 
        /// </summary>
        private PhotoCapture photoCaptureObject = null;
    
        /// <summary>
        /// HoloLens class to capture user gestures
        /// </summary>
        private GestureRecognizer recognizer;
    
  5. Aggiungere i metodi Awake() e Start() necessari per inizializzare la classe e consentire a HoloLens di acquisire i movimenti dell'utente:

        /// <summary>
        /// Initialises this class
        /// </summary>
        private void Awake()
        {
            instance = this;
        }
    
        /// <summary>
        /// Called right after Awake
        /// </summary>
        void Start()
        {
            // Initialises user gestures capture 
            recognizer = new GestureRecognizer();
            recognizer.SetRecognizableGestures(GestureSettings.Tap);
            recognizer.Tapped += TapHandler;
            recognizer.StartCapturingGestures();
        }
    
  6. Aggiungere tapHandler() che viene chiamato quando l'utente esegue un movimento Tap :

        /// <summary>
        /// Respond to Tap Input.
        /// </summary>
        private void TapHandler(TappedEventArgs obj)
        {
            tapsCount++;
            ExecuteImageCaptureAndAnalysis();
        }
    
  7. Aggiungere il metodo ExecuteImageCaptureAndAnalysis() che inizierà il processo di Acquisizione immagini:

        /// <summary>
        /// Begin process of Image Capturing and send To Azure Computer Vision service.
        /// </summary>
        private void ExecuteImageCaptureAndAnalysis()
        {
            Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending
                ((res) => res.width * res.height).First();
            Texture2D targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
    
            PhotoCapture.CreateAsync(false, delegate (PhotoCapture captureObject)
            {
                photoCaptureObject = captureObject;
    
                CameraParameters c = new CameraParameters();
                c.hologramOpacity = 0.0f;
                c.cameraResolutionWidth = targetTexture.width;
                c.cameraResolutionHeight = targetTexture.height;
                c.pixelFormat = CapturePixelFormat.BGRA32;
    
                captureObject.StartPhotoModeAsync(c, delegate (PhotoCapture.PhotoCaptureResult result)
                {
                    string filename = string.Format(@"CapturedImage{0}.jpg", tapsCount);
                    string filePath = Path.Combine(Application.persistentDataPath, filename);
    
                    // Set the image path on the FaceAnalysis class
                    FaceAnalysis.Instance.imagePath = filePath;
    
                    photoCaptureObject.TakePhotoAsync
                    (filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);
                });
            });
        }
    
  8. Aggiungere i gestori chiamati al termine del processo di acquisizione foto:

        /// <summary>
        /// Called right after the photo capture process has concluded
        /// </summary>
        void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
        {
            photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
        }
    
        /// <summary>
        /// Register the full execution of the Photo Capture. If successful, it will begin the Image Analysis process.
        /// </summary>
        void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
        {
            photoCaptureObject.Dispose();
            photoCaptureObject = null;
    
            // Request image caputer analysis
            StartCoroutine(FaceAnalysis.Instance.DetectFacesFromImage());
        }
    
  9. Ricordarsi di salvare le modifiche prima di tornare all'editor di Unity.

Capitolo 8 - Creazione della soluzione

Per eseguire un test approfondito dell'applicazione, è necessario eseguirne il sideload sul dispositivo HoloLens.

Prima di eseguire, assicurarsi che:

  • Tutte le impostazioni indicate nel capitolo 3 vengono impostate correttamente.
  • Lo script FaceAnalysis è collegato all'oggetto Main Camera.
  • Sia la chiave di autenticazione che l'ID gruppo sono stati impostati nello script FaceAnalysis .

Questo punto è pronto per compilare la soluzione. Dopo aver compilato la soluzione, sarà possibile distribuire l'applicazione.

Per avviare il processo di compilazione:

  1. Salvare la scena corrente facendo clic su File, Salva.

  2. Passare a File, Build Settings (Impostazioni di compilazione), fare clic su Aggiungi scene aperte.

  3. Assicurarsi di selezionare Progetti Unity C#.

    Distribuire la soluzione di Visual Studio

  4. Premere Compila. A questo scopo, Unity avvierà una finestra di Esplora file, in cui è necessario creare e quindi selezionare una cartella in cui compilare l'app. Creare la cartella ora, all'interno del progetto Unity e chiamarla App. Quindi, con la cartella App selezionata, premere Seleziona cartella.

  5. Unity inizierà a creare il progetto, nella cartella App.

  6. Una volta completata la compilazione di Unity (potrebbe richiedere qualche tempo), verrà aperta una finestra Esplora file nella posizione della compilazione.

    Distribuire la soluzione da Visual Studio

  7. Aprire la cartella App e quindi aprire la nuova soluzione di progetto , come illustrato in precedenza, MR_FaceRecognition.sln.

Capitolo 9 - Distribuzione dell'applicazione

Per distribuire in HoloLens:

  1. È necessario l'indirizzo IP di HoloLens (per distribuzione remota) e per assicurarsi che HoloLens sia in modalità sviluppatore. Per eseguire questa operazione:

    1. Mentre indossa holoLens, apri le impostazioni.
    2. Passare a & Internet > Wi-Fi > Opzioni avanzate
    3. Prendere nota dell'indirizzo IPv4 .
    4. Tornare quindi a Impostazioni e quindi aggiornare & sicurezza > per sviluppatori
    5. Impostare la modalità sviluppatore attivata.
  2. Passare alla nuova compilazione di Unity (cartella App ) e aprire il file della soluzione con Visual Studio.

  3. In Configurazione soluzione selezionare Debug.

  4. Nella piattaforma della soluzione selezionare x86, Computer remoto.

    Modificare la configurazione della soluzione

  5. Passare al menu Compila e fare clic su Distribuisci soluzione per trasferire localmente l'applicazione in HoloLens.

  6. L'app dovrebbe ora essere visualizzata nell'elenco delle app installate in HoloLens, pronto per l'avvio.

Nota

Per eseguire la distribuzione in visore VR immersive, impostare La piattaforma della soluzione su Computer locale e impostare Configurazione su Debug, con x86 come piattaforma. Distribuire quindi nel computer locale, usando il menu Compila, selezionando Distribuisci soluzione.

Capitolo 10 - Uso dell'applicazione

  1. Indossare HoloLens, avviare l'app.

  2. Esaminare la persona registrata con l'API Viso. Assicurarsi che:

    • Il volto della persona non è troppo distante e chiaramente visibile
    • L'illuminazione dell'ambiente non è troppo scura
  3. Usare il movimento di tocco per acquisire l'immagine della persona.

  4. Attendere che l'app invii la richiesta di analisi e riceva una risposta.

  5. Se la persona è stata riconosciuta correttamente, il nome della persona verrà visualizzato come testo dell'interfaccia utente.

  6. È possibile ripetere il processo di acquisizione usando il movimento di tocco ogni pochi secondi.

Applicazione API Viso di Azure completata

È stata creata un'app di realtà mista che usa il servizio Riconoscimento viso di Azure per rilevare i visi all'interno di un'immagine e identificare eventuali visi noti.

risultato del completamento di questo corso

Esercizi aggiuntivi

Esercizio 1

L'API Viso di Azure è abbastanza potente da rilevare fino a 64 visi in una singola immagine. Estendere l'applicazione, in modo che possa riconoscere due o tre visi, tra molte altre persone.

Esercizio 2

L'API Viso di Azure è anche in grado di fornire tutti i tipi di informazioni sugli attributi. Integralo nell'applicazione. Questo potrebbe essere ancora più interessante, se combinato con l'API Emozioni.