Guia de detecção de pontos de referência de posições para iOS

A tarefa Pose Scoreer permite detectar pontos de referência de corpos humanos em uma imagem ou vídeo. Você pode usar essa tarefa para identificar as principais localizações do corpo, analisar a postura, e categorizar movimentos. Essa tarefa usa modelos de machine learning (ML) que funcionam com imagens ou vídeos únicos. A tarefa gera pontos de referência de posições do corpo na imagem e em coordenadas mundiais tridimensionais.

Estas instruções mostram como usar o Pose Scoreer com apps iOS. O código o exemplo descrito nestas instruções está disponível em GitHub.

Para saber como essa tarefa funciona, acesse este site demonstração. Para mais informações sobre recursos, modelos e opções de configuração, desta tarefa, consulte a Visão geral.

Exemplo de código

O código de exemplo de tarefas do MediaPipe é uma implementação básica de um ponto de referência de posições para iOS. O exemplo usa a câmera de um dispositivo físico com iOS para detectar detectar poses em um stream de vídeo contínuo. O app também pode detectar poses em imagens e vídeos da galeria do dispositivo.

Você pode usar o app como ponto de partida para seu próprio app iOS ou consultá-lo ao modificar um aplicativo existente. O código de exemplo do Pose Scoreer é hospedado em GitHub.

Fazer o download do código

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

Para fazer o download do código de exemplo:

  1. Clone o repositório git usando o seguinte comando:

    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Opcionalmente, configure sua instância git para usar a finalização esparsa. Assim, você terá somente os arquivos do app de exemplo Pose Scoreer:

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

Depois de criar uma versão local do código de exemplo, você pode instalar o MediaPipe, abrir o projeto usando Xcode e executar o app. Para instruções, consulte o Guia de configuração do iOS.

Principais componentes

Os arquivos a seguir contêm o código essencial para o exemplo do Pose Scoreer. aplicativo:

  • PoseLandmarkerService.swift: Inicia o referência, processa a seleção do modelo e executa a inferência nos dados de entrada.
  • CameraViewController: Implementa a interface para o modo de entrada de transmissão da câmera em tempo real e visualiza a pontos de referência.
  • MediaLibraryViewController.swift: Implementa a interface para o modo de entrada de arquivo de vídeo e imagem estática e visualiza os pontos de referência.

Configuração

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

Dependências

O Pose Scoreer usa a biblioteca MediaPipeTasksVision, que precisa ser instalada. usando o CocoaPods. A biblioteca é compatível com aplicativos Swift e Objective-C e não requer configuração específica do idioma.

Para instruções sobre como instalar o CocoaPods no macOS, consulte a documentação do CocoaPods guia de instalação (em inglês). Para instruções sobre como criar um Podfile com os pods necessários para aplicativo, consulte Usar CocoaPods.

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

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

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

Modelo

A tarefa "Ponto de referência de poses do MediaPipe" requer um pacote treinado que seja compatível a essa tarefa. Para mais informações sobre os modelos treinados disponíveis para Faça uma pose de referência, consulte a visão geral da tarefa Modelos .

Use o download_models.sh script para fazer o download dos modelos e adicioná-los ao diretório do projeto usando Xcode. Para para adicionar arquivos ao seu projeto Xcode, consulte Como gerenciar arquivos e pastas no seu arquivo Xcode, projeto.

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

Criar a tarefa

É possível criar a tarefa "Pose Scoreer" chamando um dos inicializadores dele. O O inicializador PoseLandmarker(options:) aceita valores para a configuração. .

Se você não precisa de um ponto de referência de posições inicializado com configuração personalizada você pode usar o inicializador PoseLandmarker(modelPath:) para criar um Posicione o ponto de referência com as opções padrão. Para mais informações sobre configurações opções, consulte Visão geral da configuração.

A tarefa Pose Scoreer é compatível com três tipos de dados de entrada: imagens estáticas e arquivos de vídeo. e transmissões de vídeo ao vivo. Por padrão, PoseLandmarker(modelPath:) inicializa uma para imagens estáticas. Se você quiser que sua tarefa seja inicializada para processar vídeos arquivos ou streams de vídeo ao vivo, use PoseLandmarker(options:) para especificar o ou no modo de corrida ao vivo. O modo de transmissão ao vivo também requer poseLandmarkerLiveStreamDelegate, que ativa Posicione o marco para entregar os resultados da detecção de pontos de referência de poses ao delegado de forma assíncrona.

Escolha a guia correspondente ao modo de corrida para saber como criar a tarefa e executar inferência.

Swift

Imagem

import MediaPipeTasksVision

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

let options = PoseLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .image
options.minPoseDetectionConfidence = minPoseDetectionConfidence
options.minPosePresenceConfidence = minPosePresenceConfidence
options.minTrackingConfidence = minTrackingConfidence
options.numPoses = numPoses

let poseLandmarker = try PoseLandmarker(options: options)
    

Vídeo

import MediaPipeTasksVision

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

let options = PoseLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.minPoseDetectionConfidence = minPoseDetectionConfidence
options.minPosePresenceConfidence = minPosePresenceConfidence
options.minTrackingConfidence = minTrackingConfidence
options.numPoses = numPoses

let poseLandmarker = try PoseLandmarker(options: options)
    

Transmissão ao vivo

import MediaPipeTasksVision

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

  func poseLandmarker(
    _ poseLandmarker: PoseLandmarker,
    didFinishDetection result: PoseLandmarkerResult?,
    timestampInMilliseconds: Int,
    error: Error?) {

    // Process the pose landmarker result or errors here.

  }
}

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

let options = PoseLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.minPoseDetectionConfidence = minPoseDetectionConfidence
options.minPosePresenceConfidence = minPosePresenceConfidence
options.minTrackingConfidence = minTrackingConfidence
options.numPoses = numPoses

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

let poseLandmarker = try PoseLandmarker(options: options)
    

Objective-C

Imagem

@import MediaPipeTasksVision;

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

MPPPoseLandmarkerOptions *options = [[MPPPoseLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.minPoseDetectionConfidence = minPoseDetectionConfidence;
options.minPosePresenceConfidence = minPosePresenceConfidence;
options.minTrackingConfidence = minTrackingConfidence;
options.numPoses = numPoses;

MPPPoseLandmarker *poseLandmarker =
  [[MPPPoseLandmarker alloc] initWithOptions:options error:nil];
    

Vídeo

@import MediaPipeTasksVision;

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

MPPPoseLandmarkerOptions *options = [[MPPPoseLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.minPoseDetectionConfidence = minPoseDetectionConfidence;
options.minPosePresenceConfidence = minPosePresenceConfidence;
options.minTrackingConfidence = minTrackingConfidence;
options.numPoses = numPoses;

MPPPoseLandmarker *poseLandmarker =
  [[MPPPoseLandmarker alloc] initWithOptions:options error:nil];
    

Transmissão ao vivo

@import MediaPipeTasksVision;

// Class that conforms to the `MPPPoseLandmarkerLiveStreamDelegate` protocol
// and implements the method that the pose landmarker calls once it finishes
// performing pose landmarks= detection in each input frame.

@interface APPPoseLandmarkerResultProcessor : NSObject 

@end

@implementation APPPoseLandmarkerResultProcessor

-   (void)poseLandmarker:(MPPPoseLandmarker *)poseLandmarker
    didFinishDetectionWithResult:(MPPPoseLandmarkerResult *)poseLandmarkerResult
         timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                           error:(NSError *)error {

    // Process the pose landmarker result or errors here.

}

@end

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

MPPPoseLandmarkerOptions *options = [[MPPPoseLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.minPoseDetectionConfidence = minPoseDetectionConfidence;
options.minPosePresenceConfidence = minPosePresenceConfidence;
options.minTrackingConfidence = minTrackingConfidence;
options.numPoses = numPoses;

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

MPPPoseLandmarker *poseLandmarker =
  [[MPPPoseLandmarker alloc] initWithOptions:options error:nil];
    

Observação:se você usar o modo de vídeo ou de transmissão ao vivo, o ponto de referência de postura usará para evitar o acionamento do modelo de detecção de palma em cada frame, o que ajuda e 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
running_mode Define o modo de execução da tarefa. Existem três modos:

IMAGEM: 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 da entrada dados de uma câmera, por exemplo. Neste modo, poseLandmarkerLiveStreamDelegate precisa ser definido como uma instância de uma classe que implementa o PoseLandmarkerLiveStreamDelegate para receber os resultados de realizando detecção de ponto de referência de pose de forma assíncrona.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} RunningMode.image
num_poses O número máximo de poses que podem ser detectadas pelo Faça uma pose de referência. Integer > 0 1
min_pose_detection_confidence A pontuação de confiança mínima para que a detecção de pose seja considerada bem-sucedida. Float [0.0,1.0] 0.5
min_pose_presence_confidence A pontuação de confiança mínima da presença de pose na detecção de pontos de referência de poses. Float [0.0,1.0] 0.5
min_tracking_confidence A pontuação de confiança mínima para o rastreamento de pose para ser considerado bem-sucedido. Float [0.0,1.0] 0.5
output_segmentation_masks Define se o Pose Scoreer gera uma máscara de segmentação para o objeto detectado. pose Boolean False
result_callback Define o listener de resultados para receber os resultados do detector de ponto de referência. de forma assíncrona quando o marcador de posição está no modo de transmissão ao vivo. Só pode ser usado quando o modo de corrida está definido como LIVE_STREAM ResultListener N/A

Configuração da transmissão ao vivo

Quando o modo de corrida está definido como transmissão ao vivo, o Pose Scoreer requer o opção de configuração poseLandmarkerLiveStreamDelegate extra, que permite que o Pose Scoreer forneça resultados de detecção de poses de pontos de referência de forma assíncrona. O delegado deve implementar o método poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:), que o posto de referência chama depois de processar os resultados da postura detecção de pontos de referência em cada frame.

Nome da opção Descrição Intervalo de valor Valor padrão
poseLandmarkerLiveStreamDelegate Permite que o marcador de posição receba os resultados da pose detecção de pontos de referência de forma assíncrona no modo de transmissão ao vivo. A classe cuja estiver definida como essa propriedade deve implementar o poseLandmarker(_: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 passando para o Ponto de referência da postura. MPImage oferece suporte a diferentes tipos de imagens do iOS formatos e pode usá-los em qualquer modo em execução para inferência. Para mais informações sobre MPImage, consulte API MPImage

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

UIImage

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

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

  • Vídeos: use AVAssetImageGenerator para extrair frames de vídeo CGImage formato e converta-as 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 o UIImage.Orientation.Up orientação. É possível inicializar um MPImage com qualquer um dos UIImage.Orientation e a distribuição dos valores dos dados. O ponto de referência de posições não é compatível com orientações espelhadas como .upMirrored, .downMirrored, .leftMirrored e .rightMirrored.

Para mais informações sobre o UIImage, consulte a página do desenvolvedor de imagens de usuário Documentação.

CVPixelBuffer

O formato CVPixelBuffer é adequado para aplicativos que geram frames e usar a interface CoreImage do iOS para processamento.

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

  • Imagens: apps que geram imagens de CVPixelBuffer após algum processamento. usando o framework CoreImage do iOS, podem ser enviadas ao Pose Scoreer na modo de execução de imagem.

  • Vídeos: os quadros podem ser convertidos para o formato CVPixelBuffer para processamento e, em seguida, enviada para o ponto de referência de posições no modo de vídeo.

  • Transmissão ao vivo: apps que usam a câmera do iOS para gerar frames podem ser convertidos no formato CVPixelBuffer para processamento antes de ser enviado ao Posicione o marco 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 o CVPixelBuffer, consulte a documentação da Apple CVPixelBuffer Desenvolvedor Documentação.

CMSampleBuffer

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

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 o CMSampleBuffer, consulte a documentação da Apple do CMSampleBuffer Desenvolvedor Documentação.

Executar a tarefa

Para executar o ponto de referência de poses, use o método detect() específico para o modo de corrida:

  • 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 simples de como executar o Pose Scoreer em estes diferentes modos de execução:

Swift

Imagem

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

Vídeo

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

Transmissão ao vivo

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

Objective-C

Imagem

MPPPoseLandmarkerResult *result =
  [poseLandmarker detectImage:image error:nil];
    

Vídeo

MPPPoseLandmarkerResult *result =
  [poseLandmarker detectVideoFrame:image
           timestampInMilliseconds:timestamp
                             error:nil];
    

Transmissão ao vivo

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

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

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 Pose Scoreer.

  • Quando executada no modo de imagem ou vídeo, a tarefa Pose Scoreer bloqueia o linha de execução atual até terminar de processar a imagem ou frame de entrada. Para evite o bloqueio da linha de execução atual, execute o processamento em segundo plano conversa usando iOS Dispatch ou NSOperation frameworks.

  • Quando executada no modo de transmissão ao vivo, a tarefa "Pose Scoreer" retorna imediatamente e não bloqueia a linha de execução atual. Ele invoca Método poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) com o resultado do ponto de referência da pose após o processamento de cada frame de entrada. O O Pose Scoreer invoca esse método de forma assíncrona em um número de série dedicado. fila de despacho. Para exibir resultados na interface do usuário, envie o para a fila principal após o processamento dos resultados. Se o detectAsync é chamada quando a tarefa "Ponto de referência de postura" está ocupada processando outro o frameer de posições ignora o novo frame de entrada.

Gerenciar e exibir resultados

Ao executar a inferência, a tarefa "Pose Scoreer" retorna um PoseLandmarkerResult. que contém as coordenadas de cada ponto de referência da pose.

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

PoseLandmarkerResult:
  Landmarks:
    Landmark #0:
      x            : 0.638852
      y            : 0.671197
      z            : 0.129959
      visibility   : 0.9999997615814209
      presence     : 0.9999984502792358
    Landmark #1:
      x            : 0.634599
      y            : 0.536441
      z            : -0.06984
      visibility   : 0.999909
      presence     : 0.999958
    ... (33 landmarks per pose)
  WorldLandmarks:
    Landmark #0:
      x            : 0.067485
      y            : 0.031084
      z            : 0.055223
      visibility   : 0.9999997615814209
      presence     : 0.9999984502792358
    Landmark #1:
      x            : 0.063209
      y            : -0.00382
      z            : 0.020920
      visibility   : 0.999976
      presence     : 0.999998
    ... (33 world landmarks per pose)
  SegmentationMasks:
    ... (pictured below)

A saída contém coordenadas normalizadas (Landmarks) e coordenadas mundiais coordenadas (WorldLandmarks) para cada ponto de referência.

A saída contém as seguintes coordenadas normalizadas (Landmarks):

  • x e y: coordenadas de ponto de referência normalizadas entre 0,0 e 1,0 pelo largura (x) e altura (y) da imagem.

  • z: a profundidade do ponto de referência, com a profundidade no ponto médio dos quadris como origem. Quanto menor o valor, mais perto o ponto de referência está da câmera. O a magnitude de z usa aproximadamente a mesma escala de x.

  • visibility: a probabilidade de o ponto de referência ficar visível na imagem.

A saída contém as seguintes coordenadas mundiais (WorldLandmarks):

  • x, y e z: coordenadas tridimensionais reais em metros, com o ponto médio dos quadris como origem.

  • visibility: a probabilidade de o ponto de referência ficar visível na imagem.

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

A máscara de segmentação opcional representa a probabilidade de cada pixel pertencer para uma pessoa detectada. A imagem a seguir é uma máscara de segmentação da saída da tarefa:

O código de exemplo do Pose Scoreer demonstra como exibir o Pose Scoreer. resultados.