Guida al rilevamento dei punti di riferimento della mano per iOS

L'attività Riferimento mano di MediaPipe ti consente di rilevare i punti di riferimento delle mani in un'immagine. Queste istruzioni ti mostrano come utilizzare il punto di riferimento della mano con le app per iOS. L'esempio di codice descritto in queste istruzioni è disponibile su GitHub.

Per ulteriori informazioni sulle funzionalità, sui modelli e sulle opzioni di configurazione di questa attività, consulta la Panoramica.

Esempio di codice

Il codice di esempio Attività MediaPipe è un'implementazione di base di un'app Punto di riferimento manuale per iOS. L'esempio utilizza la fotocamera di un dispositivo iOS fisico per rilevare i punti di riferimento della mano in uno stream video continuo. L'app può anche rilevare i punti di riferimento delle mani in immagini e video dalla 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 del punto di riferimento manuale è ospitato su GitHub.

Scarica il codice

Le seguenti istruzioni 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 un pagamento sparse, in modo da avere solo i file dell'app di esempio di Fattore di riferimento manuale:

    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/hand_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 istruzioni, consulta la Guida alla configurazione per iOS.

Componenti chiave

I seguenti file contengono il codice cruciale per l'applicazione di esempio di Punto di riferimento manuale:

  • HandLandmarkerService.swift: inizializza l'indicatore di riferimento mano, gestisce la selezione del modello ed esegue l'inferenza sui dati di input.
  • CameraViewController.swift: implementa l'UI per la modalità di immissione del feed della videocamera in diretta e visualizza i risultati.
  • MediaLibraryViewController.swift: implementa l'interfaccia utente per la modalità di input di immagini fisse e video e visualizza i risultati.

Configurazione

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

Dipendenze

Il punto di riferimento manuale 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 la lingua.

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 la sezione Utilizzare CocoaPods.

Aggiungi il pod MediaPipeTasksVision in Podfile utilizzando il seguente codice:

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

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

Modello

L'attività Punto di riferimento mano di MediaPipe richiede un modello addestrato compatibile con questa attività. Per ulteriori informazioni sui modelli addestrati disponibili per il punto di riferimento manuale, consulta la sezione Modelli della panoramica delle attività.

Seleziona e scarica un modello, quindi aggiungilo alla directory del progetto utilizzando Xcode. Per istruzioni su come aggiungere file al progetto Xcode, consulta Gestione di 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.

Creare l'attività

Puoi creare l'attività Punto di riferimento mano chiamando uno dei suoi inizializzatori. L'inizializzazione HandLandmarker(options:) accetta valori per le opzioni di configurazione.

Se non hai bisogno di un Punto di riferimento manuale inizializzato con opzioni di configurazione personalizzate, puoi utilizzare l'inizializzazione HandLandmarker(modelPath:) per creare un Punto di riferimento manuale con le opzioni predefinite. Per ulteriori informazioni sulle opzioni di configurazione, consulta Panoramica della configurazione.

L'attività Mano del punto di riferimento supporta 3 tipi di dati di input: immagini fisse, file video e stream video in diretta. Per impostazione predefinita, HandLandmarker(modelPath:) inizializza un'attività per le immagini statiche. Se vuoi che l'attività venga inizializzata allo scopo di elaborare file video o stream video in diretta, usa HandLandmarker(options:) per specificare la modalità di esecuzione del video o del live streaming. La modalità live streaming richiede anche l'opzione di configurazione handLandmarkerLiveStreamDelegate aggiuntiva, che consente all'Hand Referenceer di fornire al delegato in modo asincrono i risultati dell'indicatore di riferimento.

Scegli la scheda corrispondente alla modalità di corsa per vedere come creare l'attività ed eseguire l'inferenza.

Swift

Immagine

import MediaPipeTasksVision

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

let options = HandLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .image
options.minHandDetectionConfidence = minHandDetectionConfidence
options.minHandPresenceConfidence = minHandPresenceConfidence
options.minTrackingConfidence = minHandTrackingConfidence
options.numHands = numHands

let handLandmarker = try HandLandmarker(options: options)
    

Video

import MediaPipeTasksVision

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

let options = HandLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.minHandDetectionConfidence = minHandDetectionConfidence
options.minHandPresenceConfidence = minHandPresenceConfidence
options.minTrackingConfidence = minHandTrackingConfidence
options.numHands = numHands

let handLandmarker = try HandLandmarker(options: options)
    

Live streaming

import MediaPipeTasksVision

// Class that conforms to the `HandLandmarkerLiveStreamDelegate` protocol and
// implements the method that the hand landmarker calls once it finishes
// performing landmarks detection in each input frame.
class HandLandmarkerResultProcessor: NSObject, HandLandmarkerLiveStreamDelegate {

  func handLandmarker(
    _ handLandmarker: HandLandmarker,
    didFinishDetection result: HandLandmarkerResult?,
    timestampInMilliseconds: Int,
    error: Error?) {

    // Process the hand landmarker result or errors here.

  }
}

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

let options = HandLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.minHandDetectionConfidence = minHandDetectionConfidence
options.minHandPresenceConfidence = minHandPresenceConfidence
options.minTrackingConfidence = minHandTrackingConfidence
options.numHands = numHands

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

let handLandmarker = try HandLandmarker(options: options)
    

Objective-C

Immagine

@import MediaPipeTasksVision;

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

MPPHandLandmarkerOptions *options = [[MPPHandLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.minHandDetectionConfidence = minHandDetectionConfidence;
options.minHandPresenceConfidence = minHandPresenceConfidence;
options.minTrackingConfidence = minHandTrackingConfidence;
options.numHands = numHands;

MPPHandLandmarker *handLandmarker =
  [[MPPHandLandmarker alloc] initWithOptions:options error:nil];
    

Video

@import MediaPipeTasksVision;

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

MPPHandLandmarkerOptions *options = [[MPPHandLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.minHandDetectionConfidence = minHandDetectionConfidence;
options.minHandPresenceConfidence = minHandPresenceConfidence;
options.minTrackingConfidence = minHandTrackingConfidence;
options.numHands = numHands;

MPPHandLandmarker *handLandmarker =
  [[MPPHandLandmarker alloc] initWithOptions:options error:nil];
    

Live streaming

@import MediaPipeTasksVision;

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

@interface APPHandLandmarkerResultProcessor : NSObject 

@end

@implementation APPHandLandmarkerResultProcessor

-   (void)handLandmarker:(MPPHandLandmarker *)handLandmarker
    didFinishDetectionWithResult:(MPPHandLandmarkerResult *)handLandmarkerResult
         timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                           error:(NSError *)error {

    // Process the hand landmarker result or errors here.

}

@end

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

MPPHandLandmarkerOptions *options = [[MPPHandLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.minHandDetectionConfidence = minHandDetectionConfidence;
options.minHandPresenceConfidence = minHandPresenceConfidence;
options.minTrackingConfidence = minHandTrackingConfidence;
options.numHands = numHands;

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

MPPHandLandmarker *handLandmarker =
  [[MPPHandLandmarker alloc] initWithOptions:options error:nil];
    

Opzioni di configurazione

Questa attività prevede 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 per l'attività. Esistono tre modalità:

IMAGE: la modalità per gli input 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à, resultListener deve essere chiamato per configurare un listener per ricevere i risultati in modo asincrono. In questa modalità, handLandmarkerLiveStreamDelegate deve essere impostato su un'istanza di una classe che implementa l'elemento HandLandmarkerLiveStreamDelegate per ricevere i risultati del rilevamento dei punti di riferimento della mano in modo asincrono.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} RunningMode.image
numHands Il numero massimo di mani rilevate dal rilevatore dei punti di riferimento della mano. Any integer > 0 1
minHandDetectionConfidence Il punteggio di affidabilità minimo affinché il rilevamento della mano venga considerato efficace nel modello di rilevamento del palmo. 0.0 - 1.0 0.5
minHandPresenceConfidence Il punteggio di affidabilità minimo per il punteggio della presenza della mano nel modello di rilevamento dei punti di riferimento della mano. In modalità Video e Live streaming, se il punteggio di confidenza della presenza della mano del modello del punto di riferimento della mano è inferiore a questa soglia, il punto di riferimento della mano attiva il modello di rilevamento del palmo. Altrimenti, un algoritmo di tracciamento delle mani leggero determina la posizione delle mani per i successivi rilevamenti dei punti di riferimento. 0.0 - 1.0 0.5
minTrackingConfidence Il punteggio di affidabilità minimo affinché la registrazione della mano venga considerata riuscita. Si tratta della soglia IoU del riquadro di delimitazione tra le mani nel frame corrente e nell'ultimo frame. In modalità Video e in modalità flusso del punto di riferimento mano, se il tracciamento non va a buon fine, il punto di riferimento mano attiva il rilevamento della mano. In caso contrario, il rilevamento della mano non viene eseguito. 0.0 - 1.0 0.5
result_listener Imposta il listener dei risultati per ricevere i risultati del rilevamento in modo asincrono quando l'indicatore di riferimento della mano è in modalità live streaming. Applicabile solo quando la modalità di esecuzione è impostata su LIVE_STREAM N/A N/A

Quando la modalità di corsa è impostata su live streaming, il punto di riferimento della mano richiede l'opzione di configurazione handLandmarkerLiveStreamDelegate aggiuntiva, che consente al punto di riferimento della mano di fornire risultati di rilevamento dei punti di riferimento della mano in modo asincrono. Il delegato deve implementare il metodo handLandmarker(_:didFinishDetection:timestampInMilliseconds:error:), che il Punto di riferimento della mano chiama dopo aver elaborato i risultati del rilevamento dei punti di riferimento della mano per ogni frame.

Nome opzione Descrizione Intervallo di valori Valore predefinito
handLandmarkerLiveStreamDelegate Consente al punto di riferimento della mano di ricevere i risultati del rilevamento dei punti di riferimento della mano in modo asincrono in modalità live streaming. La classe la cui istanza è impostata su questa proprietà deve implementare il metodo handLandmarker(_:didFinishDetection:timestampInMilliseconds:error:). Non applicabile Non impostata

Preparazione dei dati

Devi convertire l'immagine o il frame di input in un oggetto MPImage prima di passarli al punto di riferimento manuale. MPImage supporta diversi tipi di formati delle immagini per iOS e può utilizzarli in qualsiasi modalità di esecuzione per l'inferenza. Per ulteriori informazioni su MPImage, consulta la pagina relativa all'API MPImage

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

UIImage

Il formato UIImage è adatto per le seguenti modalità di corsa:

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

  • Video: utilizza AVAssetImageGenerator per estrarre fotogrammi video nel formato CGImage, quindi convertili in UIImage immagini.

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 elemento MPImage con l'orientamento predefinito UIImage.Orientation.Up. Puoi inizializzare un elemento MPImage con uno qualsiasi dei valori supportati per UIImage.Orientation. Il punto di riferimento della mano non supporta gli orientamenti speculari come .upMirrored, .downMirrored, .leftMirrored, .rightMirrored.

Per ulteriori informazioni su UIImage, consulta la documentazione per gli sviluppatori di Apple nell'interfaccia UI.

CVPixelBuffer

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

Il formato CVPixelBuffer è adatto per le seguenti modalità di corsa:

  • Immagini: le app che generano immagini CVPixelBuffer dopo alcune elaborazioni utilizzando il framework CoreImage di iOS possono essere inviate al punto di riferimento manuale in modalità di esecuzione delle immagini.

  • Video: i fotogrammi video possono essere convertiti nel formato CVPixelBuffer per l'elaborazione e poi inviati al Punto di riferimento manuale in modalità video.

  • live streaming: le app che utilizzano una fotocamera iOS per generare frame possono essere convertite nel formato CVPixelBuffer per l'elaborazione prima di essere inviate a Hand Referenceer 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 gli sviluppatori di Apple CVPixelBuffer.

CMSampleBuffer

Il formato CMSampleBuffer archivia esempi di contenuti multimediali di un tipo di media uniforme ed è adatto per la modalità di esecuzione live streaming. I fotogrammi in tempo reale delle fotocamere iOS vengono inviati in modo asincrono nel formato CMSampleBuffer da 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];
    

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

Esegui l'attività

Per eseguire il punto di riferimento manuale, utilizza il metodo detect() specifico per la modalità di esecuzione assegnata:

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

Swift

Immagine

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

Video

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

Live streaming

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

Objective-C

Immagine

MPPHandLandmarkerResult *result =
  [handLandmarker detectInImage:image error:nil];
    

Video

MPPHandLandmarkerResult *result =
  [handLandmarker detectInVideoFrame:image
             timestampInMilliseconds:timestamp
                               error:nil];
    

Live streaming

BOOL success =
  [handLandmarker detectAsyncInImage:image
             timestampInMilliseconds:timestamp
                               error:nil];
    

L'esempio di codice del punto di riferimento manuale mostra in maggiore dettaglio le implementazioni di ciascuna di queste modalità. Il codice di esempio consente all'utente di passare da una modalità di elaborazione all'altra, il che potrebbe non essere necessario per il tuo caso d'uso.

Tieni presente quanto riportato di seguito:

  • Quando esegui in modalità video o live streaming, devi anche fornire il timestamp del frame di input all'attività Fattore di riferimento manuale.

  • Quando viene eseguita in modalità immagine o video, l'attività di riferimento mano blocca il thread corrente fino a quando non completa l'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 per iOS Dispatch o NSOperation.

  • Quando è in esecuzione in modalità live streaming, l'attività Mano del punto di riferimento viene restituita immediatamente e non blocca il thread corrente. Richiama il metodo handLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) con il risultato dell'indicatore di riferimento della mano dopo l'elaborazione di ogni frame di input. L'Hand Referenceer richiama questo metodo in modo asincrono su una coda di invio seriale dedicata. Per visualizzare i risultati nell'interfaccia utente, inviali alla coda principale dopo l'elaborazione dei risultati. Se la funzione detectAsync viene richiamata quando l'attività Indicatore del punto di riferimento mano è impegnata a elaborare un altro frame, l'indicatore di riferimento mano ignora il nuovo frame di input.

Gestire e visualizzare i risultati

Dopo l'esecuzione dell'inferenza, l'attività Misuratore della mano restituisce un HandLandmarkerResult che contiene i punti di riferimento della mano nelle coordinate dell'immagine, i punti di riferimento della mano nelle coordinate del mondo e la mano(mano sinistra/destra) delle mani rilevate.

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

L'output HandLandmarkerResult contiene tre componenti. Ogni componente è un array in cui ogni elemento contiene i risultati seguenti per una singola mano rilevata:

  • Mano dominante

    La mano indica se la mano viene rilevata sia destra che sinistra.

  • Punti di riferimento

    Ci sono 21 punti di riferimento della mano, ciascuno composto dalle coordinate x, y e z. Le coordinate x e y sono normalizzate su [0,0, 1,0] rispettivamente in base alla larghezza e all'altezza dell'immagine. La coordinata z rappresenta la profondità del punto di riferimento, dove la profondità al polso è l'origine. Più basso è il valore, più il punto di riferimento è vicino alla fotocamera. La grandezza di z utilizza approssimativamente la stessa scala di x.

  • Punti di riferimento mondiali

    I punti di riferimento a 21 mani sono presentati anche nelle coordinate mondiali. Ogni punto di riferimento è composto da x, y e z e rappresenta le coordinate 3D del mondo reale in metri con l'origine in corrispondenza del centro geometrico della mano.

HandLandmarkerResult:
  Handedness:
    Categories #0:
      index        : 0
      score        : 0.98396
      categoryName : Left
  Landmarks:
    Landmark #0:
      x            : 0.638852
      y            : 0.671197
      z            : -3.41E-7
    Landmark #1:
      x            : 0.634599
      y            : 0.536441
      z            : -0.06984
    ... (21 landmarks for a hand)
  WorldLandmarks:
    Landmark #0:
      x            : 0.067485
      y            : 0.031084
      z            : 0.055223
    Landmark #1:
      x            : 0.063209
      y            : -0.00382
      z            : 0.020920
    ... (21 world landmarks for a hand)

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