HoloLens (1.ª geração) e Azure 304: Reconhecimento facial


Nota

Os tutoriais da Academia Mixed Reality foram concebidos com o HoloLens (1.ª geração) e Mixed Reality Headsets Envolventes em mente. Como tal, consideramos importante deixar estes tutoriais em vigor para os programadores que ainda procuram orientações no desenvolvimento desses dispositivos. Estes tutoriais não serão atualizados com os conjuntos de ferramentas ou interações mais recentes que estão a ser utilizados para HoloLens 2. Serão mantidos para continuar a trabalhar nos dispositivos suportados. Haverá uma nova série de tutoriais que serão publicados no futuro que demonstrarão como se desenvolver para HoloLens 2. Este aviso será atualizado com uma ligação para esses tutoriais quando forem publicados.


resultado da conclusão deste curso

Neste curso, irá aprender a adicionar capacidades de reconhecimento facial a uma aplicação de realidade mista, através dos Serviços Cognitivos do Azure, com a API Face da Microsoft.

A API Face do Azure é um serviço Microsoft, que fornece aos programadores os algoritmos faciais mais avançados, tudo na cloud. A API Face tem duas funções principais: deteção facial com atributos e reconhecimento facial. Isto permite que os programadores definam simplesmente um conjunto de grupos para rostos e, em seguida, enviem imagens de consulta para o serviço mais tarde, para determinar a quem pertence um rosto. Para obter mais informações, visite a página Reconhecimento Facial do Azure.

Depois de concluir este curso, terá uma aplicação holoLens de realidade mista, que poderá fazer o seguinte:

  1. Utilize um Gesto de Toque para iniciar a captura de uma imagem com a câmara holoLens a bordo.
  2. Envie a imagem capturada para o serviço API Face do Azure .
  3. Receba os resultados do algoritmo da API Face .
  4. Utilize uma Interface de Utilizador simples para apresentar o nome das pessoas correspondentes.

Isto irá ensiná-lo a obter os resultados do Serviço de API Face para a sua aplicação de realidade mista baseada no Unity.

Na sua aplicação, cabe-lhe a si saber como irá integrar os resultados com a sua estrutura. Este curso foi concebido para lhe ensinar a integrar um Serviço do Azure no seu Projeto do Unity. O seu trabalho é utilizar os conhecimentos obtidos neste curso para melhorar a sua aplicação de realidade mista.

Suporte de dispositivos

Curso HoloLens Auscultadores envolventes
MR e Azure 304: Reconhecimento facial ✔️ ✔️

Nota

Embora este curso se concentre principalmente no HoloLens, também pode aplicar o que aprende neste curso a Windows Mixed Reality headsets envolventes (VR). Uma vez que os auscultadores envolventes (VR) não têm câmaras acessíveis, precisará de uma câmara externa ligada ao PC. À medida que acompanha o curso, verá notas sobre quaisquer alterações que possa ter de utilizar para suportar headsets envolventes (VR).

Pré-requisitos

Nota

Este tutorial foi concebido para programadores com experiência básica com o Unity e c#. Tenha também em atenção que os pré-requisitos e as instruções escritas neste documento representam o que foi testado e verificado no momento da escrita (maio de 2018). Pode utilizar o software mais recente, conforme indicado no artigo instalar as ferramentas , embora não se deva presumir que as informações neste curso corresponderão perfeitamente ao que encontrará no software mais recente do que o indicado abaixo.

Recomendamos o seguinte hardware e software para este curso:

Antes de começar

  1. Para evitar problemas ao criar este projeto, é fortemente sugerido que crie o projeto mencionado neste tutorial numa pasta de raiz ou quase raiz (os caminhos de pastas longas podem causar problemas no tempo de compilação).
  2. Configure e teste o HoloLens. Se precisar de suporte para configurar o HoloLens, certifique-se de que visita o artigo de configuração do HoloLens.
  3. É uma boa ideia executar a Calibragem e a Otimização do Sensor ao começar a desenvolver uma nova Aplicação HoloLens (por vezes, pode ajudar a executar essas tarefas para cada utilizador).

Para obter ajuda sobre a Calibragem, siga esta ligação para o artigo Calibragem do HoloLens.

Para obter ajuda sobre a Otimização do Sensor, siga esta ligação para o artigo Otimização do Sensor do HoloLens.

Capítulo 1 - Portal do Azure

Para utilizar o serviço API Face no Azure, terá de configurar uma instância do serviço para ser disponibilizada à sua aplicação.

  1. Primeiro, inicie sessão no Portal do Azure.

    Nota

    Se ainda não tiver uma conta do Azure, terá de criar uma. Se estiver a seguir este tutorial numa situação de sala de aula ou laboratório, peça ajuda ao seu instrutor ou a um dos responsáveis pela configuração da sua nova conta.

  2. Depois de iniciar sessão, clique em Novo no canto superior esquerdo e procure API Face, prima Enter.

    procurar api facial

    Nota

    A palavra Novo pode ter sido substituída por Criar um recurso, em portais mais recentes.

  3. A nova página irá fornecer uma descrição do serviço API Face . Na parte inferior esquerda deste pedido, selecione o botão Criar para criar uma associação com este serviço.

    informações da api face

  4. Depois de clicar em Criar:

    1. Insira o nome pretendido para esta instância de serviço.

    2. Selecione uma subscrição.

    3. Selecione o escalão de preço adequado para si, se esta for a primeira vez que cria um Serviço de API Face, deverá estar disponível um escalão gratuito (denominado F0).

    4. Escolha um Grupo de Recursos ou crie um novo. Um grupo de recursos fornece uma forma de monitorizar, controlar o acesso, aprovisionar e gerir a faturação de uma coleção de recursos do Azure. É recomendado manter todos os serviços do Azure associados a um único projeto (por exemplo, estes laboratórios) num grupo de recursos comum).

      Se quiser ler mais sobre os Grupos de Recursos do Azure, visite o artigo do grupo de recursos.

    5. A aplicação UWP, Person Maker, que utiliza mais tarde, requer a utilização de "E.U.A. Oeste" para localização.

    6. Também terá de confirmar que compreendeu os Termos e Condições aplicados a este Serviço.

    7. Selecione Criar.*

      criar serviço de api face

  5. Depois de clicar em Criar,* terá de aguardar pela criação do serviço, o que poderá demorar um minuto.

  6. Será apresentada uma notificação no portal assim que a instância do Serviço for criada.

    notificação de criação de serviços

  7. Clique nas notificações para explorar a nova instância do Serviço.

    ir para notificação de recursos

  8. Quando estiver pronto, clique no botão Ir para recurso na notificação para explorar a nova instância do Serviço.

    aceder a chaves de api face

  9. Neste tutorial, a sua aplicação terá de efetuar chamadas para o seu serviço, o que é feito através da "chave" da subscrição do seu serviço. Na página Início rápido , do serviço API Face , o primeiro ponto é o número 1, para Agarrar as chaves.

  10. Na página Serviço , selecione a hiperligação Blue Keys (se estiver na página Início rápido) ou a ligação Chaves no menu de navegação dos serviços (à esquerda, indicada pelo ícone 'chave') para revelar as suas chaves.

    Nota

    Tome nota de qualquer uma das chaves e proteja-a, pois irá precisar dela mais tarde.

Capítulo 2 – Utilizar a aplicação UWP "Person Maker"

Certifique-se de que transfere a Aplicação UWP pré-criada denominada Criador de Pessoas. Esta aplicação não é o produto final deste curso, apenas uma ferramenta para o ajudar a criar as suas entradas do Azure, em que o projeto posterior irá depender.

O Criador de Pessoas permite-lhe criar entradas do Azure, que estão associadas a pessoas e grupos de pessoas. A aplicação colocará todas as informações necessárias num formato que, posteriormente, pode ser utilizado pela FaceAPI para reconhecer os rostos das pessoas que adicionou.

[IMPORTANTE] O Criador de Pessoas utiliza alguma limitação básica para ajudar a garantir que não excede o número de chamadas de serviço por minuto para o escalão de subscrição gratuito. O texto verde na parte superior mudará para vermelho e será atualizado como "ATIVO" quando a limitação estiver a ocorrer; Se for este o caso, basta aguardar pela aplicação (aguardará até poder continuar a aceder ao serviço face, atualizando como "IN-ACTIVE" quando puder utilizá-la novamente).

Esta aplicação utiliza as bibliotecas Microsoft.ProjectOxford.Face , que lhe permitirão utilizar plenamente a API Face. Esta biblioteca está disponível gratuitamente como Um Pacote NuGet. Para obter mais informações sobre esta situação e apIs semelhantes, certifique-se de que visita o artigo de referência da API.

Nota

Estes são apenas os passos necessários. As instruções sobre como fazer estas ações estão mais abaixo no documento. A aplicação Criador de Pessoas permitir-lhe-á:

  • Crie um Grupo de Pessoas, que é um grupo composto por várias pessoas que pretende associar ao mesmo. Com a sua conta do Azure, pode alojar vários Grupos de Pessoas.

  • Crie uma Pessoa, que é membro de um Grupo de Pessoas. Cada pessoa tem várias imagens de Rosto associadas à mesma.

  • Atribua imagens faciais a uma Pessoa para permitir que o Serviço de API Face do Azure reconheça uma Pessoa pelo rosto correspondente.

  • Preparar o serviço API Face do Azure.

Tenha em atenção que, para preparar esta aplicação para reconhecer pessoas, precisará de dez (10) fotografias de perto de cada pessoa que pretende adicionar ao Seu Grupo de Pessoas. A Aplicação Windows 10 Cam pode ajudá-lo a tirar estes passos. Tem de garantir que cada fotografia é clara (evite desfocar, ocultar ou estar demasiado longe do assunto), ter a fotografia no formato de ficheiro jpg ou png, sendo que o tamanho do ficheiro de imagem não é superior a 4 MB e não inferior a 1 KB.

Nota

Se estiver a seguir este tutorial, não utilize a sua própria cara para a preparação, pois quando colocar o HoloLens, não pode olhar para si próprio. Utilize o rosto de um colega ou colega.

Criador de Pessoas Em Execução:

  1. Abra a pasta PersonMaker e faça duplo clique na solução PersonMaker para abri-la com o Visual Studio.

  2. Assim que a solução PersonMaker estiver aberta, certifique-se de que:

    1. A Configuração da Solução está definida como Depuração.

    2. A Plataforma de Soluções está definida como x86

    3. A Plataforma de Destino é Máquina Local.

    4. Também poderá ter de Restaurar Pacotes NuGet (clique com o botão direito do rato na Solução e selecione Restaurar Pacotes NuGet).

  3. Clique em Máquina Local e a aplicação será iniciada. Tenha em atenção que, em ecrãs mais pequenos, todos os conteúdos podem não estar visíveis, embora possa deslocar-se mais para baixo para o ver.

    interface de utilizador do criador de pessoas

  4. Insira a Chave de Autenticação do Azure, que deve ter, a partir do serviço API Face no Azure.

  5. Inserir:

    1. O ID que pretende atribuir ao Grupo de Pessoas. O ID tem de estar em minúsculas, sem espaços. Tome nota deste ID, uma vez que será necessário mais tarde no seu projeto do Unity.
    2. O Nome que pretende atribuir ao Grupo de Pessoas (pode ter espaços).
  6. Prima o botão Criar Grupo de Pessoas . Deverá ser apresentada uma mensagem de confirmação por baixo do botão.

Nota

Se tiver um erro "Acesso Negado", verifique a localização que definiu para o serviço do Azure. Conforme indicado acima, esta aplicação foi concebida para "E.U.A. Oeste".

Importante

Irá reparar que também pode clicar no botão Obter um Grupo Conhecido : é para se já tiver criado um grupo de pessoas e pretender utilizá-lo, em vez de criar um novo. Tenha em atenção que, se clicar em Criar um Grupo de Pessoas com um grupo conhecido, também irá obter um grupo.

  1. Insira o Nome da Pessoa que pretende criar.

    1. Clique no botão Criar Pessoa .

    2. Deverá ser apresentada uma mensagem de confirmação por baixo do botão.

    3. Se quiser eliminar uma pessoa que criou anteriormente, pode escrever o nome na caixa de texto e premir Eliminar Pessoa

  2. Certifique-se de que sabe a localização de dez (10) fotografias da pessoa que pretende adicionar ao seu grupo.

  3. Prima Criar e Abrir Pasta para abrir o Explorador do Windows na pasta associada à pessoa. Adicione as dez (10) imagens na pasta. Estes têm de ser de formato de ficheiro JPG ou PNG .

  4. Clique em Submeter para o Azure. Um contador irá mostrar-lhe o estado da submissão, seguido de uma mensagem quando estiver concluída.

  5. Assim que o contador terminar e for apresentada uma mensagem de confirmação, clique em Preparar para preparar o seu Serviço.

Assim que o processo estiver concluído, estará pronto para avançar para o Unity.

Capítulo 3 - Configurar o projeto unity

Segue-se uma configuração típica para desenvolver com realidade mista e, como tal, é um bom modelo para outros projetos.

  1. Abra o Unity e clique em Novo.

    Inicie um novo projeto do Unity.

  2. Agora, terá de fornecer um nome do Projeto unity. Inserir MR_FaceRecognition. Certifique-se de que o tipo de projeto está definido como 3D. Defina a Localização para um local adequado para si (lembre-se de que é melhor estar mais perto dos diretórios de raiz). Em seguida, clique em Criar projeto.

    Forneça detalhes para o novo projeto do Unity.

  3. Com o Unity aberto, vale a pena verificar se o Editor de Scripts predefinido está definido como Visual Studio. Aceda a Editar > Preferências e, em seguida, a partir da nova janela, navegue para Ferramentas Externas. Altere o Editor de Scripts Externos para o Visual Studio 2017. Feche a janela Preferências .

    Atualizar a preferência do editor de scripts.

  4. Em seguida, aceda a Definições de Compilação de Ficheiros > e mude a plataforma para Plataforma Universal do Windows, clicando no botão Mudar de Plataforma.

    Janela Definições de Compilação, mude de plataforma para UWP.

  5. Aceda a Definições de Compilação de Ficheiros > e certifique-se de que:

    1. O Dispositivo de Destino está definido como HoloLens

      Para os headsets envolventes, defina Dispositivo de Destino como Qualquer Dispositivo.

    2. O Tipo de Compilação está definido como D3D

    3. O SDK está definido como Instalado mais recentemente

    4. A Versão do Visual Studio está definida como Mais Recente instalada

    5. A compilação e a execução estão definidas como Máquina Local

    6. Guarde a cena e adicione-a à compilação.

      1. Faça-o ao selecionar Adicionar Cenas Abertas. Será apresentada uma janela guardar.

        Clique no botão Adicionar cenas abertas

      2. Selecione o botão Nova pasta , para criar uma nova pasta, atribua-lhe o nome Cenas.

        Criar nova pasta de scripts

      3. Abra a pasta Cenas recentemente criada e, em seguida, no campo Nome do ficheiro: texto, escreva FaceRecScene e, em seguida, prima Guardar.

        Dê um nome à nova cena.

    7. As restantes definições, em Definições de Compilação, devem ser deixadas como predefinição por enquanto.

  6. Na janela Definições de Compilação , clique no botão Definições do Leitor . Esta ação abrirá o painel relacionado no espaço onde o Inspetor está localizado.

    Abra as definições do leitor.

  7. Neste painel, é necessário verificar algumas definições:

    1. No separador Outras Definições :

      1. A Versão do Runtime de Scripts deve ser Experimental (.NET 4.6 Equivalente). Alterar isto irá acionar a necessidade de reiniciar o Editor.

      2. O Back-end de Scripts deve ser .NET

      3. O Nível de Compatibilidade da API deve ser .NET 4.6

        Atualizar outras definições.

    2. No separador Definições de Publicação , em Capacidades, verifique:

      • InternetClient

      • Câmara Web

        A atualizar as definições de publicação.

    3. Mais abaixo no painel, em Definições XR (encontradas abaixo de Definições de Publicação), marque a Realidade Virtual Suportada, certifique-se de que o SDK Windows Mixed Reality é adicionado.

      Atualize as Definições de X R.

  8. De volta às Definições de Compilação, os Projetos C# do Unity já não estão desativados; marque a caixa de verificação junto a esta opção.

  9. Feche a janela Definições de Compilação.

  10. Guarde o Seu Cenário e Projeto (CENA DE GRAVAÇÃO DE FICHEIRO>/PROJETO GUARDAR FICHEIRO>).

Capítulo 4 - Configuração da Câmara Principal

Importante

Se quiser ignorar o componente Configuração do Unity deste curso e continuar diretamente para o código, pode transferir este .unitypackage e importá-lo para o seu projeto como um Pacote Personalizado. Tenha em atenção que este pacote também inclui a importação da DLL newtonsoft, abrangida no Capítulo 5. Com esta importação, pode continuar a partir do Capítulo 6.

  1. No Painel hierarquia , selecione a Câmara Principal.

  2. Depois de selecionado, poderá ver todos os componentes da Câmara Principal no Painel de Inspetores.

    1. O objeto Câmara tem de ter o nome Câmara Principal (anote a ortografia!)

    2. A Etiqueta da Câmara Principal tem de ser definida como MainCamera (anote a ortografia!)

    3. Certifique-se de que a Posição da Transformação está definida como 0, 0, 0

    4. Defina Limpar Sinalizadores como Cor Sólida

    5. Defina a Cor de Fundo do Componente da Câmara como Preto, Alfa 0 (Código Hexadecima: #00000000)

      configurar componentes da câmara

Capítulo 5 – Importar a biblioteca Newtonsoft.Json

Importante

Se tiver importado o ".unitypackage" no último Capítulo, pode ignorar este Capítulo.

Para ajudá-lo a anular a serialização e serialização de objetos recebidos e enviados para o Bot Service tem de transferir a biblioteca Newtonsoft.Json. Encontrará uma versão compatível já organizada com a estrutura de pastas do Unity correta neste ficheiro de pacote do Unity.

Para importar a biblioteca:

  1. Transfira o Pacote do Unity.

  2. Clique em Ativos, Importar Pacote, Pacote Personalizado.

    Importar Newtonsoft.Json

  3. Procure o Pacote do Unity que transferiu e clique em Abrir.

  4. Certifique-se de que todos os componentes do pacote estão marcados e clique em Importar.

    Importar os recursos newtonsoft.Json

Capítulo 6 - Criar a classe FaceAnalysis

O objetivo da classe FaceAnalysis é alojar os métodos necessários para comunicar com o seu Serviço de Reconhecimento Facial do Azure.

  • Depois de enviar ao serviço uma imagem de captura, irá analisá-la e identificar os rostos no mesmo e determinar se alguma pertence a uma pessoa conhecida.
  • Se for encontrada uma pessoa conhecida, esta classe apresentará o respetivo nome como texto de IU na cena.

Para criar a classe FaceAnalysis :

  1. Clique com o botão direito do rato na Pasta Recursos localizada no Painel de Projeto e, em seguida, clique em Criar>Pasta. Chame a pasta Scripts.

    Crie a classe FaceAnalysis.

  2. Faça duplo clique na pasta que acabou de criar para abri-la.

  3. Clique com o botão direito do rato dentro da pasta e, em seguida, clique em Criar>Script C#. Chame o script FaceAnalysis.

  4. Faça duplo clique no novo script faceAnalysis para o abrir com o Visual Studio 2017.

  5. Introduza os seguintes espaços de nomes acima da classe FaceAnalysis :

        using Newtonsoft.Json;
        using System.Collections;
        using System.Collections.Generic;
        using System.IO;
        using System.Text;
        using UnityEngine;
        using UnityEngine.Networking;
    
  6. Agora, tem de adicionar todos os objetos que são utilizados para anular a serialização. Estes objetos têm de ser adicionados fora do script FaceAnalysis (abaixo do parêntese reto 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. Os métodos Start() e Update() não serão utilizados, por isso, elimine-os agora.

  8. Na classe FaceAnalysis , adicione as seguintes variáveis:

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

    Substitua a chave e o personGroupId pela sua Chave de Serviço e o ID do grupo que criou anteriormente.

  9. Adicione o método Awake(), que inicializa a classe, adicionando a classe ImageCapture à Câmara Principal e chama o método de criação etiqueta:

        /// <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. Adicione o método CreateLabel(), que cria o objeto Etiqueta para apresentar o resultado da análise:

        /// <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. Adicione o método DetectFacesFromImage() e GetImageAsByteArray( ). O primeiro irá pedir ao Serviço de Reconhecimento Facial para detetar qualquer rosto possível na imagem submetida, enquanto este último é necessário para converter a imagem capturada numa 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. Adicione o método IdentifyFaces(), que pede ao Serviço de Reconhecimento Facial para identificar qualquer rosto conhecido anteriormente detetado na imagem submetida. O pedido devolverá um ID da pessoa identificada, mas não o 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. Adicione o método GetPerson( ). Ao fornecer o ID da pessoa, este método solicita que o Serviço de Reconhecimento Facial devolva o nome da pessoa 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. Lembre-se de Guardar as alterações antes de voltar ao Editor do Unity.

  15. No Editor do Unity, arraste o script FaceAnalysis da pasta Scripts no painel Projeto para o objeto Câmara Principal no painel Hierarquia. O novo componente de script será adicionado à Câmara Principal.

Colocar o FaceAnalysis na Câmara Principal

Capítulo 7 - Criar a classe ImageCapture

O objetivo da classe ImageCapture é alojar os métodos necessários para comunicar com o Serviço de Reconhecimento Facial do Azure para analisar a imagem que irá capturar, identificar rostos na mesma e determinar se pertence a uma pessoa conhecida. Se for encontrada uma pessoa conhecida, esta classe apresentará o respetivo nome como texto de IU na cena.

Para criar a classe ImageCapture :

  1. Clique com o botão direito do rato na pasta Scripts que criou anteriormente e, em seguida, clique em Criar, Script C#. Chame o script ImageCapture.

  2. Faça duplo clique no novo script ImageCapture para o abrir com o Visual Studio 2017.

  3. Introduza os seguintes espaços de nomes acima da classe ImageCapture:

        using System.IO;
        using System.Linq;
        using UnityEngine;
        using UnityEngine.XR.WSA.Input;
        using UnityEngine.XR.WSA.WebCam;
    
  4. Na classe ImageCapture , adicione as seguintes variáveis:

        /// <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. Adicione os métodos Awake() e Start() necessários para inicializar a classe e permitir que o HoloLens capture os gestos do utilizador:

        /// <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. Adicione o TapHandler() que é chamado quando o utilizador efetua um gesto de Toque :

        /// <summary>
        /// Respond to Tap Input.
        /// </summary>
        private void TapHandler(TappedEventArgs obj)
        {
            tapsCount++;
            ExecuteImageCaptureAndAnalysis();
        }
    
  7. Adicione o método ExecuteImageCaptureAndAnalysis(), que iniciará o processo de Captura de Imagens:

        /// <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. Adicione os processadores que são chamados quando o processo de captura de fotografias tiver sido concluído:

        /// <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. Lembre-se de Guardar as alterações antes de voltar ao Editor do Unity.

Capítulo 8 – Criar a solução

Para realizar um teste minucioso da sua aplicação, terá de carregá-la em sideload para o HoloLens.

Antes de o fazer, certifique-se de que:

  • Todas as definições mencionadas no Capítulo 3 estão definidas corretamente.
  • O script FaceAnalysis está anexado ao objeto Câmara Principal.
  • A Chave de Autenticação e o ID de Grupo foram definidos no script FaceAnalysis .

Neste ponto, está pronto para criar a Solução. Assim que a Solução tiver sido criada, estará pronto para implementar a sua aplicação.

Para iniciar o processo de Compilação:

  1. Guarde a cena atual ao clicar em Ficheiro, Guardar.

  2. Aceda a Ficheiro, Definições de Compilação, clique em Adicionar Cenas Abertas.

  3. Certifique-se de que assinala Projetos C# do Unity.

    Implementar a solução do Visual Studio

  4. Prima Compilar. Ao fazê-lo, o Unity iniciará uma janela de Explorador de Ficheiros, onde terá de criar e, em seguida, selecionar uma pasta para compilar a aplicação. Crie essa pasta agora, no projeto do Unity, e chame-lhe Aplicação. Em seguida, com a pasta Aplicação selecionada, prima Selecionar Pasta.

  5. O Unity começará a criar o seu projeto, para a pasta Aplicação.

  6. Assim que o Unity terminar a criação (poderá demorar algum tempo), abrirá uma janela de Explorador de Ficheiros na localização da sua compilação.

    Implementar a solução a partir do Visual Studio

  7. Abra a pasta Aplicação e, em seguida, abra a nova Solução de Projeto (conforme visto acima, MR_FaceRecognition.sln).

Capítulo 9 – Implementar a sua aplicação

Para implementar no HoloLens:

  1. Precisará do Endereço IP do HoloLens (para Implementação Remota) e para garantir que o HoloLens está no Modo de Programador. Para efetuar este procedimento:

    1. Enquanto estiver a usar o HoloLens, abra as Definições.
    2. Aceda a Opções Avançadas da Internet & de Rede > Wi-Fi >
    3. Repare no endereço IPv4 .
    4. Em seguida, navegue novamente para Definições e, em seguida, para Atualizar Segurança > & para Programadores
    5. Defina o Modo de Programador ativado.
  2. Navegue para a nova compilação do Unity (a pasta Aplicação ) e abra o ficheiro de solução com o Visual Studio.

  3. Na Configuração da Solução, selecione Depurar.

  4. Na Plataforma de Soluções, selecione x86, Máquina Remota.

    Alterar a configuração da solução

  5. Aceda ao menu Compilar e clique em Implementar Solução para colocar a aplicação sideload no HoloLens.

  6. A sua Aplicação deverá agora aparecer na lista de aplicações instaladas no HoloLens, prontas para serem iniciadas!

Nota

Para implementar em headsets envolventes, defina a Plataforma de Soluções como Máquina Local e defina a Configuração como Depuração, com x86 como Plataforma. Em seguida, implemente no computador local, com o menu Compilar, selecionando Implementar Solução.

Capítulo 10 – Utilizar a aplicação

  1. Com o HoloLens, inicie a aplicação.

  2. Observe a pessoa que registou na API Face. Certifique-se de que:

    • O rosto da pessoa não está muito distante e claramente visível
    • A iluminação do ambiente não é muito escura
  3. Utilize o gesto de toque para capturar a imagem da pessoa.

  4. Aguarde que a Aplicação envie o pedido de análise e receba uma resposta.

  5. Se a pessoa tiver sido reconhecida com êxito, o nome da pessoa será apresentado como texto de IU.

  6. Pode repetir o processo de captura com o gesto de toque a cada poucos segundos.

A aplicação da API Face do Azure concluída

Parabéns, criou uma aplicação de realidade mista que tira partido do serviço reconhecimento facial do Azure para detetar rostos numa imagem e identificar rostos conhecidos.

resultado da conclusão deste curso

Exercícios de bónus

Exercício 1

A API Face do Azure é suficientemente poderosa para detetar até 64 rostos numa única imagem. Expanda a aplicação, para que possa reconhecer dois ou três rostos, entre muitas outras pessoas.

Exercício 2

A API Face do Azure também pode fornecer de volta todos os tipos de informações de atributos. Integre-o na aplicação. Isto pode ser ainda mais interessante, quando combinado com a API de Emoções.