Dimensionar para lidar com mais usuários inscritos

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.

Este guia mostra a você como ampliar objetos de um PersonGroup e FaceList existentes para objetos de LargePersonGroup e LargeFaceList, respectivamente. PersonGroups podem conter até 1.000 pessoas no nível gratuito e 10.000 no nível pago, enquanto LargePersonGroups podem armazenar até um milhão de pessoas no nível pago.

Importante

A estrutura de dados mais recente PersonDirectory é recomendada para o novo desenvolvimento. Ele pode conter até 75 milhões de identidades e não requer treinamento manual. Para obter mais informações, consulte o Guia PersonDirectory.

Este guia demonstra o processo de migração. O guia pressupõe uma familiaridade básica com objetos de PersonGroup e FaceList, com a operação Treinar e com as funções de reconhecimento facial. Para saber mais sobre esses temas, confira o guia conceitual de reconhecimento facial.

LargePersonGroup e LargeFaceList são mencionados, coletivamente, como operações em grande escala. Um LargePersonGroup pode conter até um milhão de pessoas, cada um com no máximo 248 rostos. Um LargeFaceList pode conter até um milhão de rostos. As operações em grande escala são semelhantes aos PersonGroups e FaceLists convencionais, mas têm algumas diferenças devido à nova arquitetura.

Os exemplos foram escritos em C# com a biblioteca de clientes da Detecção Facial dos Serviços de IA do Azure.

Observação

Para habilitar o desempenho da pesquisa de rostos para fins de Identificação e FindSimilar em grande escala, introduza uma operação Treinar para pré-processar a LargeFaceList e o LargePersonGroup. O tempo de treinamento varia de segundos a cerca de meia hora, dependendo da capacidade real. Durante o período de treinamento, é possível executar operações de Identificação e FindSimilar se uma operação de treinamento bem-sucedida tiver sido realizada anteriormente. A desvantagem é que as novas pessoas e faces adicionadas serão exibidas no resultado apenas quando for realizada uma nova migração de publicação para treinamento em grande escala.

Etapa 1: Inicializar o objeto de cliente

Quando você usa a biblioteca de clientes da Detecção Facial, a chave e o ponto de extremidade de assinatura são transmitidos para o construtor da classe FaceClient. Confira o guia de início rápido para obter instruções sobre como criar um objeto cliente de Detecção Facial.

Etapa 2: Migração de código

Esta seção se concentra apenas em como migrar a implementação de um PersonGroup ou FaceList para um LargePersonGroup ou LargeFaceList. Embora um LargePersonGroup ou LargeFaceList sejam diferentes de um PersonGroup ou FaceList em termos de design e implementação interna, as interfaces de API são semelhantes para fins de compatibilidade com versões anteriores.

Não há suporte para migração de dados. Em vez disso, você recria o LargePersonGroup ou a LargeFaceList.

Migrar um objeto PersonGroup para um LargePersonGroup

A migração de um PersonGroup para um LargePersonGroup é simples. Eles compartilham exatamente as mesmas operações em nível de grupo.

Para o caso de uma implementação de PersonGroup ou relacionada a pessoas, é necessário alterar apenas os caminhos da API ou o módulo/classe do SDK para LargePersonGroup e LargePersonGroupPerson.

Adicione todos os rostos e pessoas do PersonGroup ao novo LargePersonGroup. Para saber mais, confira Adicionar faces.

Migrar um FaceList para um LargeFaceList

APIs de FaceList APIs de LargeFaceList
Criar Criar
Excluir Excluir
Obter Obter
Lista Lista
Atualizar Atualizar
- Treinar
- Obter Status de Treinamento

A tabela anterior é uma comparação de operações em nível de lista entre FaceList e LargeFaceList. Como já mostramos, a LargeFaceList vem com novas operações, Treinar e Obter Status de Treinamento, quando comparada à FaceList. Treinar a LargeFaceList é um pré-requisito para a operação FindSimilar. O treinamento não é obrigatório para a FaceList. O snippet de código a seguir é uma função auxiliar para aguardar o treinamento de uma LargeFaceList:

/// <summary>
/// Helper function to train LargeFaceList and wait for finish.
/// </summary>
/// <remarks>
/// The time interval can be adjusted considering the following factors:
/// - The training time which depends on the capacity of the LargeFaceList.
/// - The acceptable latency for getting the training status.
/// - The call frequency and cost.
///
/// Estimated training time for LargeFaceList in different scale:
/// -     1,000 faces cost about  1 to  2 seconds.
/// -    10,000 faces cost about  5 to 10 seconds.
/// -   100,000 faces cost about  1 to  2 minutes.
/// - 1,000,000 faces cost about 10 to 30 minutes.
/// </remarks>
/// <param name="largeFaceListId">The Id of the LargeFaceList for training.</param>
/// <param name="timeIntervalInMilliseconds">The time interval for getting training status in milliseconds.</param>
/// <returns>A task of waiting for LargeFaceList training finish.</returns>
private static async Task TrainLargeFaceList(
    string largeFaceListId,
    int timeIntervalInMilliseconds = 1000)
{
    // Trigger a train call.
    await FaceClient.LargeTrainLargeFaceListAsync(largeFaceListId);

    // Wait for training finish.
    while (true)
    {
        Task.Delay(timeIntervalInMilliseconds).Wait();
        var status = await faceClient.LargeFaceList.TrainAsync(largeFaceListId);

        if (status.Status == Status.Running)
        {
            continue;
        }
        else if (status.Status == Status.Succeeded)
        {
            break;
        }
        else
        {
            throw new Exception("The train operation is failed!");
        }
    }
}

Anteriormente, um uso típico da FaceList com rostos adicionados e do FindSimilar se parecia com o seguinte:

// Create a FaceList.
const string FaceListId = "myfacelistid_001";
const string FaceListName = "MyFaceListDisplayName";
const string ImageDir = @"/path/to/FaceList/images";
faceClient.FaceList.CreateAsync(FaceListId, FaceListName).Wait();

// Add Faces to the FaceList.
Parallel.ForEach(
    Directory.GetFiles(ImageDir, "*.jpg"),
    async imagePath =>
        {
            using (Stream stream = File.OpenRead(imagePath))
            {
                await faceClient.FaceList.AddFaceFromStreamAsync(FaceListId, stream);
            }
        });

// Perform FindSimilar.
const string QueryImagePath = @"/path/to/query/image";
var results = new List<SimilarPersistedFace[]>();
using (Stream stream = File.OpenRead(QueryImagePath))
{
    var faces = faceClient.Face.DetectWithStreamAsync(stream).Result;
    foreach (var face in faces)
    {
        results.Add(await faceClient.Face.FindSimilarAsync(face.FaceId, FaceListId, 20));
    }
}

Ao migrá-los para a LargeFaceList, passa a se parecer com o seguinte:

// Create a LargeFaceList.
const string LargeFaceListId = "mylargefacelistid_001";
const string LargeFaceListName = "MyLargeFaceListDisplayName";
const string ImageDir = @"/path/to/FaceList/images";
faceClient.LargeFaceList.CreateAsync(LargeFaceListId, LargeFaceListName).Wait();

// Add Faces to the LargeFaceList.
Parallel.ForEach(
    Directory.GetFiles(ImageDir, "*.jpg"),
    async imagePath =>
        {
            using (Stream stream = File.OpenRead(imagePath))
            {
                await faceClient.LargeFaceList.AddFaceFromStreamAsync(LargeFaceListId, stream);
            }
        });

// Train() is newly added operation for LargeFaceList.
// Must call it before FindSimilarAsync() to ensure the newly added faces searchable.
await TrainLargeFaceList(LargeFaceListId);

// Perform FindSimilar.
const string QueryImagePath = @"/path/to/query/image";
var results = new List<SimilarPersistedFace[]>();
using (Stream stream = File.OpenRead(QueryImagePath))
{
    var faces = faceClient.Face.DetectWithStreamAsync(stream).Result;
    foreach (var face in faces)
    {
        results.Add(await faceClient.Face.FindSimilarAsync(face.FaceId, largeFaceListId: LargeFaceListId));
    }
}

Como já mostramos antes, o gerenciamento de dados e a parte FindSimilar são quase iguais. A única exceção é que um novo pré-processamento da operação Treinar deve ser executado na LargeFaceList para que a operação FindSimilar funcione.

Etapa 3: Treinar sugestões

Embora a operação Treinar acelere as operações FindSimilar e Identificação, o tempo de treinamento é afetado, principalmente quando é realizado em grande escala. O tempo de treinamento estimado em escalas diferentes está listado na tabela a seguir.

Escala de faces ou pessoas Tempo de treinamento estimado
1,000 1 a 2 segundos
10.000 5 a 10 segundos
100.000 1 a 2 minutos
1\.000.000 10 a 30 minutos

Para usar o recurso de grande escala da maneira ideal, convém implementar as estratégias a seguir.

Etapa 3.1: Personalizar o intervalo de tempo

Conforme demonstrado em TrainLargeFaceList(), há um intervalo de tempo em milissegundos para atrasar o processo de verificação de status de treinamento infinito. Para a LargeFaceList com mais rostos, usar um intervalo maior reduz o número e o custo das chamadas. Personalize o intervalo de tempo de acordo com a capacidade esperada da LargeFaceList.

A mesma estratégia também se aplica ao LargePersonGroup. Por exemplo, quando você treina um LargePersonGroup com um milhão de pessoas, o timeIntervalInMilliseconds deverá ser 60.000, o que constitui um intervalo de um minuto.

Etapa 3.2: Buffer de pequena escala

As pessoas ou rostos em um LargePersonGroup ou uma LargeFaceList são pesquisáveis apenas após terem sido treinados. Em um cenário dinâmico, novas pessoas ou faces são constantemente adicionadas e devem ser imediatamente pesquisáveis, mesmo que o treinamento leve mais tempo do que o esperado.

Para atenuar esse problema, use um LargePersonGroup ou uma LargeFaceList adicionais de dimensões reduzidas como um buffer, somente para as inserções recém-adicionadas. Este buffer consome menos tempo em treinamento devido ao tamanho menor. O recurso de pesquisa imediata deve funcionar neste buffer temporário. Use esse buffer combinado com o treinamento no LargePersonGroup ou LargeFaceList mestres executando o treinamento mestre em um intervalo mais esparso. por exemplo, à meia-noite e diariamente.

Fluxo de trabalho de exemplo:

  1. Crie um LargePersonGroup ou uma LargeFaceList mestres, o que constitui a coleção mestre. Crie um LargePersonGroup ou uma LargeFaceList para servirem de buffer, o que constitui a coleção de buffers. A coleção de buffers se destina apenas a pessoas ou faces recém-adicionadas.
  2. Adicione novas pessoas ou faces à coleção mestra e à coleção de buffers.
  3. Treine apenas a coleção de buffers com um intervalo de tempo curto para garantir que as entradas recém-adicionadas tenham efeito.
  4. Chame a Identificação ou FindSimilar tanto para a coleção mestre quanto para a coleção de buffers. Mescle os resultados.
  5. Se o tamanho da coleção de buffers aumentar para um determinado limite ou em um tempo ocioso do sistema, crie uma nova coleção de buffers. Acione a operação Treinar na coleção mestre.
  6. Exclua a coleção de buffers antiga após o término da operação Treinar na coleção mestre.

Etapa 3.3: Treinamento autônomo

Se uma latência relativamente longa for aceitável, não será necessário acionar a operação Treinar imediatamente após adicionar novos dados. Em vez disso, a operação Treinar pode ser separada da lógica principal e acionada regularmente. Esta estratégia é adequada para cenários dinâmicos com uma latência aceitável. Pode ser aplicada a cenários estáticos para reduzir ainda mais a frequência da operação Treinar.

Digamos que haja uma função TrainLargePersonGroup semelhante a TrainLargeFaceList. Uma implementação típica de um treinamento autônomo em um LargePersonGroup invocando a classe Timer em System.Timers seria:

private static void Main()
{
    // Create a LargePersonGroup.
    const string LargePersonGroupId = "mylargepersongroupid_001";
    const string LargePersonGroupName = "MyLargePersonGroupDisplayName";
    faceClient.LargePersonGroup.CreateAsync(LargePersonGroupId, LargePersonGroupName).Wait();

    // Set up standalone training at regular intervals.
    const int TimeIntervalForStatus = 1000 * 60; // 1-minute interval for getting training status.
    const double TimeIntervalForTrain = 1000 * 60 * 60; // 1-hour interval for training.
    var trainTimer = new Timer(TimeIntervalForTrain);
    trainTimer.Elapsed += (sender, args) => TrainTimerOnElapsed(LargePersonGroupId, TimeIntervalForStatus);
    trainTimer.AutoReset = true;
    trainTimer.Enabled = true;

    // Other operations like creating persons, adding faces, and identification, except for Train.
    // ...
}

private static void TrainTimerOnElapsed(string largePersonGroupId, int timeIntervalInMilliseconds)
{
    TrainLargePersonGroup(largePersonGroupId, timeIntervalInMilliseconds).Wait();
}

Para saber mais sobre gerenciamento de dados e implementações relacionadas à identificação, confira os tópicos Adicionar rostos.

Resumo

Neste guia, você aprendeu como migrar o código existente de um PersonGroup ou de uma FaceList, sem dados, para um LargePersonGroup ou uma LargeFaceList:

  • Um LargePersonGroup e uma LargeFaceList funcionam de modo semelhante a um PersonGroup ou uma FaceList, com a exceção de que a operação Treinar é obrigatória para uma LargeFaceList.
  • Adote a estratégia adequada da operação Treinar para uma atualização dinâmica de dados em conjuntos de dados de grandes dimensões.

Próximas etapas

Siga um guia de instruções para aprender a adicionar rostos a um PersonGroup ou escreva um script para realizar a operação Identificar em um PersonGroup.