HoloLens (prima generazione) e Azure 304: riconoscimento del viso


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 dei volti con attributi e riconoscimento del viso. Ciò consente agli sviluppatori di impostare semplicemente 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 API Viso.
  4. Usare un'interfaccia utente semplice per visualizzare il nome delle persone corrispondenti.

In questo modo si apprenderà 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 tuo compito 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 viso ✔️ ✔️

Nota

Anche se questo corso è incentrato principalmente su HoloLens, puoi anche applicare ciò che impari in questo corso ai visori VR immersive di Windows Realtà mista. Poiché i visori VR immersive non hanno fotocamere accessibili, è necessaria una fotocamera esterna connessa al PC. Mentre segui il corso, vedrai le 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 scrittura (maggio 2018). Sei libero di usare il software più recente, come elencato all'interno dell'articolo installare gli strumenti , anche se non si deve presumere che le informazioni in questo corso corrispondano perfettamente a ciò che troverai 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 delle cartelle lunghe possono causare problemi in fase di compilazione).
  2. Configurare e testare HoloLens. Se hai bisogno di supporto per configurare HoloLens, assicurati di visitare l'articolo configurazione di HoloLens.
  3. È consigliabile eseguire la calibrazione e l'ottimizzazione dei sensori quando si inizia a sviluppare una nuova app HoloLens (a volte può essere utile per eseguire tali attività per ogni utente).

Per informazioni su 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. Accedere prima di tutto 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 prottori di assistenza per configurare il nuovo account.

  2. Dopo aver eseguito l'accesso, fare clic su Nuovo nell'angolo superiore sinistro e cercare l'API Viso, premere INVIO.

    cercare l'API Viso

    Nota

    La parola New 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 questo prompt 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. Seleziona un abbonamento.

    3. Selezionare il piano tariffario appropriato, se è la prima volta che si crea un servizio API Viso, sarà 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 relativo al gruppo di risorse.

    5. L'app UWP, Person Maker, che usi 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 usando la "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 dall'API Viso 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 verrà modificato in rosso e aggiornato come "ATTIVO" quando si verifica la limitazione; se questo è il caso, è sufficiente attendere l'applicazione (attenderà fino a quando non potrà continuare ad 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 su api simili, vedere l'articolo informazioni di riferimento sulle API.

Nota

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

  • Creare un gruppo di persone, che è un gruppo composto da diverse persone a cui si vuole associare. Con l'account Azure è possibile ospitare più gruppi di persone.

  • Creare una persona, che è un membro di un gruppo di persone. A ogni persona è associata una serie di immagini viso.

  • Assegnare immagini del 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, avrai bisogno di dieci (10) foto di primo piano di ogni persona che vuoi aggiungere al tuo gruppo di persone. L'app Windows 10 Cam può aiutarti a prenderli. È necessario assicurarsi che ogni foto sia chiara (evitare sfocatura, oscuramento o troppo lontano, dal soggetto), avere la foto in formato jpg o png, con le dimensioni del file di immagine non superiori a 4 MB e non inferiore a 1 KB.

Nota

Se si segue questa esercitazione, non usare il proprio viso per il training, come quando si inserisce HoloLens, non è possibile guardare da soli. Usa il volto di un collega o di un collega o di un collega.

Esecuzione di Person Maker:

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

  2. Quando la soluzione PersonMaker è aperta, assicurarsi che:

    1. La configurazione della soluzione è impostata su Debug.

    2. La piattaforma della soluzione è impostata su x86

    3. La piattaforma di destinazione è computer locale.

    4. Potrebbe anche essere necessario ripristinare i pacchetti NuGet (fare clic con il pulsante destro del mouse sulla soluzione e scegliere 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 più 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. Insert:

    1. ID da assegnare al gruppo di persone. L'ID deve essere minuscolo, senza spazi. Prendere nota di questo ID, perché sarà necessario più avanti nel progetto Unity.
    2. Nome da assegnare al gruppo di persone (può avere spazi).
  6. Fare clic sul pulsante Crea gruppo persone. Sotto il pulsante verrà visualizzato un messaggio di conferma.

Nota

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

Importante

Si noterà che è anche possibile fare clic sul pulsante Recupera un gruppo noto: questo vale 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 di persone con un gruppo noto, verrà recuperato anche un gruppo.

  1. Inserire il nome della persona che si desidera creare.

    1. Fare clic sul pulsante Crea persona .

    2. Sotto il pulsante verrà visualizzato un messaggio di conferma.

    3. Se si desidera 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 . Devono essere in formato di file JPG o PNG .

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

  5. Al termine del contatore e dopo aver visualizzato un messaggio di conferma, fare clic su Train (Esegui training) per eseguire il training del servizio.

Al termine del processo, si è pronti per passare a Unity.

Capitolo 3 - Configurare il progetto Unity

Di seguito è riportata una configurazione tipica per lo sviluppo con la 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. Inserisci MR_FaceRecognition. Assicurarsi che il tipo di progetto sia impostato su 3D. Impostare La posizione su un punto appropriato per l'utente (tenere presente che più vicino alle directory radice è preferibile). 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 di script esterni in Visual Studio 2017. Chiudere la finestra Preferenze .

    Aggiornare le preferenze dell'editor di script.

  4. Passare quindi a Impostazioni compilazione file > e impostare la piattaforma su piattaforma UWP (Universal Windows Platform), facendo clic sul pulsante Cambia piattaforma.

    Finestra Impostazioni di compilazione, passare dalla piattaforma alla piattaforma UWP.

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

    1. Il dispositivo di destinazione è impostato su HoloLens

      Per i visori VR immersive, impostare Dispositivo di destinazione su Qualsiasi dispositivo.

    2. Il tipo di compilazione è impostato su D3D

    3. L'SDK è impostato su Latest installed (Versione più recente installata)

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

    5. Compilazione ed esecuzione è impostata su Computer locale

    6. Salvare la scena e aggiungerla alla compilazione.

      1. A tale scopo, selezionare 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 di script

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

        Assegnare un nome alla nuova scena.

    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 per aprire 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 runtime di scripting deve essere sperimentale (equivalente a .NET 4.6). La modifica di questo trigger attiverà la necessità di riavviare l'editor.

      2. Il back-end di scripting 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 (disponibili sotto Impostazioni di pubblicazione), selezionare Realtà virtuale supportata, assicurarsi che Windows Realtà mista SDK sia stato aggiunto.

      Aggiornare le impostazioni X R.

  8. Tornare 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 importazione, è 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 Fotocamera principale (si noti l'ortografia!)

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

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

    4. Imposta flag di cancellazione su colore a tinta unita

    5. Impostare il colore di sfondo del componente fotocamera su Nero, Alfa 0 (Codice esadecimale: #00000000)

      configurare i componenti della fotocamera

Capitolo 5: Importare la libreria Newtonsoft.Json

Importante

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

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

Per importare la libreria:

  1. Scaricare il pacchetto Unity.

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

    Importare Newtonsoft.Json

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

  4. Assicurarsi che tutti i componenti del pacchetto siano contrassegnati 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 al servizio un'immagine di acquisizione, la analizzerà e identificherà i visi all'interno e determinerà 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 nella cartella Assets disponibile nel pannello del progetto, quindi fare clic su Crea>cartella. Chiamare la cartella Scripts.

    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 utilizzati per la deserializzazione. Questi oggetti devono essere aggiunti all'esterno dello script FaceAnalysis (sotto la parentesi graffa 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 del 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 primo richiederà al Servizio riconoscimento viso di rilevare qualsiasi possibile viso 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 metodo IdentifyFaces(), 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 Scripts nel pannello Progetto all'oggetto Fotocamera principale nel pannello Hierarchy (Gerarchia). Il nuovo componente script verrà quindi aggiunto alla fotocamera principale.

Posizionare FaceAnalysis sulla 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 che verrà acquisita, identificando i visi e determinando 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 Scripts creata in precedenza, quindi fare clic su Crea, script 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 di 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 trasferire localmente l'applicazione in HoloLens.

Prima di procedere, 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.

A questo punto si è pronti per compilare la soluzione. Dopo aver compilato la soluzione, si sarà pronti per distribuire l'applicazione.

Per avviare il processo di compilazione:

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

  2. Passare a File, Impostazioni di compilazione, fare clic su Aggiungi scene aperte.

  3. Assicurarsi di selezionare Progetti C# Unity.

    Distribuire la soluzione 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 ora la cartella all'interno del progetto Unity e chiamarla App. Quindi, con la cartella App selezionata, premere Seleziona cartella.

  5. Unity inizierà a compilare il progetto, all'esterno della cartella App.

  6. Una volta completata la compilazione di Unity(potrebbe essere necessario del 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 project (come illustrato in precedenza, MR_FaceRecognition.sln).

Capitolo 9 - Distribuzione dell'applicazione

Per eseguire la distribuzione in HoloLens:

  1. È necessario l'indirizzo IP di HoloLens (per la distribuzione remota) e assicurarsi che HoloLens sia in modalità sviluppatore. A questo scopo, è necessario:

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

  3. Nella configurazione della 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, pronte per l'avvio.

Nota

Per eseguire la distribuzione in visore VR immersive, impostare Piattaforma soluzione su Computer locale e impostare Configurazione su Debug, con x86 come piattaforma. Eseguire quindi la distribuzione 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. Assicurati che:

    • Il volto della persona non è troppo lontano e chiaramente visibile
    • L'illuminazione dell'ambiente non è troppo scura
  3. Usa 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 sfrutta 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 un'unica 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.