HoloLens (1.ª generación) y Azure 304: Reconocimiento facial


Nota

Los tutoriales de Mixed Reality Academy se han diseñado teniendo en cuenta HoloLens (1.ª generación) y los cascos envolventes de realidad mixta. Por lo tanto, creemos que es importante conservar estos tutoriales para los desarrolladores que sigan buscando instrucciones sobre el desarrollo para esos dispositivos. Estos tutoriales no se actualizarán con los conjuntos de herramientas o las interacciones más recientes que se usan para HoloLens 2. Se mantendrán para que sigan funcionando en los dispositivos compatibles. Habrá una nueva serie de tutoriales que se publicarán en el futuro que demostrarán cómo desarrollar para HoloLens 2. Este aviso se actualizará con un vínculo a esos tutoriales cuando se publiquen.


resultado de completar este curso

En este curso aprenderá a agregar funcionalidades de reconocimiento facial a una aplicación de realidad mixta, mediante Azure Cognitive Services, con Microsoft Face API.

Azure Face API es un servicio de Microsoft, que proporciona a los desarrolladores los algoritmos faciales más avanzados, todos en la nube. Face API tiene dos funciones principales: detección de caras con atributos y reconocimiento facial. Esto permite a los desarrolladores simplemente establecer un conjunto de grupos para caras y, a continuación, enviar imágenes de consulta al servicio más adelante, para determinar a quién pertenece una cara. Para más información, visite la página De reconocimiento facial de Azure.

Después de completar este curso, tendrá una aplicación holoLens de realidad mixta, que podrá hacer lo siguiente:

  1. Use un gesto de pulsación para iniciar la captura de una imagen mediante la cámara HoloLens incorporada.
  2. Envíe la imagen capturada al servicio Azure Face API .
  3. Reciba los resultados del algoritmo de Face API .
  4. Use una interfaz de usuario sencilla para mostrar el nombre de las personas coincidentes.

Esto le enseñará a obtener los resultados del servicio Face API en la aplicación de realidad mixta basada en Unity.

En la aplicación, le corresponde la forma en que integrará los resultados con el diseño. Este curso está diseñado para enseñar a integrar un servicio de Azure con el proyecto de Unity. Es su trabajo usar los conocimientos que obtiene de este curso para mejorar la aplicación de realidad mixta.

Compatibilidad con dispositivos

Curso HoloLens Cascos envolventes
Realidad mixta y Azure (304): Reconocimiento facial ✔️ ✔️

Nota

Aunque este curso se centra principalmente en HoloLens, también puede aplicar lo que aprende en este curso para Windows Mixed Reality cascos envolventes (VR). Dado que los cascos envolventes (VR) no tienen cámaras accesibles, necesitará una cámara externa conectada a su PC. A medida que siga con el curso, verá notas sobre los cambios que puede que tenga que emplear para admitir cascos envolventes (VR).

Requisitos previos

Nota:

Este tutorial está diseñado para desarrolladores que tienen experiencia básica con Unity y C#. Tenga en cuenta también que los requisitos previos y las instrucciones escritas de este documento representan lo que se ha probado y comprobado en el momento de la escritura (mayo de 2018). Puede usar el software más reciente, como se muestra en el artículo de instalación de las herramientas , aunque no debe asumirse que la información de este curso coincidirá perfectamente con lo que encontrará en el software más reciente que lo que se muestra a continuación.

Se recomienda el siguiente hardware y software para este curso:

Antes de empezar

  1. Para evitar problemas al compilar este proyecto, se recomienda encarecidamente crear el proyecto mencionado en este tutorial en una carpeta raíz o casi raíz (las rutas de acceso de carpeta largas pueden causar problemas en tiempo de compilación).
  2. Configure y pruebe holoLens. Si necesita compatibilidad con la configuración de HoloLens, asegúrese de visitar el artículo de configuración de HoloLens.
  3. Es una buena idea realizar la calibración y la optimización del sensor al empezar a desarrollar una nueva aplicación de HoloLens (a veces puede ayudar a realizar esas tareas para cada usuario).

Para obtener ayuda sobre calibración, siga este vínculo al artículo Calibración de HoloLens.

Para obtener ayuda sobre la optimización de sensores, siga este vínculo al artículo Optimización del sensor de HoloLens.

Capítulo 1: Azure Portal

Para usar el servicio Face API en Azure, deberá configurar una instancia del servicio para que esté disponible para la aplicación.

  1. En primer lugar, inicie sesión en Azure Portal.

    Nota

    Si aún no tiene una cuenta de Azure, deberá crear una. Si sigue este tutorial en una situación de clase o laboratorio, pida a su instructor o a uno de los proctores que le ayuden a configurar su nueva cuenta.

  2. Una vez que haya iniciado sesión, haga clic en Nuevo en la esquina superior izquierda y busque Face API, presione Entrar.

    búsqueda de Face API

    Nota

    Es posible que la palabra New se haya reemplazado por Create a resource (Crear un recurso) en portales más recientes.

  3. La nueva página proporcionará una descripción del servicio Face API . En la parte inferior izquierda de este símbolo del sistema, seleccione el botón Crear para crear una asociación con este servicio.

    información de face api

  4. Una vez que haya hecho clic en Crear:

    1. Inserte el nombre deseado para esta instancia de servicio.

    2. Seleccione una suscripción.

    3. Seleccione el plan de tarifa adecuado para usted, si es la primera vez que se crea un servicio Face API, debe estar disponible un nivel gratuito (denominado F0).

    4. Elija un grupo de recursos o cree uno nuevo. Un grupo de recursos proporciona una manera de supervisar, controlar el acceso, aprovisionar y administrar la facturación de una colección de recursos de Azure. Se recomienda mantener todos los servicios de Azure asociados a un único proyecto (por ejemplo, estos laboratorios) en un grupo de recursos común).

      Si desea obtener más información sobre los grupos de recursos de Azure, visite el artículo sobre el grupo de recursos.

    5. La aplicación para UWP, Person Maker, que usas más adelante, requiere el uso de "Oeste de EE. UU." para la ubicación.

    6. También deberá confirmar que ha comprendido los Términos y Condiciones aplicados a este Servicio.

    7. Seleccione Crear.*

      creación de un servicio face api

  5. Una vez que haya hecho clic en Crear,* tendrá que esperar a que se cree el servicio, esto puede tardar un minuto.

  6. Una notificación aparecerá en el portal una vez creada la instancia de servicio.

    notificación de creación de servicios

  7. Haga clic en las notificaciones para explorar la nueva instancia de servicio.

    Ir a la notificación de recursos

  8. Cuando esté listo, haga clic en el botón Ir al recurso en la notificación para explorar la nueva instancia de servicio.

    claves de api de face de acceso

  9. En este tutorial, la aplicación tendrá que realizar llamadas al servicio, que se realiza mediante el uso de la suscripción del servicio "key". En la página Inicio rápido , del servicio Face API , el primer punto es el número 1, para Obtener las claves.

  10. En la página Servicio , seleccione el hipervínculo claves azules (si está en la página Inicio rápido) o el vínculo Claves en el menú de navegación de servicios (a la izquierda, indicado por el icono "clave", para mostrar las claves).

    Nota

    Tome nota de cualquiera de las claves y guídelo, ya que lo necesitará más adelante.

Capítulo 2: Uso de la aplicación para UWP "Person Maker"

Asegúrate de descargar la aplicación para UWP precompilada llamada Person Maker. Esta aplicación no es el producto final de este curso, solo una herramienta para ayudarle a crear las entradas de Azure, en las que se basará el proyecto posterior.

Person Maker permite crear entradas de Azure, que están asociadas a personas y grupos de personas. La aplicación colocará toda la información necesaria en un formato que, posteriormente, podrá usar FaceAPI para reconocer las caras de las personas que ha agregado.

[IMPORTANTE] Person Maker usa algunas limitaciones básicas para garantizar que no supere el número de llamadas de servicio por minuto para el nivel de suscripción gratuita. El texto verde de la parte superior cambiará a rojo y se actualizará como "ACTIVO" cuando se produzca una limitación; Si este es el caso, basta con esperar a la aplicación (esperará hasta que pueda continuar accediendo al servicio face, actualizando como "IN-ACTIVE" cuando pueda usarlo de nuevo).

Esta aplicación usa las bibliotecas Microsoft.ProjectOxford.Face , lo que le permitirá hacer un uso completo de Face API. Esta biblioteca está disponible de forma gratuita como paquete NuGet. Para obtener más información sobre esto y similares, las API se aseguran de visitar el artículo de referencia de API.

Nota

Estos son solo los pasos necesarios, las instrucciones para hacer estas cosas están más abajo del documento. La aplicación Person Maker le permitirá:

  • Cree un grupo de personas, que es un grupo compuesto por varias personas a las que desea asociar. Con su cuenta de Azure, puede hospedar varios grupos de personas.

  • Cree una persona, que es miembro de un grupo de personas. Cada persona tiene una serie de imágenes de Face asociadas.

  • Asigne imágenes de caras a una persona para permitir que el servicio Azure Face API reconozca a una persona por la cara correspondiente.

  • Entrene el servicio Azure Face API.

Ten en cuenta, así que para entrenar esta aplicación para reconocer a las personas, necesitarás diez (10) fotos de primer plano de cada persona que quieras agregar a tu grupo de personas. La Windows 10 Cam App puede ayudarle a tomarlos. Debe asegurarse de que cada foto sea clara (evite desenfoque, o esté demasiado lejos del asunto), tenga la foto en formato de archivo jpg o png, con el tamaño del archivo de imagen que no sea mayor de 4 MB y no menos de 1 KB.

Nota

Si sigue este tutorial, no use su propia cara para el entrenamiento, ya que al colocar HoloLens en, no puede mirarse usted mismo. Use la cara de un compañero o estudiante.

Ejecución de Person Maker:

  1. Abra la carpeta PersonMaker y haga doble clic en la solución PersonMaker para abrirla con Visual Studio.

  2. Una vez abierta la solución PersonMaker , asegúrese de que:

    1. La configuración de la solución se establece en Depurar.

    2. La plataforma de soluciones se establece en x86.

    3. La plataforma de destino es máquina local.

    4. También puede que tenga que restaurar paquetes NuGet (haga clic con el botón derecho en la solución y seleccione Restaurar paquetes NuGet).

  3. Haga clic en Equipo local y se iniciará la aplicación. Tenga en cuenta que, en pantallas más pequeñas, es posible que todo el contenido no esté visible, aunque puede desplazarse más hacia abajo para verlo.

    interfaz de usuario de person maker

  4. Inserte la clave de autenticación de Azure, que debe tener, desde el servicio Face API en Azure.

  5. Insertar:

    1. Identificador que desea asignar al grupo de personas. El identificador debe estar en minúsculas, sin espacios. Anote este identificador, ya que será necesario más adelante en el proyecto de Unity.
    2. El nombre que desea asignar al grupo de personas (puede tener espacios).
  6. Presione el botón Crear grupo de personas . Un mensaje de confirmación debe aparecer debajo del botón.

Nota

Si tiene un error "Acceso denegado", compruebe la ubicación establecida para el servicio de Azure. Como se indicó anteriormente, esta aplicación está diseñada para "Oeste de EE. UU.".

Importante

Observará que también puede hacer clic en el botón Capturar un grupo conocido : esto es para si ya ha creado un grupo de personas y desea usarlo, en lugar de crear uno nuevo. Tenga en cuenta que, si hace clic en Crear un grupo de personas con un grupo conocido, también capturará un grupo.

  1. Inserte el nombre de la persona que desea crear.

    1. Haga clic en el botón Crear persona .

    2. Un mensaje de confirmación debe aparecer debajo del botón.

    3. Si desea eliminar una persona que ha creado anteriormente, puede escribir el nombre en el cuadro de texto y presionar Eliminar persona.

  2. Asegúrese de que conoce la ubicación de diez (10) fotos de la persona que desea agregar a su grupo.

  3. Presione Crear y abrir carpeta para abrir el Explorador de Windows en la carpeta asociada a la persona. Agregue las diez (10) imágenes en la carpeta . Estos deben ser de formato de archivo JPG o PNG .

  4. Haga clic en Enviar a Azure. Un contador le mostrará el estado del envío, seguido de un mensaje cuando se haya completado.

  5. Una vez finalizado el contador y se ha mostrado un mensaje de confirmación, haga clic en Entrenar para entrenar el servicio.

Una vez completado el proceso, está listo para pasar a Unity.

Capítulo 3: Configuración del proyecto de Unity

A continuación se muestra una configuración típica para desarrollar con realidad mixta y, como tal, es una buena plantilla para otros proyectos.

  1. Abra Unity y haga clic en Nuevo.

    Inicie el nuevo proyecto de Unity.

  2. Ahora tendrá que proporcionar un nombre de proyecto de Unity. Inserte MR_FaceRecognition. Asegúrese de que el tipo de proyecto está establecido en 3D. Establezca la ubicación en algún lugar adecuado para usted (recuerde que más cerca de los directorios raíz es mejor). A continuación, haga clic en Crear proyecto.

    Proporcione detalles para el nuevo proyecto de Unity.

  3. Con Unity abierto, vale la pena comprobar que el Editor de scripts predeterminado está establecido en Visual Studio. Vaya a Editar > preferencias y, a continuación, en la nueva ventana, vaya a Herramientas externas. Cambie el Editor de scripts externos a Visual Studio 2017. Cierre la ventana Preferencias.

    Actualizar la preferencia del editor de scripts.

  4. A continuación, vaya a Configuración de compilación de archivos > y cambie la plataforma a Plataforma universal de Windows, haciendo clic en el botón Cambiar plataforma.

    Ventana Configuración de compilación, cambie la plataforma a UWP.

  5. Vaya a Configuración de compilación de archivos > y asegúrese de que:

    1. El dispositivo de destino está establecido en HoloLens.

      Para los cascos envolventes, establezca Dispositivo de destino en Cualquier dispositivo.

    2. El tipo de compilación se establece en D3D.

    3. El SDK se establece en Latest installed (Versión más reciente instalada)

    4. La versión de Visual Studio se establece en Latest installed (Versión más reciente instalada)

    5. Compilar y ejecutar está establecido en Equipo local

    6. Guarde la escena y agréguela a la compilación.

      1. Para ello, seleccione Agregar escenas abiertas. Aparecerá una ventana de guardado.

        Haga clic en el botón Agregar escenas abiertas.

      2. Seleccione el botón Nueva carpeta para crear una nueva carpeta, asígnela el nombre Scenes.

        Creación de una carpeta de scripts

      3. Abra la carpeta Escenas recién creada y, a continuación, en el campo Nombre de archivo: texto, escriba FaceRecScene y presione Guardar.

        Asigne un nombre a la nueva escena.

    7. La configuración restante, en Configuración de compilación, debe dejarse como predeterminada por ahora.

  6. En la ventana Configuración de compilación, haga clic en el botón Configuración del reproductor ; se abrirá el panel relacionado en el espacio donde se encuentra el Inspector .

    Abra la configuración del reproductor.

  7. En este panel, es necesario comprobar algunas opciones de configuración:

    1. En la pestaña Otros valores:

      1. La versióndel entorno de ejecución de scripting debe ser experimental (equivalente a .NET 4.6). Al cambiar esto, se desencadenará la necesidad de reiniciar el Editor.

      2. El back-end de scripting debe ser .NET

      3. El nivel de compatibilidad de API debe ser .NET 4.6

        Actualice otras opciones de configuración.

    2. En la pestaña Configuración de publicación , en Funcionalidades, active:

      • InternetClient

      • Cámara web

        Actualización de la configuración de publicación.

    3. Más abajo del panel, en Configuración de XR (que se encuentra a continuación de Configuración de publicación), marque Virtual Reality Supported (Compatible con La realidad virtual), asegúrese de que se agrega el SDK de Windows Mixed Reality.

      Actualice la configuración de X R.

  8. De nuevo en Configuración de compilación, los proyectos de C# de Unity ya no están atenuados; marque la casilla situada junto a esta.

  9. Cierre la ventana Build Settings (Configuración de compilación).

  10. Guarde la escena y el proyecto (ARCHIVO > SAVE SCENE/FILE > SAVE PROJECT).

Capítulo 4: Configuración de la cámara principal

Importante

Si desea omitir el componente De configuración de Unity de este curso y continuar directamente en el código, no dude en descargar este archivo .unitypackage e importarlo en el proyecto como un paquete personalizado. Tenga en cuenta que este paquete también incluye la importación del archivo DLL newtonsoft, que se trata en el capítulo 5. Con esta importación, puede continuar desde el capítulo 6.

  1. En el Panel jerarquía , seleccione la Cámara principal.

  2. Una vez seleccionado, podrá ver todos los componentes de la cámara principal en el panel inspector.

    1. El objeto Camera debe denominarse Cámara principal (tenga en cuenta la ortografía).

    2. La etiqueta de cámara principal debe establecerse en MainCamera (tenga en cuenta la ortografía).

    3. Asegúrese de que la posición de transformación está establecida en 0, 0, 0

    4. Establecer marcas de borrar en color sólido

    5. Establezca el color de fondo del componente de cámara en Negro, Alfa 0 (código hexadecimal: #000000000)

      configurar componentes de cámara

Capítulo 5: Importación de la biblioteca Newtonsoft.Json

Importante

Si importó el archivo '.unitypackage' en el último capítulo, puede omitir este capítulo.

Para ayudarle a deserializar y serializar objetos recibidos y enviados al Bot Service debe descargar la biblioteca Newtonsoft.Json. Encontrará una versión compatible ya organizada con la estructura de carpetas de Unity correcta en este archivo de paquete de Unity.

Para importar la biblioteca:

  1. Descargue el paquete de Unity.

  2. Haga clic en Activos, Importar paquete, Paquete personalizado.

    Importación de Newtonsoft.Json

  3. Busque el paquete de Unity que ha descargado y haga clic en Abrir.

  4. Asegúrese de que todos los componentes del paquete estén marcados y haga clic en Importar.

    Importación de los recursos de Newtonsoft.Json

Capítulo 6: Creación de la clase FaceAnalysis

El propósito de la clase FaceAnalysis es hospedar los métodos necesarios para comunicarse con azure Face Recognition Service.

  • Después de enviar al servicio una imagen de captura, la analizará e identificará las caras dentro y determinará si alguna pertenece a una persona conocida.
  • Si se encuentra una persona conocida, esta clase mostrará su nombre como texto de la interfaz de usuario en la escena.

Para crear la clase FaceAnalysis :

  1. Haga clic con el botón derecho en la carpeta Assets ubicada en el Panel de proyectos y, a continuación, haga clic en Crear>carpeta. Llame a la carpeta Scripts.

    Cree la clase FaceAnalysis.

  2. Haga doble clic en la carpeta que acaba de crear para abrirla.

  3. Haga clic con el botón derecho dentro de la carpeta y, a continuación, haga clic en Crear>script de C#. Llame al script FaceAnalysis.

  4. Haga doble clic en el nuevo script FaceAnalysis para abrirlo con Visual Studio 2017.

  5. Escriba los siguientes espacios de nombres encima de la clase FaceAnalysis :

        using Newtonsoft.Json;
        using System.Collections;
        using System.Collections.Generic;
        using System.IO;
        using System.Text;
        using UnityEngine;
        using UnityEngine.Networking;
    
  6. Ahora debe agregar todos los objetos que se usan para deserializar. Estos objetos deben agregarse fuera del script FaceAnalysis (debajo del corchete inferior).

        /// <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. Los métodos Start() y Update() no se usarán, por lo tanto, elimínelos ahora.

  8. Dentro de la clase FaceAnalysis , agregue las siguientes variables:

        /// <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

    Reemplace la clave y personGroupId por la clave de servicio y el identificador del grupo que creó anteriormente.

  9. Agregue el método Awake(), que inicializa la clase , agregando la clase ImageCapture a la cámara principal y llama al método de creación 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. Agregue el método CreateLabel(), que crea el objeto Label para mostrar el resultado del análisis:

        /// <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. Agregue el método DetectFacesFromImage() y GetImageAsByteArray(). El primero solicitará al servicio de reconocimiento facial que detecte cualquier cara posible en la imagen enviada, mientras que esta última es necesaria para convertir la imagen capturada en una matriz de bytes:

        /// <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. Agregue el método IdentifyFaces(), que solicita al servicio de reconocimiento facial que identifique cualquier cara conocida detectada anteriormente en la imagen enviada. La solicitud devolverá un identificador de la persona identificada, pero no el nombre:

        /// <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. Agregue el método GetPerson(). Al proporcionar el identificador de persona, este método solicita al servicio de reconocimiento facial que devuelva el nombre de la persona identificada:

        /// <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. Recuerde Guardar los cambios antes de volver al Editor de Unity.

  15. En el Editor de Unity, arrastre el script FaceAnalysis desde la carpeta Scripts del panel Proyecto al objeto Cámara principal en el panel Jerarquía. El nuevo componente de script se agregará a la cámara principal.

Colocar FaceAnalysis en la cámara principal

Capítulo 7: Creación de la clase ImageCapture

El propósito de la clase ImageCapture es hospedar los métodos necesarios para comunicarse con azure Face Recognition Service para analizar la imagen que va a capturar, identificar caras en ella y determinar si pertenece a una persona conocida. Si se encuentra una persona conocida, esta clase mostrará su nombre como texto de la interfaz de usuario en la escena.

Para crear la clase ImageCapture :

  1. Haga clic con el botón derecho en la carpeta Scripts que ha creado anteriormente y, a continuación, haga clic en Crear, Script de C#. Llame al script ImageCapture.

  2. Haga doble clic en el nuevo script ImageCapture para abrirlo con Visual Studio 2017.

  3. Escriba los siguientes espacios de nombres encima de la clase ImageCapture:

        using System.IO;
        using System.Linq;
        using UnityEngine;
        using UnityEngine.XR.WSA.Input;
        using UnityEngine.XR.WSA.WebCam;
    
  4. Dentro de la clase ImageCapture , agregue las siguientes variables:

        /// <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. Agregue los métodos Awake() e Start() necesarios para inicializar la clase y permitir que HoloLens capture los gestos del usuario:

        /// <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. Agregue la función TapHandler() a la que se llama cuando el usuario realiza un gesto de pulsación :

        /// <summary>
        /// Respond to Tap Input.
        /// </summary>
        private void TapHandler(TappedEventArgs obj)
        {
            tapsCount++;
            ExecuteImageCaptureAndAnalysis();
        }
    
  7. Agregue el método ExecuteImageCaptureAndAnalysis(), que iniciará el proceso de captura de imágenes:

        /// <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. Agregue los controladores a los que se llama cuando se ha completado el proceso de captura de fotos:

        /// <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. Recuerde Guardar los cambios antes de volver al Editor de Unity.

Capítulo 8: Creación de la solución

Para realizar una prueba exhaustiva de la aplicación, deberá transferirla localmente a HoloLens.

Antes de hacerlo, asegúrese de que:

  • Todas las configuraciones mencionadas en el capítulo 3 se establecen correctamente.
  • El script FaceAnalysis se adjunta al objeto Cámara principal.
  • Tanto la clave de autenticación como el identificador de grupo se han establecido en el script FaceAnalysis .

Este punto está listo para compilar la solución. Una vez compilada la solución, estará listo para implementar la aplicación.

Para comenzar el proceso de compilación:

  1. Para guardar la escena actual, haga clic en Archivo, Guardar.

  2. Vaya a Archivo, Configuración de compilación, haga clic en Agregar escenas abiertas.

  3. Asegúrese de marcar proyectos de C# de Unity.

    Implementación de la solución de Visual Studio

  4. Presione Compilar. Al hacerlo, Unity iniciará una ventana de Explorador de archivos, donde debe crear y, a continuación, seleccionará una carpeta en la que compilará la aplicación. Cree esa carpeta ahora, en el proyecto de Unity y llámala Aplicación. A continuación, con la carpeta Aplicación seleccionada, presione Seleccionar carpeta.

  5. Unity comenzará a compilar el proyecto, en la carpeta Aplicación.

  6. Una vez que Unity haya terminado de compilarse (puede tardar algún tiempo), se abrirá una ventana de Explorador de archivos en la ubicación de la compilación.

    Implementación de la solución desde Visual Studio

  7. Abra la carpeta Aplicación y, a continuación, abra la nueva solución de proyecto (como se ha visto anteriormente, MR_FaceRecognition.sln).

Capítulo 9: Implementación de la aplicación

Para implementar en HoloLens:

  1. Necesitará la dirección IP de HoloLens (para la implementación remota) y para asegurarse de que HoloLens está en modo de desarrollador. Para ello, siga estos pasos:

    1. Mientras llevas tu HoloLens, abre la configuración.
    2. Vaya a Opciones avanzadas de Red & Internet > Wi-Fi >
    3. Anote la dirección IPv4 .
    4. A continuación, vuelva a Configuración y, a continuación, a Actualizar & Seguridad > para desarrolladores.
    5. Establezca el modo de desarrollador activado.
  2. Vaya a la nueva compilación de Unity (la carpeta Aplicación ) y abra el archivo de solución con Visual Studio.

  3. En Configuración de la solución, seleccione Depurar.

  4. En la Plataforma de soluciones, seleccione x86, Máquina remota.

    Cambio de la configuración de la solución

  5. Vaya al menú Compilar y haga clic en Implementar solución para transferir localmente la aplicación a HoloLens.

  6. La aplicación debería aparecer ahora en la lista de aplicaciones instaladas en HoloLens, lista para iniciarse.

Nota

Para realizar la implementación en cascos envolventes, establezca la Plataforma de soluciones en Máquina local y establezca la configuración en Depurar, con x86 como plataforma. A continuación, implemente en el equipo local, con el menú Compilar y seleccione Implementar solución.

Capítulo 10: Uso de la aplicación

  1. Con HoloLens, inicie la aplicación.

  2. Examine la persona que ha registrado con Face API. Asegúrese de lo siguiente:

    • La cara de la persona no está demasiado distante y claramente visible
    • La iluminación del entorno no es demasiado oscura
  3. Use el gesto de pulsación para capturar la imagen de la persona.

  4. Espere a que la aplicación envíe la solicitud de análisis y reciba una respuesta.

  5. Si la persona se ha reconocido correctamente, el nombre de la persona aparecerá como texto de la interfaz de usuario.

  6. Puede repetir el proceso de captura mediante el gesto de pulsación cada pocos segundos.

La aplicación de Azure Face API finalizada

Enhorabuena, ha creado una aplicación de realidad mixta que aprovecha el servicio Azure Face Recognition para detectar caras dentro de una imagen e identificar las caras conocidas.

resultado de completar este curso

Ejercicios extra

Ejercicio 1

Azure Face API es lo suficientemente eficaz como para detectar hasta 64 caras en una sola imagen. Amplíe la aplicación para que pueda reconocer dos o tres caras, entre muchas otras personas.

Ejercicio 2

Azure Face API también puede proporcionar todo tipo de información de atributos. Intégrelo en la aplicación. Esto podría ser aún más interesante, cuando se combina con Emotion API.