Usar a estrutura de dados do PersonDirectory (visualização)

Atenção

O acesso ao serviço presencial é limitado com base em critérios de elegibilidade e uso, a fim de apoiar nossos princípios de IA responsável. O serviço Face só está disponível para clientes e parceiros geridos pela Microsoft. Use o formulário de admissão de Reconhecimento Facial para solicitar acesso. Para obter mais informações, consulte a página Acesso limitado Face.

Para executar operações de reconhecimento facial, como Identificar e Localizar Similar, os clientes da API de rosto precisam criar uma lista variada de objetos Pessoa . PersonDirectory é uma estrutura de dados no Public Preview que contém IDs exclusivos, cadeias de caracteres de nome opcionais e cadeias de metadados de usuário opcionais para cada identidade Person adicionada ao diretório. Siga este guia para aprender a fazer tarefas básicas com o PersonDirectory.

Vantagens do PersonDirectory

Atualmente, a API Face oferece a estrutura LargePersonGroup , que tem funcionalidade semelhante, mas é limitada a 1 milhão de identidades. A estrutura do PersonDirectory pode ser dimensionada para até 75 milhões de identidades.

Outra grande diferença entre o PersonDirectory e as estruturas de dados anteriores é que você não precisará mais fazer chamadas à API Train depois de adicionar rostos a um objeto Person — o processo de atualização acontece automaticamente.

Pré-requisitos

  • Subscrição do Azure - Crie uma gratuitamente.
  • Depois de ter sua assinatura do Azure, crie um recurso Face no portal do Azure para obter sua chave e ponto de extremidade. Depois de implantar, selecione Ir para recurso.
    • Você precisará da chave e do ponto de extremidade do recurso criado para conectar seu aplicativo à API do Face. Você colará sua chave e ponto de extremidade no código abaixo.
    • Você pode usar o nível de preço gratuito (F0) para experimentar o serviço e atualizar posteriormente para um nível pago para produção.

Adicionar pessoas ao PersonDirectory

As pessoas são as unidades básicas de inscrição no Diretório de Pessoas. Depois de adicionar uma Pessoa ao diretório, você pode adicionar até 248 imagens de rosto a essa Pessoa, por modelo de reconhecimento. Em seguida, você pode identificar rostos contra eles usando escopos variados.

Criar a Pessoa

Para criar uma Person, você precisa chamar a API CreatePerson e fornecer um nome ou valor de propriedade userData.

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

var addPersonUri = "https:// {endpoint}/face/v1.0-preview/persons";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("name", "Example Person");
body.Add("userData", "User defined data");
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(addPersonUri, content); 
}

A chamada CreatePerson retornará uma ID gerada para a Pessoa e um local de operação. Os dados da Pessoa serão processados de forma assíncrona, para que você use o local da operação para buscar os resultados.

Aguarde a conclusão da operação assíncrona

Você precisará consultar o status da operação assíncrona usando a cadeia de caracteres de local da operação retornada para verificar o progresso.

Primeiro, você deve definir um modelo de dados como o seguinte para lidar com a resposta de status.

[Serializable]
public class AsyncStatus
{
    [DataMember(Name = "status")]
    public string Status { get; set; }

    [DataMember(Name = "createdTime")]
    public DateTime CreatedTime { get; set; }

    [DataMember(Name = "lastActionTime")]
    public DateTime? LastActionTime { get; set; }

    [DataMember(Name = "finishedTime", EmitDefaultValue = false)]
    public DateTime? FinishedTime { get; set; }

    [DataMember(Name = "resourceLocation", EmitDefaultValue = false)]
    public string ResourceLocation { get; set; }

    [DataMember(Name = "message", EmitDefaultValue = false)]
    public string Message { get; set; }
}

Usando o HttpResponseMessage acima, você pode pesquisar o URL e aguardar os resultados.

string operationLocation = response.Headers.GetValues("Operation-Location").FirstOrDefault();

Stopwatch s = Stopwatch.StartNew();
string status = "notstarted";
do
{
    if (status == "succeeded")
    {
        await Task.Delay(500);
    }

    var operationResponseMessage = await client.GetAsync(operationLocation);

    var asyncOperationObj = JsonConvert.DeserializeObject<AsyncStatus>(await operationResponseMessage.Content.ReadAsStringAsync());
    status = asyncOperationObj.Status;

} while ((status == "running" || status == "notstarted") && s.Elapsed < TimeSpan.FromSeconds(30));

Quando o status retorna como "bem-sucedido", o objeto Person é considerado adicionado ao diretório.

Nota

A operação assíncrona da chamada Criar Pessoa não precisa mostrar o status "bem-sucedido" antes que os rostos possam ser adicionados a ela, mas precisa ser concluída antes que a Pessoa possa ser adicionada a um DynamicPersonGroup (veja abaixo Criar e atualizar um DynamicPersonGroup) ou comparada durante uma chamada de Identificação. Verifique se as chamadas funcionarão imediatamente depois que os rostos forem adicionados com sucesso à Pessoa.

Adicionar rostos a Pessoas

Depois de ter o ID da Pessoa da chamada Criar Pessoa, você pode adicionar até 248 imagens de rosto a uma Pessoa por modelo de reconhecimento. Especifique o modelo de reconhecimento (e, opcionalmente, o modelo de deteção) a ser usado na chamada, pois os dados sob cada modelo de reconhecimento serão processados separadamente dentro do PersonDirectory.

Os modelos de reconhecimento atualmente suportados são:

  • Recognition_02
  • Recognition_03
  • Recognition_04

Além disso, se a imagem contiver várias faces, você precisará especificar a caixa delimitadora do retângulo para a face que é o destino pretendido. O código a seguir adiciona faces a um objeto Person .

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

// Optional query strings for more fine grained face control
var queryString = "userData={userDefinedData}&targetFace={left,top,width,height}&detectionModel={detectionModel}";
var uri = "https://{endpoint}/face/v1.0-preview/persons/{personId}/recognitionModels/{recognitionModel}/persistedFaces?" + queryString;

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("url", "{image url}");
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(uri, content);
}

Após a chamada Add Faces, os dados faciais serão processados de forma assíncrona e você precisará aguardar o sucesso da operação da mesma maneira que antes.

Quando a operação para a adição de rosto terminar, os dados estarão prontos para em Identificar chamadas.

Criar e atualizar um DynamicPersonGroup

DynamicPersonGroups são coleções de referências a objetos Person dentro de um PersonDirectory, eles são usados para criar subconjuntos do diretório. Um uso comum é quando você deseja obter menos falsos positivos e maior precisão em uma operação Identificar limitando o escopo apenas aos objetos Person que você espera corresponder. Casos de uso práticos incluem diretórios para acesso específico a edifícios entre um campus ou organização maior. O diretório da organização pode conter 5 milhões de indivíduos, mas você só precisa pesquisar 800 pessoas específicas para um determinado edifício, então você criaria um DynamicPersonGroup contendo esses indivíduos específicos.

Se você já usou um PersonGroup antes, observe duas diferenças principais:

  • Cada Pessoa dentro de um DynamicPersonGroup é uma referência à Pessoa real no PersonDirectory, o que significa que não é necessário recriar uma Pessoa em cada grupo.
  • Como mencionado nas seções anteriores, não há necessidade de fazer chamadas de trem, pois os dados faciais são processados no nível do diretório automaticamente.

Criar o grupo

Para criar um DynamicPersonGroup, você precisa fornecer uma ID de grupo com caracteres alfanuméricos ou traço. Esse ID funcionará como o identificador exclusivo para todos os fins de uso do grupo.

Há duas maneiras de inicializar uma coleção de grupo. Você pode criar um grupo vazio inicialmente e preenchê-lo mais tarde:

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

var uri = "https://{endpoint}/face/v1.0-preview/dynamicpersongroups/{dynamicPersonGroupId}";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("name", "Example DynamicPersonGroup");
body.Add("userData", "User defined data");
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PutAsync(uri, content);
}

Esse processo é imediato e não há necessidade de esperar que nenhuma operação assíncrona seja bem-sucedida.

Como alternativa, você pode criá-lo com um conjunto de IDs de Pessoa para conter essas referências desde o início, fornecendo o conjunto no argumento AddPersonIds :

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

var uri = "https://{endpoint}/face/v1.0-preview/dynamicpersongroups/{dynamicPersonGroupId}";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("name", "Example DynamicPersonGroup");
body.Add("userData", "User defined data");
body.Add("addPersonIds", new List<string>{"{guid1}", "{guid2}", …});
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PutAsync(uri, content);

    // Async operation location to query the completion status from
    var operationLocation = response.Headers.Get("Operation-Location");
}

Nota

Assim que a chamada retornar, o DynamicPersonGroup criado estará pronto para uso em uma chamada de identificação, com quaisquer referências de pessoa fornecidas no processo. O status de conclusão do ID da operação retornada, por outro lado, indica o status de atualização da relação pessoa-grupo.

Atualizar o DynamicPersonGroup

Após a criação inicial, você pode adicionar e remover referências de Pessoa do DynamicPersonGroup com a API Atualizar Grupo de Pessoas Dinâmicas. Para adicionar objetos Person ao grupo, liste os IDs de Pessoa no argumento addPersonsIds. Para remover objetos Person , liste-os no argumento removePersonIds . Tanto a adição quanto a remoção podem ser realizadas em uma única chamada:

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

var uri = "https://{endpoint}/face/v1.0-preview/dynamicpersongroups/{dynamicPersonGroupId}";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("name", "Example Dynamic Person Group updated");
body.Add("userData", "User defined data updated");
body.Add("addPersonIds", new List<string>{"{guid1}", "{guid2}", …});
body.Add("removePersonIds", new List<string>{"{guid1}", "{guid2}", …});
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PatchAsync(uri, content);

    // Async operation location to query the completion status from
    var operationLocation = response.Headers.Get("Operation-Location");
}

Quando a chamada retornar, as atualizações da coleção serão refletidas quando o grupo for consultado. Assim como na API de criação, a operação retornada indica o status de atualização da relação pessoa-grupo para qualquer Pessoa envolvida na atualização. Você não precisa esperar a conclusão da operação antes de fazer novas chamadas de atualização para o grupo.

Identificar rostos em um PersonDirectory

A maneira mais comum de usar dados faciais em um PersonDirectory é comparar os objetos Person inscritos com um determinado rosto e identificar o candidato mais provável ao qual ele pertence. Várias faces podem ser fornecidas na solicitação, e cada uma receberá seu próprio conjunto de resultados de comparação na resposta.

No PersonDirectory, há três tipos de escopos contra os quais cada face pode ser identificada:

Cenário 1: Identificar em relação a um DynamicPersonGroup

Especificar a propriedade dynamicPersonGroupId na solicitação compara o rosto com cada Pessoa referenciada no grupo. Apenas um único DynamicPersonGroup pode ser identificado em uma chamada.

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

// Optional query strings for more fine grained face control
var uri = "https://{endpoint}/face/v1.0-preview/identify";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("faceIds", new List<string>{"{guid1}", "{guid2}", …});
body.Add("dynamicPersonGroupId", "{dynamicPersonGroupIdToIdentifyIn}");
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(uri, content);
}

Cenário 2: Identificar com base numa lista específica de pessoas

Você também pode especificar uma lista de IDs de Pessoa na propriedade personIds para comparar o rosto com cada um deles.

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");
            
var uri = "https://{endpoint}/face/v1.0-preview/identify";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("faceIds", new List<string>{"{guid1}", "{guid2}", …});
body.Add("personIds", new List<string>{"{guid1}", "{guid2}", …});
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(uri, content);
}

Cenário 3: Identificar em relação a todo o PersonDirectory

Fornecer um único asterisco na propriedade personIds na solicitação compara o rosto com cada Pessoa inscrita no PersonDirectory.

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");
            
var uri = "https://{endpoint}/face/v1.0-preview/identify";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("faceIds", new List<string>{"{guid1}", "{guid2}", …});
body.Add("personIds", new List<string>{"*"});
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(uri, content);
}

Para todos os três cenários, a identificação compara apenas o rosto de entrada com rostos cuja chamada AddPersonFace retornou com uma resposta "bem-sucedida".

Verificar rostos contra pessoas no PersonDirectory

Com um ID de rosto retornado de uma chamada de deteção, você pode verificar se o rosto pertence a uma Pessoa específica inscrita no Diretório de Pessoas. Especifique a Pessoa usando a propriedade personId.

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

var uri = "https://{endpoint}/face/v1.0-preview/verify";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("faceId", "{guid1}");
body.Add("personId", "{guid1}");
var jsSerializer = new JavaScriptSerializer();
byte[] byteData = Encoding.UTF8.GetBytes(jsSerializer.Serialize(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(uri, content);
}

A resposta conterá um valor booleano indicando se o serviço considera que o novo rosto pertence à mesma Pessoa e um índice de confiança para a previsão.

Próximos passos

Neste guia, você aprendeu como usar a estrutura do PersonDirectory para armazenar dados de rosto e pessoa para seu aplicativo Face. Em seguida, aprenda as práticas recomendadas para adicionar os dados faciais dos usuários.