Olá, dando continuidade nas postagens sobre como implementar Serviços Cognitivos em aplicações Xamarin.Forms, neste post irei demonstrar como criar um App de verificação facial, para analisar duas fotos e identificar se são da mesma pessoa.
Para isso será utilizado a API de Detecçao Facial presente no Micrsoft Cognitive Services e os serviços de detecção e de verificação.
O serviço de detecção será utilizado para identificar rostos na imagem, e o de verificação para verificar se são da mesma pessoa.
Neste post não detalho o serviço de detecção, se você possui alguma dúvida sobre isso ou quer saber mais, recomendo ler o post Microsoft Cognitive Services – Face Detect com Xamarin.Forms
Para este exemplo irei assumir que você já criou uma aplicação Xamarin.Forms e utilizou o Nuget Package Xam.Plugin.Media para capturar uma foto da câmera. Se você possui dúvidas sobre isso, recomendo ler o post: Utilizando a Câmera – Xamarin.Forms, lá eu explico passo a passo como utilizar o plugin para tirar fotos em aplicações Xamarin.Forms.
OBTENDO CHAVES
É necessário obter uma URL e Chaves para utilizar a API de Detecção Facial, então o primeiro passo é acessar o link: https://azure.microsoft.com/pt-br/try/cognitive-services/?api=face-api e clicar em “Obter Chave de API”.
Em seguida será necessário realizar login com uma conta Microsoft.
Para este exemplo estou utilizando minha conta e os serviços disponibilizados gratuitamente por 30 dias. (Após esse período essas chaves serão desativadas).
Agora que você já possui sua URL e as chaves para utilizar a API, recomendo que guarde essas informações.
ADICIONANDO NUGET PACKAGES
Clique com o botão direito em cima de sua Solution e selecione “Manage NuGet Packages for Solution…”.
Digite “Microsoft.ProjectOxford.Face” e selecione o plugin como demonstrado na imagem a seguir.
Selecione apenas o projeto compartilhado e clique no botão “Install”.
Depois repita esses passos para instalar os seguintes pacotes:
- Microsoft.ProjectOxford.Common.DotNetStandard
- Newtonsoft.Json
Para utilizar o serviço de verificação de rostos, é necessário possuir uma base de dados para comparação, ou seja, criar um grupo e uma pessoa no Microsoft Cognitive Services. Porém, como o intuito desse app é apenas comparar 2 fotos e verificar se são da mesma pessoa, iremos criar um grupo e uma pessoa genérica (apenas para poder utilizar o serviço), e isso será necessário apenas uma unica vez.
A ideia é sempre utilizar esse mesmo grupo e essa mesma pessoa e ao final de cada verificação apagar a foto adicionada a essa pessoa, para que possa ser utilizada na próxima vez por uma foto de uma pessoa diferente, então esses passos de criação de um grupo e uma pessoa, irei realizar direto no site do Microsoft Cognitive Services, mas se você preferir também pode cria-los via código.
Criar um grupo
Para criar o grupo direto no site, acesse o link : https://westcentralus.dev.cognitive.microsoft.com/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f30395244/console
Informe os seguintes parâmetros como demonstrado na imagem a seguir:
- PersonGroupId – o id que usuará para identificação do seu grupo
- OCP-Apim-Subscription-Key – a sua chave obtida no passo “Obtendo Chaves”
- “name” – o nome que deseja para o grupo
Em seguida pressione o botão “SEND” e o resultado deve ser um Response status 200 OK.
Criar uma pessoa
Para criar uma pessoa direto no site, acesse o link : https://westcentralus.dev.cognitive.microsoft.com/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f3039523c/console
Informe os seguintes parâmetros como demonstrado na imagem a seguir:
- PersonGroupId – o id do grupo criado no passo anterior
- OCP-Apim-Subscription-Key – a sua chave obtida no passo “Obtendo Chaves”
- “name” – o nome que deseja para a pessoa
Em seguida pressione o botão “SEND” e o resultado deve ser um Response status 200 OK com um json informando o personId, guarde esse Id, pois será utilizado nos passos a seguir.
Voltando para o App…
Xaml
Para esse exemplo crie:
- Image – Para demonstrar a primeira foto tirada
- Button – Para chamar o método TakePicture1
- Image – Para demonstrar a segunda foto tirada
- Button – Para chamar o método TakePicture2
- Button – Para chamar o método FaceVerify
<?xml version="1.0" encoding="utf-8" ?> | |
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" | |
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |
xmlns:local="clr-namespace:DemoFaceVerify" | |
x:Class="DemoFaceVerify.MainPage"> | |
<StackLayout> | |
<StackLayout Orientation="Horizontal" | |
HorizontalOptions="Center" | |
VerticalOptions="Center" BackgroundColor="DarkSlateGray"> | |
<Image x:Name="MinhaImagem1" Aspect="AspectFill" HeightRequest="200" | |
WidthRequest="400" HorizontalOptions="CenterAndExpand" /> | |
</StackLayout> | |
<Button Text="Tirar Foto 1" Clicked="TakePicture1" FontSize="20" /> | |
<StackLayout Orientation="Horizontal" | |
HorizontalOptions="Center" | |
VerticalOptions="Center" BackgroundColor="DarkSlateGray"> | |
<Image x:Name="MinhaImagem2" Aspect="AspectFill" HeightRequest="200" | |
WidthRequest="400" HorizontalOptions="CenterAndExpand" /> | |
</StackLayout> | |
<Button Text="Tirar Foto 2" Clicked="TakePicture2" FontSize="20" /> | |
<Button Text="Verificar" Clicked="FaceVerify" BackgroundColor="Blue"/> | |
</StackLayout> | |
</ContentPage> |
C#
Crie as seguintes variaveis:
- _faceServiceClient – IFaceServiceClient
- personId – Guid
- faceId1 – Guid
- faceId2 – Guid
- filePath1 – string
Inicialize as variáveis no construtor e substitua “URL” pela sua url, “KEY” por uma de suas chaves obtidas no passo anterior “Obtendo Chaves” e “PERSONID” obtido no passo “Criar uma pessoa”.
using System; | |
using Microsoft.ProjectOxford.Face; | |
using Plugin.Media; | |
using Plugin.Media.Abstractions; | |
using Xamarin.Forms; | |
namespace DemoFaceVerify | |
{ | |
public partial class MainPage : ContentPage | |
{ | |
private readonly IFaceServiceClient _faceServiceClient; | |
private readonly Guid personId; | |
private Guid faceId1; | |
private Guid faceId2; | |
private string filePath1; | |
public MainPage() | |
{ | |
InitializeComponent(); | |
_faceServiceClient = new FaceServiceClient("KEY", "URL"); | |
faceId1 = new Guid(); | |
faceId2 = new Guid(); | |
personId = new Guid("PERSONID"); | |
} | |
} | |
} |
Crie os métodos “TakePicture1” e “TakePicture2” como demonstrado no post Utilizando a Câmera – Xamarin.Forms, eles serão responsáveis por tirar as fotos.
No método “TakePicture1” atribua o file.Path para a variável filePath1 e em seguida crie uma chamada para o método FaceAddInPerson passando como parâmetro file.Path.
No método “TakePicture2” crie uma chamada para o método FaceDetect passando como parâmetro file.Path.
Crie o método FaceAddInPerson, que será responsável por adicionar a Foto 1 na pessoa criada anteriormente e atribuir o resultado na variável faceId1. Em seguida realize uma chamada para TrainPersonGroupAsync (É necessário “treinar” o grupo, para encontrar o rosto depois no método Verify)
private async Task FaceAddInPerson(string image) | |
{ | |
// Call the Face API. | |
try | |
{ | |
using (Stream imageFileStream = File.OpenRead(image)) | |
{ | |
var result = await _faceServiceClient.AddPersonFaceAsync("grupo",personId, imageFileStream); | |
faceId1 = result.PersistedFaceId; | |
} | |
await _faceServiceClient.TrainPersonGroupAsync("grupo"); | |
} | |
// Catch and display Face API errors. | |
catch (FaceAPIException f) | |
{ | |
await DisplayAlert("Error", f.ErrorMessage, "ok"); | |
} | |
// Catch and display all other errors. | |
catch (Exception e) | |
{ | |
await DisplayAlert("Error", e.Message, "ok"); | |
} | |
} |
Crie o método FaceDetect, que será responsável por chamar o DetectAsync (Identifica rostos na imagem e retorna uma lista de faceId). Pegue o primeiro rosto da lista (Esperamos que só tenha um) e atribua a variável faceId2.
public async Task FaceDetect(string image) | |
{ | |
// Call the Face API. | |
try | |
{ | |
using (Stream imageFileStream = File.OpenRead(image)) | |
{ | |
var faces = await _faceServiceClient.DetectAsync(imageFileStream, | |
returnFaceId: true, | |
returnFaceLandmarks: false, | |
returnFaceAttributes: null); | |
//Get First Face in List | |
if (faces.Length > 0) | |
faceId2 = faces[0].FaceId; | |
} | |
} | |
// Catch and display Face API errors. | |
catch (FaceAPIException f) | |
{ | |
await DisplayAlert("Error", f.ErrorMessage, "ok"); | |
} | |
// Catch and display all other errors. | |
catch (Exception e) | |
{ | |
await DisplayAlert("Error", e.Message, "ok"); | |
} | |
} |
Crie o método FaceVerify que será responsável por chamar o VerifyAsync, demonstrando o resultado através de um DisplayAlert e por último deletando a foto adicionada na pessoa, para que possa utilizar novamente com uma pessoa diferente sem ter problemas, lembre-se que tanto o grupo quanto a pessoa criada no Cognitive Services para este caso em questão serão genéricas.
public async void FaceVerify(object sender, EventArgs e) | |
{ | |
if (faceId1 == new Guid()) | |
await FaceAddInPerson(filePath1); | |
// Call the Face API. | |
try | |
{ | |
var result = await _faceServiceClient.VerifyAsync(faceId2,"grupo",personId); | |
await DisplayAlert("Result", | |
"IsIdentical: " + result.IsIdentical + | |
" Confidence: " + result.Confidence, | |
"OK"); | |
await _faceServiceClient.DeletePersonFaceAsync("grupo", personId, faceId1); | |
faceId1 = new Guid(); | |
} | |
// Catch and display Face API errors. | |
catch (FaceAPIException f) | |
{ | |
await DisplayAlert("Error", f.ErrorMessage, "ok"); | |
} | |
// Catch and display all other errors. | |
catch (Exception ex) | |
{ | |
await DisplayAlert("Error", ex.Message, "ok"); | |
} | |
} |
Resultado
Esse e todos os exemplos deste blog encontram-se disponíveis no GitHub.
Leia mais sobre esse assunto na documentação oficial da Microsoft.