Compartilhar via


Usar a estrutura de dados do PersonDirectory (versão prévia)

Cuidado

O acesso ao serviço de Detecção Facial é limitado com base em critérios de qualificação e uso para dar suporte aos nossos princípios de IA responsável. O serviço de Detecção Facial só está disponível para clientes e parceiros gerenciados da 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 facial.

Para executar operações de reconhecimento facial como Identificar e Localizar Semelhante, os clientes da API de Detecção Facial precisam criar uma lista sortida de objetos de Pessoa. O PersonDirectory é uma estrutura de dados na Visualização Pública que contém IDs exclusivas, cadeias de caracteres de nomes opcionais e cadeias de caracteres de metadados de usuários opcionais para cada identidade de Pessoa adicionada ao diretório. Siga este guia para saber como fazer tarefas básicas no PersonDirectory.

Vantagens do PersonDirectory

Atualmente, a API de Detecção Facial oferece a estrutura LargePersonGroup, que tem funcionalidade semelhante, mas é limitada a 1 milhão de identidades. A estrutura PersonDirectory pode escalar verticalmente 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 de treinamento depois de adicionar rostos a um objeto Person: o processo de atualização ocorre automaticamente.

Pré-requisitos

  • Assinatura do Azure – crie uma gratuitamente.
  • Depois de obter sua assinatura do Azure, crie um recurso da Detecção Facial no portal do Azure para obter a chave e o ponto de extremidade. Após a implantação, selecione Ir para recurso.
    • Você precisará da chave e do ponto de extremidade do recurso criado para conectar seu aplicativo à API de Detecção Facial. Cole a chave e o ponto de extremidade no código abaixo.
    • Use o tipo de preço gratuito (F0) para experimentar o serviço e atualizar mais tarde para um nível pago para produção.

Adicionar Pessoas ao PersonDirectory

Pessoas são as unidades de registro de base no PersonDirectory. Depois de adicionar uma Pessoa ao diretório, você pode adicionar até 248 imagens de rostos a essa Pessoa por modelo de reconhecimento. Em seguida, você pode identificar rostos em relação a elas usando escopos variados.

Criar a Pessoa

Para criar uma Pessoa, você precisa chamar a API CreatePerson e fornecer um valor de propriedade Name ou 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 para CreatePerson retornará uma ID gerada para a Pessoa e um local de operação. Os dados da Pessoa serão processados de maneira assíncrona, portanto, você usará o local da operação para buscar os resultados.

Aguardar 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 a HttpResponseMessage acima, você pode sondar a URL e aguardar os resultados.

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

Stopwatch s = Stopwatch.StartNew();
string status = "notstarted";
do
{
    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 retornado for "êxito", o objeto de Pessoa será considerado adicionado ao diretório.

Observação

A operação assíncrona da chamada de criação de Pessoa não precisa mostrar o status de "êxito" antes que os rostos possam ser adicionados a ela, mas precisa ser concluído 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. As chamadas de verificação funcionarão imediatamente depois que os rostos forem adicionados com êxito à Pessoa.

Adicionar rostos a Pessoas

Quando tiver a ID da Pessoa da chamada para CreatePerson, você poderá adicionar até 248 imagens de rosto a uma Pessoa por modelo de reconhecimento. Especifique o modelo de reconhecimento (e, opcionalmente, o modelo de detecção) a ser usado na chamada, pois os dados em cada modelo de reconhecimento serão processados separadamente dentro do PersonDirectory.

Os modelos de reconhecimento com suporte no momento são:

  • Recognition_02
  • Recognition_03
  • Recognition_04

Além disso, se a imagem contiver vários rostos, você precisará especificar a caixa delimitadora de retângulo para o rosto que é o destino pretendido. O código a seguir adiciona rostos 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 para adicionar rostos, os dados de rosto serão processados de maneira assíncrona e você precisará aguardar o sucesso da operação da mesma maneira que antes.

Quando a operação de adição de rosto for concluída, os dados estarão prontos para chamadas de identificaçãoi.

Criar e atualizar um DynamicPersonGroup

DynamicPersonGroups são coleções de referências a objetos de Pessoa dentro de um PersonDirectory; eles são usados para criar subconjuntos do diretório. Um uso comum é quando você deseja receber menos falsos positivos e ter mais precisão em uma operação de identificação limitando o escopo apenas para os objetos de Pessoa que você espera que correspondam. Casos de uso práticos incluem diretórios para acesso a prédios específicos um campus ou uma 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 prédio. Portanto, você criaria um DynamicPersonGroup contendo esses indivíduos específicos.

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

  • 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.
  • Conforme mencionado em seções anteriores, não há necessidade de fazer chamadas de treinamento, pois os dados de rosto são processados automaticamente no nível do diretório.

Criar o grupo

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

Há duas maneiras de inicializar uma coleção de grupos. 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 todas as operações assíncronas tenham êxito.

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");
}

Observação

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

Atualizar o DynamicPersonGroup

Após a criação inicial, você pode adicionar e remover as referências de Pessoa do DynamicPersonGroup com a API Atualizar Grupo de Pessoas Dinâmico. Para adicionar objetos de Pessoa ao grupo, liste as IDs de Pessoa no argumento addPersonsIds. Para remover objetos de Pessoa, liste-os no argumento removePersonIds. A adição e a remoção podem ser executadas em uma só 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");
}

Depois que a chamada for retornada, as atualizações da coleção serão refletidas quando o grupo for consultado. Assim como acontece com a API de criação, a operação retornada indica o status da atualização da relação de pessoa para grupo para qualquer Pessoa envolvida na atualização. Você não precisa aguardar a conclusão da operação antes de fazer mais chamadas de atualização para o grupo.

Identificar rostos em um PersonDirectory

A maneira mais comum de usar dados de rosto em um PersonDirectory é comparar os objetos de Pessoa registrados com um determinado rosto e identificar o candidato mais provável ao qual ele pertence. Vários rostos podem ser fornecidos na solicitação, e cada um deles receberá o próprio conjunto de resultados de comparação na resposta.

No PersonDirectory, há três tipos de escopos em que cada rosto pode ser identificado:

Cenário 1: identificar em um DynamicPersonGroup

Especificar a propriedade dynamicPersonGroupId na solicitação compara o rosto com todas as Pessoas referenciadas no grupo. Apenas um 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 em uma lista específica de pessoas

Você também pode especificar uma lista de IDs de Pessoas na propriedade personIds para comparar o rosto a cada uma delas.

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 no PersonDirectory inteiro

Fornecer apenas um asterisco na propriedade personIds na solicitação compara o rosto a todas as Pessoas inscritas 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 os três cenários, a identificação só compara o rosto de entrada a rostos cuja chamada a AddPersonFace retornou uma resposta "com êxito".

Verificar rostos com relação a pessoas no PersonDirectory

Com uma ID de rosto retornada de uma chamada de detecção, você pode verificar se o rosto pertence a uma Pessoa específica inscrita no PersonDirectory. 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}");
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);
}

A resposta conterá um valor booliano que indica se o serviço considera o que o novo rosto pertence à mesma Pessoa e uma pontuação de confiança para a previsão.

Próximas etapas

Neste guia, você aprendeu a usar a estrutura PersonDirectory para armazenar dados de rostos e de pessoas para seu aplicativo de Detecção Facial. Em seguida, conheça as melhores práticas para adicionar dados de rosto de seus usuários.