Guida al rilevamento dei punti di riferimento in posa per iOS

L'attività di rilevamento di punti di riferimento della posa consente di rilevare i punti di riferimento dei corpi umani in un'immagine o un video. Puoi utilizzare questa attività per identificare le posizioni chiave del corpo, analizzare la postura e classificare i movimenti. Questa attività utilizza modelli di machine learning (ML) che funzionano con singole immagini o video. L'attività genera i punti di riferimento della posa del corpo nelle coordinate dell'immagine e nelle coordinate del mondo tridimensionale.

Queste istruzioni mostrano come utilizzare il rilevamento di punti di riferimento con le app per iOS. Il codice saggio descritto in queste istruzioni è disponibile su GitHub.

Puoi vedere questa attività in azione visualizzando questa demo web. Per saperne di più sulle funzionalità, sui modelli e sulle opzioni di configurazione di questa attività, consulta la Panoramica.

Esempio di codice

Il codice di esempio di MediaPipe Tasks è un'implementazione di base di un'app di rilevamento di punti di riferimento per iOS. L'esempio utilizza la fotocamera su un dispositivo iOS fisico per rilevare le pose in uno stream video continuo. L'app può anche rilevare le pose nelle immagini e nei video della galleria del dispositivo.

Puoi utilizzare l'app come punto di partenza per la tua app per iOS o farvi riferimento quando modifichi un'app esistente. Il codice di esempio di Pose Landmarker è ospitato su GitHub.

Scarica il codice

Le istruzioni riportate di seguito mostrano come creare una copia locale del codice di esempio utilizzando lo strumento a riga di comando git.

Per scaricare il codice di esempio:

  1. Clona il repository git utilizzando il seguente comando:

    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Facoltativamente, configura l'istanza Git in modo da utilizzare il controllo sparse, in modo da avere solo i file per l'app di esempio di rilevamento di punti di riferimento di pose:

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

Dopo aver creato una versione locale del codice di esempio, puoi installare la libreria di attività MediaPipe, aprire il progetto utilizzando Xcode ed eseguire l'app. Per le istruzioni, consulta la Guida alla configurazione per iOS.

Componenti chiave

I seguenti file contengono il codice fondamentale per l'applicazione di esempio di rilevamento di punti di riferimento di pose:

  • PoseLandmarkerService.swift: inizializza il landmarker, gestisce la selezione del modello ed esegue l'inferenza sui dati di input.
  • CameraViewController: implementa l'interfaccia utente per la modalità di inserimento del feed della videocamera in diretta e visualizza i punti di riferimento.
  • MediaLibraryViewController.swift: implementa l'interfaccia utente per la modalità di inserimento di immagini e file video e visualizza i punti di riferimento.

Configurazione

Questa sezione descrive i passaggi chiave per configurare l'ambiente di sviluppo e i progetti di codice per utilizzare Pose Landmarker. Per informazioni generali sulla configurazione dell'ambiente di sviluppo per l'utilizzo delle attività MediaPipe, inclusi i requisiti della versione della piattaforma, consulta la guida alla configurazione per iOS.

Dipendenze

Pose Landmarker utilizza la libreria MediaPipeTasksVision, che deve essere installata utilizzando CocoaPods. La libreria è compatibile con le app Swift e Objective-C e non richiede alcuna configurazione aggiuntiva specifica per il linguaggio.

Per istruzioni su come installare CocoaPods su macOS, consulta la guida all'installazione di CocoaPods. Per istruzioni su come creare un Podfile con i pod necessari per la tua app, consulta Utilizzare CocoaPods.

Aggiungi il pod MediaPipeTasksVision in Podfile utilizzando il seguente codice:

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

Se la tua app include target di test di unità, consulta la Guida alla configurazione per iOS per ulteriori informazioni sulla configurazione del tuo Podfile.

Modello

L'attività MediaPipe Pose Landmarker richiede un bundle addestrato compatibile con questa attività. Per ulteriori informazioni sui modelli addestrati disponibili per Posa di landmark, consulta la sezione Modelli della panoramica dell'attività.

Utilizza lo script download_models.sh per scaricare i modelli e aggiungerli alla directory del progetto utilizzando Xcode. Per istruzioni su come aggiungere file al progetto Xcode, consulta Gestire file e cartelle nel progetto Xcode.

Utilizza la proprietà BaseOptions.modelAssetPath per specificare il percorso del modello nel tuo app bundle. Per un esempio di codice, consulta la sezione successiva.

Crea l'attività

Puoi creare l'attività di rilevamento di punti di riferimento tramite pose chiamando uno dei relativi inizializzatori. L'inizializzatore PoseLandmarker(options:) accetta i valori per le opzioni di configurazione.

Se non hai bisogno di un landmarker di pose inizializzato con opzioni di configurazione personalizzate, puoi utilizzare l'inizializzatore PoseLandmarker(modelPath:) per creare un landmarker di pose con le opzioni predefinite. Per ulteriori informazioni sulle opzioni di configurazione, consulta Panoramica della configurazione.

L'attività di rilevamento di punti di riferimento della posa supporta tre tipi di dati di input: immagini fisse, file video e live streaming video. Per impostazione predefinita, PoseLandmarker(modelPath:) inizializza un compito per le immagini fisse. Se vuoi che l'attività venga inizializzata per elaborare file video o stream video in diretta, utilizza PoseLandmarker(options:) per specificare la modalità di esecuzione del video o del live streaming. La modalità live streaming richiede anche l'opzione di configurazione aggiuntiva poseLandmarkerLiveStreamDelegate, che consente a Pose Landmarker di inviare i risultati del rilevamento dei landmark della posa al delegato in modo asincrono.

Scegli la scheda corrispondente alla modalità di esecuzione per scoprire come creare il compito e eseguire l'inferenza.

Swift

Immagine

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)
    

Video

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)
    

Live streaming

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

Immagine

@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];
    

Video

@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];
    

Live streaming

@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];
    

Nota: se utilizzi la modalità video o la modalità live streaming, la funzionalità Spostamento di oggetti in base alla posizione utilizza il monitoraggio per evitare di attivare il modello di rilevamento del palmo su ogni fotogramma, il che contribuisce a ridurre la latenza.

Opzioni di configurazione

Questa attività offre le seguenti opzioni di configurazione per le app per iOS:

Nome opzione Descrizione Intervallo di valori Valore predefinito
running_mode Imposta la modalità di esecuzione dell'attività. Esistono tre modalità:

IMMAGINE: la modalità per l'inserimento di singole immagini.

VIDEO: la modalità per i fotogrammi decodificati di un video.

LIVE_STREAM: la modalità per un live streaming di dati di input, ad esempio da una videocamera. In questa modalità, poseLandmarkerLiveStreamDelegate deve essere impostato su un'istanza di una classe che implementa PoseLandmarkerLiveStreamDelegate per ricevere i risultati dell'esecuzione del rilevamento dei punti di riferimento della posa in modo asincrono.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} RunningMode.image
num_poses Il numero massimo di pose che possono essere rilevate da Pose Landmarker. Integer > 0 1
min_pose_detection_confidence Il punteggio di attendibilità minimo per il rilevamento della posa da considerare positivo. Float [0.0,1.0] 0.5
min_pose_presence_confidence Il punteggio di attendibilità minimo del punteggio di presenza della posa nel rilevamento dei punti di riferimento della posa. Float [0.0,1.0] 0.5
min_tracking_confidence Il punteggio di attendibilità minimo per il monitoraggio della posa da considerare riuscito. Float [0.0,1.0] 0.5
output_segmentation_masks Indica se l'indicatore di posizione della posa restituisce una maschera di segmentazione per la posa rilevata. Boolean False
result_callback Imposta l'ascoltatore dei risultati in modo da ricevere i risultati del rilevamento di punti di riferimento in modo asincrono quando la funzionalità è in modalità live streaming. Può essere utilizzato solo quando la modalità di esecuzione è impostata su LIVE_STREAM ResultListener N/A

Configurazione del live streaming

Quando la modalità di esecuzione è impostata su live streaming, il rilevamento di landmark di pose richiede l'opzione di configurazione aggiuntiva poseLandmarkerLiveStreamDelegate, che consente al rilevamento di landmark di pose di fornire i risultati in modo asincrono. Il delegato deve implementare il metodo poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:), chiamato da Rilevamento di landmark della posa dopo l'elaborazione dei risultati dell'esecuzione del rilevamento di landmark della posa su ogni fotogramma.

Nome opzione Descrizione Intervallo di valori Valore predefinito
poseLandmarkerLiveStreamDelegate Consente a Pose Landmarker di ricevere i risultati dell'esecuzione del rilevamento dei punti di riferimento della posa in modo asincrono in modalità live streaming. La classe di cui è impostata l'istanza su questa proprietà deve implementare il metodo poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:). Non applicabile Non impostato

Preparazione dei dati

Devi convertire l'immagine o l'inquadratura di input in un oggetto MPImage prima di passarlo a Pose Landmarker. MPImage supporta diversi tipi di formati di immagini iOS e può utilizzarli in qualsiasi modalità di esecuzione per l'inferenza. Per ulteriori informazioni su MPImage, consulta l'API MPImage.

Scegli un formato di immagine iOS in base al tuo caso d'uso e alla modalità di esecuzione richiesta dalla tua applicazione.MPImage accetta i formati di immagine iOS UIImage, CVPixelBuffer e CMSampleBuffer.

UIImage

Il formato UIImage è adatto alle seguenti modalità di esecuzione:

  • Immagini: le immagini di un app bundle, della galleria dell'utente o del file system formattate come immagini UIImage possono essere convertite in un oggetto MPImage.

  • Video: utilizza AVAssetImageGenerator per estrarre i frame video nel formato CGImage, quindi convertili in immagini 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];
    

L'esempio inizializza un MPImage con l'orientamento predefinito UIImage.Orientation.Up. Puoi inizializzare un MPImage con uno dei valori supportati di UIImage.Orientation. La funzionalità di rilevamento di punti di riferimento con pose non supporta orientamenti con mirroring come .upMirrored, .downMirrored, .leftMirrored, .rightMirrored.

Per ulteriori informazioni su UIImage, consulta la documentazione per sviluppatori Apple su UIImage.

CVPixelBuffer

Il formato CVPixelBuffer è adatto per le applicazioni che generano frame e utilizzano il framework CoreImage di iOS per l'elaborazione.

Il formato CVPixelBuffer è adatto alle seguenti modalità di esecuzione:

  • Immagini: le app che generano immagini CVPixelBuffer dopo un po' di elaborazione utilizzando il framework CVPixelBuffer di iOS possono essere inviate a Pose Landmarker in modalità di esecuzione delle immagini.CoreImage

  • Video: i fotogrammi dei video possono essere convertiti in formato CVPixelBuffer per l'elaborazione e poi inviati a Pose Landmarker in modalità video.

  • live streaming: le app che utilizzano una fotocamera iOS per generare frame possono essere convertite in formato CVPixelBuffer per l'elaborazione prima di essere inviate a Posa Segnaposto in modalità live streaming.

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];
    

Per ulteriori informazioni su CVPixelBuffer, consulta la documentazione per sviluppatori Apple su CVPixelBuffer.

CMSampleBuffer

Il formato CMSampleBuffer memorizza i sample di media di un tipo di media uniforme ed è adatto alla modalità di esecuzione del live streaming. I frame in tempo reale delle videocamere iOS vengono caricati in modo asincrono nel formato CMSampleBuffer da AVCaptureVideoDataOutput di 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];
    

Per ulteriori informazioni su CMSampleBuffer, consulta la documentazione per sviluppatori Apple su CMSampleBuffer.

Esegui l'attività

Per eseguire il rilevamento di punti di riferimento di pose, utilizza il metodo detect() specifico per la modalità di esecuzione assegnata:

  • Immagine fissa: detect(image:)
  • Video: detect(videoFrame:timestampInMilliseconds:)
  • Live streaming: detectAsync(image:timestampInMilliseconds:)

I seguenti esempi di codice mostrano esempi semplici di come eseguire Pose Landmarker in queste diverse modalità di esecuzione:

Swift

Immagine

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

Video

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

Live streaming

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

Objective-C

Immagine

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

Video

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

Live streaming

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

L'esempio di codice di Landmarker di pose mostra le implementazioni di ciascuna di queste modalità in modo più dettagliato detect(image:), detect(videoFrame:timestampInMilliseconds:) e detectAsync(image:timestampInMilliseconds:). Il codice di esempio consente all'utente di passare da una modalità di elaborazione all'altra, che potrebbe non essere necessaria per il tuo caso d'uso.

Tieni presente quanto segue:

  • Quando esegui l'operazione in modalità video o live streaming, devi anche fornire il timestamp del frame di input all'attività di rilevamento di punti di riferimento delle pose.

  • Quando viene eseguita in modalità immagine o video, l'attività di rilevamento di punti di riferimento della posa blocca il thread corrente fino al termine dell'elaborazione dell'immagine o del frame di input. Per evitare di bloccare il thread corrente, esegui l'elaborazione in un thread in background utilizzando i framework iOS Dispatch o NSOperation.

  • Quando viene eseguita in modalità live streaming, l'attività di rilevamento di punti di riferimento della posa ritorna immediatamente e non blocca il thread corrente. Richiama il metodo poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) con il risultato del rilevamento di punti di riferimento della posa dopo l'elaborazione di ogni frame di input. Il landmarker di pose richiama questo metodo in modo asincrono in una coda di invio seriale dedicata. Per visualizzare i risultati nell'interfaccia utente, inviali alla coda principale dopo averli elaborati. Se la funzione detectAsync viene chiamata quando l'attività di rilevamento di punti di riferimento della posa è impegnata a elaborare un altro fotogramma, il rilevamento di punti di riferimento della posa ignora il nuovo fotogramma di input.

Gestire e visualizzare i risultati

Dopo l'esecuzione dell'inferenza, l'attività di rilevamento di landmark di pose restituisce un PoseLandmarkerResult che contiene le coordinate di ogni landmark di posa.

Di seguito è riportato un esempio dei dati di output di questa attività:

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)

L'output contiene sia le coordinate normalizzate (Landmarks) sia le coordinate mondiali (WorldLandmarks) per ogni punto di riferimento.

L'output contiene le seguenti coordinate normalizzate (Landmarks):

  • x e y: coordinate di punti di riferimento normalizzate tra 0,0 e 1,0 in base alla larghezza (x) e all'altezza (y) dell'immagine.

  • z: la profondità del punto di riferimento, con la profondità al centro dei fianchi come origine. Più basso è il valore, più il punto di riferimento è vicino alla fotocamera. La magnitudine di z utilizza approssimativamente la stessa scala di x.

  • visibility: la probabilità che il punto di riferimento sia visibile all'interno dell'immagine.

L'output contiene le seguenti coordinate mondiali (WorldLandmarks):

  • x, y e z: coordinate tridimensionali reali in metri, con il punto mediano dei fianchi come origine.

  • visibility: la probabilità che il punto di riferimento sia visibile all'interno dell'immagine.

L'immagine seguente mostra una visualizzazione dell'output dell'attività:

Una donna in una posa meditativa. La posa è evidenziata da un wireframe che indica il posizionamento di arti e tronco

La maschera di segmentazione facoltativa rappresenta la probabilità che ogni pixel appartenga a una persona rilevata. L'immagine seguente è una maschera di segmentazione dell'output della task:

Maschera di segmentazione dell'immagine precedente che delinea la forma della donna

Il codice di esempio di Pose Landmarker mostra come visualizzare i risultati di Pose Landmarker.