Guia de detecção de pontos de referência do rosto para iOS

A tarefa MediaPipe Face Landmarker permite detectar pontos de referência do rosto e expressões faciais em imagens e vídeos. Você pode usar essa tarefa para identificar expressões faciais humanas, aplicar filtros e efeitos faciais e criar avatares virtuais. Essa tarefa usa modelos de machine learning (ML) que podem funcionar com imagens únicas, vídeos ou um fluxo contínuo de imagens. A tarefa gera pontos de referência faciais tridimensionais, pontuações de blendshape (coeficientes que representam a expressão facial) para inferir superfícies faciais detalhadas em tempo real e matrizes de transformação para realizar as transformações necessárias para a renderização de efeitos.

O exemplo de código descrito nestas instruções está disponível no GitHub. Confira esta demonstração da Web para conferir essa tarefa em ação. Para mais informações sobre os recursos, modelos e opções de configuração desta tarefa, consulte a Visão geral.

Exemplo de código

O código de exemplo do MediaPipe Tasks é uma implementação básica de um app de ponto de referência do rosto para iOS. O exemplo usa a câmera em um dispositivo iOS físico para detectar pontos de referência faciais em uma transmissão de vídeo contínua. O app também pode detectar pontos de referência do rosto em imagens e vídeos da galeria do dispositivo.

Você pode usar o app como ponto de partida para o seu próprio app iOS ou se referir a ele ao modificar um app existente. O código de exemplo do Face Landmarker está hospedado no GitHub.

Fazer o download do código

As instruções a seguir mostram como criar uma cópia local do código de exemplo usando a ferramenta de linha de comando git.

Para fazer o download do código de exemplo:

  1. Clone o repositório do Git usando o seguinte comando:

    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Como opção, configure sua instância do Git para usar o checkout esparso, para que você tenha apenas os arquivos do app de exemplo do Face Landmarker:

    cd mediapipe-samples
    git sparse-checkout init --cone
    git sparse-checkout set examples/face_landmarker/ios
    

Depois de criar uma versão local do código de exemplo, é possível instalar a biblioteca de tarefas do MediaPipe, abrir o projeto usando o Xcode e executar o app. Para instruções, consulte o Guia de configuração para iOS.

Principais componentes

Os arquivos a seguir contêm o código crucial para o exemplo de aplicativo Face Landmarker:

Configuração

Esta seção descreve as principais etapas para configurar seu ambiente de desenvolvimento e projetos de código para usar o Face Landmarker. Para informações gerais sobre como configurar seu ambiente de desenvolvimento para usar tarefas do MediaPipe, incluindo os requisitos de versão da plataforma, consulte o Guia de configuração para iOS.

Dependências

O Face Landmarker usa a biblioteca MediaPipeTasksVision, que precisa ser instalada usando o CocoaPods. A biblioteca é compatível com apps Swift e Objective-C e não requer nenhuma configuração específica da linguagem.

Para instruções sobre como instalar o CocoaPods no MacOS, consulte o Guia de instalação do CocoaPods. Para instruções sobre como criar um Podfile com os pods necessários para seu app, consulte Como usar CocoaPods.

Adicione o pod MediaPipeTasksVision no Podfile usando o seguinte código:

target 'MyFaceLandmarkerApp' do
  use_frameworks!
  pod 'MediaPipeTasksVision'
end

Se o app incluir destinos de teste de unidade, consulte o Guia de configuração para iOS para mais informações sobre como configurar o Podfile.

Modelo

A tarefa do MediaPipe Face Landmarker requer um pacote de modelo treinado que seja compatível com essa tarefa. Para mais informações sobre os modelos treinados disponíveis para o Face Landmarker, consulte a seção de modelos da visão geral da tarefa.

Selecione e faça o download de um modelo e adicione-o ao diretório do projeto usando o Xcode. Para instruções sobre como adicionar arquivos ao projeto do Xcode, consulte Gerenciar arquivos e pastas no projeto do Xcode.

Use a propriedade BaseOptions.modelAssetPath para especificar o caminho para o modelo no app bundle. Para conferir um exemplo de código, consulte a próxima seção.

Criar a tarefa

É possível criar a tarefa de detecção de pontos de referência do rosto chamando um dos inicializadores dela. O inicializador FaceLandmarker(options:) aceita valores para as opções de configuração.

Se você não precisar de um Face Landmarker inicializado com opções de configuração personalizadas, use o inicializador FaceLandmarker(modelPath:) para criar um Face Landmarker com as opções padrão. Para mais informações sobre as opções de configuração, consulte a Visão geral da configuração.

A tarefa Face Landmarker oferece suporte a três tipos de dados de entrada: imagens estáticas, arquivos de vídeo e transmissões de vídeo ao vivo. Por padrão, FaceLandmarker(modelPath:) inicializa uma tarefa para imagens estáticas. Se você quiser que a tarefa seja inicializada para processar arquivos de vídeo ou transmissões de vídeo ao vivo, use FaceLandmarker(options:) para especificar o modo de execução do vídeo ou da transmissão ao vivo. O modo de transmissão ao vivo também requer a opção de configuração adicional faceLandmarkerLiveStreamDelegate, que permite que o Face Landmarker transmita resultados de marcadores de rosto para o delegado de forma assíncrona.

Escolha a guia correspondente ao seu modo de execução para saber como criar a tarefa e executar a inferência.

Swift

Imagem

import MediaPipeTasksVision

let modelPath = Bundle.main.path(
  forResource: "face_landmarker",
  ofType: "task")

let options = FaceLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .image
options.minFaceDetectionConfidence = minFaceDetectionConfidence
options.minFacePresenceConfidence = minFacePresenceConfidence
options.minTrackingConfidence = minTrackingConfidence
options.numFaces = numFaces

let faceLandmarker = try FaceLandmarker(options: options)
    

Vídeo

import MediaPipeTasksVision

let modelPath = Bundle.main.path(
  forResource: "face_landmarker",
  ofType: "task")

let options = FaceLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.minFaceDetectionConfidence = minFaceDetectionConfidence
options.minFacePresenceConfidence = minFacePresenceConfidence
options.minTrackingConfidence = minTrackingConfidence
options.numFaces = numFaces

let faceLandmarker = try FaceLandmarker(options: options)
    

Transmissão ao vivo

import MediaPipeTasksVision

// Class that conforms to the `FaceLandmarkerLiveStreamDelegate` protocol and
// implements the method that the face landmarker calls once it finishes
// performing face landmark detection in each input frame.
class FaceLandmarkerResultProcessor: NSObject, FaceLandmarkerLiveStreamDelegate {

  func faceLandmarker(
    _ faceLandmarker: FaceLandmarker,
    didFinishDetection result: FaceLandmarkerResult?,
    timestampInMilliseconds: Int,
    error: Error?) {

    // Process the face landmarker result or errors here.

  }
}

let modelPath = Bundle.main.path(
  forResource: "face_landmarker",
  ofType: "task")

let options = FaceLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.minFaceDetectionConfidence = minFaceDetectionConfidence
options.minFacePresenceConfidence = minFacePresenceConfidence
options.minTrackingConfidence = minTrackingConfidence
options.numFaces = numFaces

// Assign an object of the class to the `faceLandmarkerLiveStreamDelegate`
// property.
let processor = FaceLandmarkerResultProcessor()
options.faceLandmarkerLiveStreamDelegate = processor

let faceLandmarker = try FaceLandmarker(options: options)
    

Objective-C

Imagem

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"face_landmarker"
                                                      ofType:@"task"];

MPPFaceLandmarkerOptions *options = [[MPPFaceLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.minFaceDetectionConfidence = minFaceDetectionConfidence;
options.minFacePresenceConfidence = minFacePresenceConfidence;
options.minTrackingConfidence = minTrackingConfidence;
options.numFaces = numFaces;

MPPFaceLandmarker *faceLandmarker =
  [[MPPFaceLandmarker alloc] initWithOptions:options error:nil];
    

Vídeo

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"face_landmarker"
                                                      ofType:@"task"];

MPPFaceLandmarkerOptions *options = [[MPPFaceLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.minFaceDetectionConfidence = minFaceDetectionConfidence;
options.minFacePresenceConfidence = minFacePresenceConfidence;
options.minTrackingConfidence = minTrackingConfidence;
options.numFaces = numFaces;

MPPFaceLandmarker *faceLandmarker =
  [[MPPFaceLandmarker alloc] initWithOptions:options error:nil];
    

Transmissão ao vivo

@import MediaPipeTasksVision;

// Class that conforms to the `MPPFaceLandmarkerLiveStreamDelegate` protocol
// and implements the method that the face landmarker calls once it finishes
// performing face landmark detection in each input frame.
@interface APPFaceLandmarkerResultProcessor : NSObject 

@end

@implementation APPFaceLandmarkerResultProcessor

-   (void)faceLandmarker:(MPPFaceLandmarker *)faceLandmarker
    didFinishDetectionWithResult:(MPPFaceLandmarkerResult *)faceLandmarkerResult
         timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                           error:(NSError *)error {

    // Process the face landmarker result or errors here.

}

@end

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"face_landmarker"
                                                      ofType:@"task"];

MPPFaceLandmarkerOptions *options = [[MPPFaceLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.minFaceDetectionConfidence = minFaceDetectionConfidence;
options.minFacePresenceConfidence = minFacePresenceConfidence;
options.minTrackingConfidence = minTrackingConfidence;
options.numFaces = numFaces;

// Assign an object of the class to the `faceLandmarkerLiveStreamDelegate`
// property.
APPFaceLandmarkerResultProcessor *processor = [APPFaceLandmarkerResultProcessor new];
options.faceLandmarkerLiveStreamDelegate = processor;

MPPFaceLandmarker *faceLandmarker =
  [[MPPFaceLandmarker alloc] initWithOptions:options error:nil];
    

Observação:se você usa o modo de vídeo ou de transmissão ao vivo, o Face Landmarker usa o rastreamento para evitar acionar o modelo de detecção em cada frame, o que ajuda a reduzir a latência.

Opções de configuração

Esta tarefa tem as seguintes opções de configuração para apps iOS:

Nome da opção Descrição Intervalo de valor Valor padrão
runningMode Define o modo de execução da tarefa. O Face Landmarker tem três modos:

IMAGE: o modo para entradas de imagem única.

VÍDEO: o modo para frames decodificados de um vídeo.

LIVE_STREAM: o modo de transmissão ao vivo de dados de entrada, como de uma câmera. Nesse modo, o `faceLandmarkLiveStreamDelegate` precisa ser definido como uma instância de uma classe que implementa o `FaceLandmarkLiveStreamDelegate` para receber os resultados da detecção assíncrona de pontos de referência do rosto.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} {RunningMode.image}
numFaces O número máximo de rostos que podem ser detectados pelo Face Landmarker. Avização só é aplicada quando numFaces é definida como 1. Número inteiro maior que 0 1
minFaceDetectionConfidence A pontuação de confiança mínima para que a detecção de rosto seja considerada bem-sucedida. Ponto flutuante [0.0,1.0] 0,5
minFacePresenceConfidence A pontuação de confiança mínima da pontuação de presença do rosto na detecção de ponto de referência do rosto. Ponto flutuante [0.0,1.0] 0,5
minTrackingConfidence A pontuação de confiança mínima para que o rastreamento de rosto seja considerado bem-sucedido. Ponto flutuante [0.0,1.0] 0,5
outputFaceBlendshapes Se o FaceLandmarker vai gerar blendshapes faciais. As blendshapes do rosto são usadas para renderizar o modelo 3D do rosto. Booleano falso
outputFacialTransformationMatrixes Se o FaceLandmarker vai gerar a matriz de transformação facial. O FaceLandmarker usa a matriz para transformar os pontos de referência do rosto de um modelo canônico para o rosto detectado, para que os usuários possam aplicar efeitos nos pontos de referência detectados. Booleano falso

Quando o modo de execução está definido como LIVE_STREAM, o Face Landmarker requer a opção de configuração faceLandmarkerLiveStreamDelegate adicional, que permite que o Face Landmarker forneça resultados de detecção de pontos de referência do rosto de forma assíncrona. O delegado precisa implementar o método faceLandmarker(_:didFinishDetection:timestampInMilliseconds:error:), que o Face Landmarker chama após processar os resultados da detecção de pontos de referência faciais em cada frame.

Nome da opção Descrição Intervalo de valor Valor padrão
faceLandmarkerLiveStreamDelegate Permite que o Face Landmarker receba os resultados da detecção de pontos de referência do rosto de forma assíncrona no modo de transmissão ao vivo. A classe que tem a instância definida para essa propriedade precisa implementar o método faceLandmarker(_:didFinishDetection:timestampInMilliseconds:error:). Não relevante Não definido

Preparar dados

É necessário converter a imagem ou o frame de entrada em um objeto MPImage antes de transmiti-lo ao Face Landmarker. O MPImage oferece suporte a diferentes tipos de formatos de imagem do iOS e pode usá-los em qualquer modo de execução para inferência. Para mais informações sobre MPImage, consulte a API MPImage.

Escolha um formato de imagem do iOS com base no seu caso de uso e no modo de execução requerido pelo aplicativo.MPImage aceita os formatos de imagem UIImage, CVPixelBuffer e CMSampleBuffer do iOS.

UIImage

O formato UIImage é adequado para os seguintes modos de execução:

  • Imagens: as imagens de um pacote de apps, galeria de usuários ou sistema de arquivos formatadas como UIImage podem ser convertidas em um objeto MPImage.

  • Vídeos: use AVAssetImageGenerator para extrair frames de vídeo no formato CGImage e converta-os em imagens UIImage.

Swift

// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(uiImage: image)
    

Objective-C

// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

O exemplo inicializa um MPImage com a orientação padrão UIImage.Orientation.Up. É possível inicializar uma MPImage com qualquer um dos valores UIImage.Orientation compatíveis. O Face Landmarker não oferece suporte a orientações espelhadas, como .upMirrored, .downMirrored, .leftMirrored e .rightMirrored.

Para mais informações sobre UIImage, consulte a documentação para desenvolvedores da Apple de UIImage (em inglês).

CVPixelBuffer

O formato CVPixelBuffer é adequado para aplicativos que geram frames e usam o framework CoreImage do iOS para processamento.

O formato CVPixelBuffer é adequado para os seguintes modos de execução:

  • Imagens: apps que geram imagens CVPixelBuffer após algum processamento usando o framework CoreImage do iOS podem ser enviados para o Face Landmarker no modo de execução de imagem.

  • Vídeos: os frames de vídeo podem ser convertidos para o formato CVPixelBuffer para processamento e, em seguida, enviados para o Face Landmarker no modo de vídeo.

  • Transmissão ao vivo: os apps que usam uma câmera do iOS para gerar frames podem ser convertidos no formato CVPixelBuffer para processamento antes de serem enviados para o Face Landmarker no modo de transmissão ao vivo.

Swift

// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(pixelBuffer: pixelBuffer)
    

Objective-C

// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

Para mais informações sobre CVPixelBuffer, consulte a documentação para desenvolvedores da Apple CVPixelBuffer.

CMSampleBuffer

O formato CMSampleBuffer armazena amostras de mídia de um tipo uniforme e é adequado para o modo de execução de transmissões ao vivo. Os frames ao vivo das câmeras do iOS são enviados de forma assíncrona no formato CMSampleBuffer pelo AVCaptureVideoDataOutput do iOS.

Swift

// Obtain a CMSampleBuffer.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(sampleBuffer: sampleBuffer)
    

Objective-C

// Obtain a `CMSampleBuffer`.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithSampleBuffer:sampleBuffer error:nil];
    

Para mais informações sobre CMSampleBuffer, consulte a documentação para desenvolvedores da Apple CMSampleBuffer (em inglês).

Executar a tarefa

Para executar o Face Landmarker, use o método detect() específico para o modo de execução atribuído:

  • Imagem estática: detect(image:)
  • Vídeo: detect(videoFrame:timestampInMilliseconds:)
  • Transmissão ao vivo: detectAsync(image:timestampInMilliseconds:)

Os exemplos de código a seguir mostram exemplos básicos de como executar o Face Landmarker nesses diferentes modos de execução:

Swift

Imagem

let result = try faceLandmarker.detect(image: image)
    

Vídeo

let result = try faceLandmarker.detect(
  videoFrame: image,
  timestampInMilliseconds: timestamp)
    

Transmissão ao vivo

try faceLandmarker.detectAsync(
  image: image,
  timestampInMilliseconds: timestamp)
    

Objective-C

Imagem

MPPFaceLandmarkerResult *result =
  [faceLandmarker detectImage:image error:nil];
    

Vídeo

MPPFaceLandmarkerResult *result =
  [faceLandmarker detectVideoFrame:image
           timestampInMilliseconds:timestamp
                             error:nil];
    

Transmissão ao vivo

BOOL success =
  [faceLandmarker detectAsyncImage:image
           timestampInMilliseconds:timestamp
                             error:nil];
    

O exemplo de código do Face Landmarker mostra as implementações de cada um desses modos com mais detalhes detect(image:), detect(videoFrame:timestampInMilliseconds:) e detectAsync(image:timestampInMilliseconds:). O código de exemplo permite que o usuário alterne entre modos de processamento que podem não ser necessários para seu caso de uso.

Observe o seguinte:

  • Ao executar no modo de vídeo ou de transmissão ao vivo, também é necessário fornecer o carimbo de data/hora do frame de entrada para a tarefa do Face Landmarker.

  • Quando executada no modo de imagem ou vídeo, a tarefa do Face Landmarker bloqueia a linha de execução atual até que ela termine de processar a imagem ou o frame de entrada. Para evitar o bloqueio da linha de execução atual, execute o processamento em uma linha de execução em segundo plano usando os frameworks Dispatch ou NSOperation do iOS. Se o app for criado usando Swift, você também poderá usar a Concorrência do Swift para a execução de linhas de execução em segundo plano.

  • Quando executada no modo de transmissão ao vivo, a tarefa de detecção de pontos faciais é retornada imediatamente e não bloqueia a linha de execução atual. Ele invoca o método faceLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) com o resultado da detecção de marco facial após o processamento de cada frame de entrada. O Face Landmarker invoca esse método de forma assíncrona em uma fila de envio serial dedicada. Para mostrar os resultados na interface do usuário, envie os resultados para a fila principal após o processamento.

Processar e mostrar resultados

Ao executar a inferência, o Face Landmarker retorna uma FaceLandmarkerResult, que contém uma malha de rosto para cada rosto detectado, com coordenadas para cada ponto de referência do rosto. Opcionalmente, o objeto de resultado também pode conter blendshapes, que denotam expressões faciais, e matrizes de transformação facial para aplicar efeitos faciais nos pontos de referência detectados.

Confira a seguir um exemplo dos dados de saída desta tarefa:

FaceLandmarkerResult:
  face_landmarks:
    NormalizedLandmark #0:
      x: 0.5971359014511108
      y: 0.485361784696579
      z: -0.038440968841314316
    NormalizedLandmark #1:
      x: 0.3302789330482483
      y: 0.29289937019348145
      z: -0.09489090740680695
    ... (478 landmarks for each face)
  face_blendshapes:
    browDownLeft: 0.8296722769737244
    browDownRight: 0.8096957206726074
    browInnerUp: 0.00035583582939580083
    browOuterUpLeft: 0.00035752105759456754
    ... (52 blendshapes for each face)
  facial_transformation_matrixes:
    [9.99158978e-01, -1.23036895e-02, 3.91213447e-02, -3.70770246e-01]
    [1.66496094e-02,  9.93480563e-01, -1.12779640e-01, 2.27719707e+01]
    ...

A imagem a seguir mostra uma visualização da saída da tarefa:

Um homem com as regiões do rosto mapeadas geometricamente para indicar a forma e as dimensões do rosto

O código de exemplo do Face Landmarker demonstra como exibir os resultados retornados pela tarefa. Consulte FaceOverlay.swift para mais detalhes.