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

A tarefa MediaPipe Face Scoreer permite detectar pontos de referência de rostos 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 tridimensionais faciais, pontuações de formas mistas (coeficientes que representam expressões faciais) 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 na Web para ver essa tarefa em ação. Para mais informações sobre os recursos, modelos e opções de configuração dessa 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 marco de rostos 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 características faciais em imagens e vídeos da galeria do dispositivo.

Você pode usar o app como ponto de partida para o seu 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
    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 abaixo 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 Markdown usa a biblioteca MediaPipeTasksVision, que precisa ser instalada com 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 Pointser, consulte a visão geral da tarefa Seção Modelos.

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 Como 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 que um Face Markdown com opções de configuração personalizadas seja inicializado com opções de configuração personalizadas, use o inicializador FaceLandmarker(modelPath:) para criar um Face Markdown 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 faceLandmarkerLiveStreamDelegate extra, que permite que o Face Marcer forneça resultados desse tipo ao delegado de forma assíncrona.

Escolha a guia correspondente ao 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ê usar o modo de vídeo ou de transmissão ao vivo, o Face Markdown vai usar o rastreamento para evitar o acionamento do 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 para a 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, "faceLandmarkerLiveStreamDelegate" precisa ser definido como uma instância de uma classe que implementa "FaceLandmarkerLiveStreamDelegate" para receber os resultados da detecção de pontos de referência do rosto de forma assíncrona.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} {RunningMode.image}
numFaces O número máximo de rostos que podem ser detectados pelo Face Landmarker. A suavizaçã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. Float [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. Float [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 de rosto 3D. Booleano falso
outputFacialTransformationMatrixes Define se FaceLandmarker gera 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. MPImage oferece suporte a diferentes tipos de formatos de imagem do iOS e pode usá-los em qualquer modo em 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 exigido 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: imagens de um pacote de apps, uma galeria do usuário ou um sistema de arquivos formatadas como imagens 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 uma MPImage com a orientação UIImage.Orientation.Up padrão. É possível inicializar uma MPImage com qualquer um dos valores UIImage.Orientation compatíveis. O marco facial não oferece suporte a orientações espelhadas, como .upMirrored, .downMirrored, .leftMirrored, .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 marco de rostos 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 ao Face Markdown 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 do desenvolvedor 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, você também precisa fornecer o carimbo de data/hora do frame de entrada para a tarefa "Face Markdowner".

  • 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 "Face Markdowner" retorna 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 pontos de referência 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 depois de processá-los.

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 abaixo mostra uma visualização da saída da tarefa:

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