Guida al rilevamento dei punti di riferimento della mano per Android

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 a mano con app per Android. 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 di MediaPipe Tasks è una semplice implementazione di un'app di riferimento manuale per Android. L'esempio utilizza la fotocamera di un dispositivo Android fisico per rilevare in modo continuo i punti di riferimento della mano e può anche utilizzare immagini e video della galleria del dispositivo per rilevare in modo statico i punti di riferimento delle mani.

Puoi utilizzare l'app come punto di partenza per la tua app per Android 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 per l'app di esempio di Fattore di riferimento manuale:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/hand_landmarker/android
    

Dopo aver creato una versione locale del codice di esempio, puoi importare il progetto in Android Studio ed eseguire l'app. Per le istruzioni, consulta la Guida alla configurazione per Android.

Componenti chiave

I seguenti file contengono il codice cruciale per questa applicazione di esempio di rilevamento dei punti di riferimento della mano:

  • HandLandmarkerHelper.kt: inizializza il rilevatore dei punti di riferimento della mano e gestisce il modello e la selezione dei delegati.
  • MainActivity.kt: implementa l'applicazione, inclusa la chiamata a HandLandmarkerHelper.

Configurazione

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

Dipendenze

L'attività Punto di riferimento mano utilizza la libreria com.google.mediapipe:tasks-vision. Aggiungi questa dipendenza al file build.gradle della tua app Android:

dependencies {
    implementation 'com.google.mediapipe:tasks-vision:latest.release'
}

Modello

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

Seleziona e scarica il modello e archivialo all'interno della directory del progetto:

<dev-project-root>/src/main/assets

Specifica il percorso del modello all'interno del parametro ModelAssetPath. Nel codice di esempio, il modello è definito nel file HandLandmarkerHelper.kt:

baseOptionBuilder.setModelAssetPath(MP_HAND_LANDMARKER_TASK)

Creare l'attività

L'attività Punto di riferimento mano di MediaPipe utilizza la funzione createFromOptions() per configurarla. La funzione createFromOptions() accetta i valori per le opzioni di configurazione. Per ulteriori informazioni sulle opzioni di configurazione, consulta Opzioni di configurazione.

Il punto di riferimento della mano supporta tre tipi di dati di input: immagini fisse, file video e live streaming. Devi specificare la modalità di esecuzione corrispondente al tipo di dati di input quando crei l'attività. Scegli la scheda corrispondente al tipo di dati di input per vedere come creare l'attività ed eseguire l'inferenza.

Immagine

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_HAND_LANDMARKER_TASK)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder =
    HandLandmarker.HandLandmarkerOptions.builder()
        .setBaseOptions(baseOptions)
        .setMinHandDetectionConfidence(minHandDetectionConfidence)
        .setMinTrackingConfidence(minHandTrackingConfidence)
        .setMinHandPresenceConfidence(minHandPresenceConfidence)
        .setNumHands(maxNumHands)
        .setRunningMode(RunningMode.IMAGE)

val options = optionsBuilder.build()

handLandmarker =
    HandLandmarker.createFromOptions(context, options)
    

Video

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_HAND_LANDMARKER_TASK)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder =
    HandLandmarker.HandLandmarkerOptions.builder()
        .setBaseOptions(baseOptions)
        .setMinHandDetectionConfidence(minHandDetectionConfidence)
        .setMinTrackingConfidence(minHandTrackingConfidence)
        .setMinHandPresenceConfidence(minHandPresenceConfidence)
        .setNumHands(maxNumHands)
        .setRunningMode(RunningMode.VIDEO)

val options = optionsBuilder.build()

handLandmarker =
    HandLandmarker.createFromOptions(context, options)
    

Live streaming

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_HAND_LANDMARKER_TASK)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder =
    HandLandmarker.HandLandmarkerOptions.builder()
        .setBaseOptions(baseOptions)
        .setMinHandDetectionConfidence(minHandDetectionConfidence)
        .setMinTrackingConfidence(minHandTrackingConfidence)
        .setMinHandPresenceConfidence(minHandPresenceConfidence)
        .setNumHands(maxNumHands)
        .setResultListener(this::returnLivestreamResult)
        .setErrorListener(this::returnLivestreamError)
        .setRunningMode(RunningMode.VIDEO)

val options = optionsBuilder.build()

handLandmarker =
    HandLandmarker.createFromOptions(context, options)
    

L'implementazione di codice di esempio del punto di riferimento manuale consente all'utente di passare da una modalità di elaborazione all'altra. Questo approccio rende più complicato il codice per la creazione delle attività e potrebbe non essere appropriato per il tuo caso d'uso. Puoi vedere questo codice nella funzione setupHandLandmarker() del file HandLandmarkerHelper.kt.

Opzioni di configurazione

Questa attività prevede le seguenti opzioni di configurazione per le app per Android:

Nome opzione Descrizione Intervallo di valori Valore predefinito
runningMode 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.
{IMAGE, VIDEO, LIVE_STREAM} 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
resultListener 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
errorListener Imposta un listener di errori facoltativo. N/A N/A

Preparazione dei dati

La mano Punto di riferimento funziona con immagini, file video e video in live streaming. L'attività gestisce la pre-elaborazione dell'input dei dati, tra cui il ridimensionamento, la rotazione e la normalizzazione dei valori.

Il seguente codice mostra come trasferire i dati per l'elaborazione. Questi esempi includono dettagli su come gestire i dati di immagini, file video e stream di video dal vivo.

Immagine

import com.google.mediapipe.framework.image.BitmapImageBuilder
import com.google.mediapipe.framework.image.MPImage

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(image).build()
    

Video

import com.google.mediapipe.framework.image.BitmapImageBuilder
import com.google.mediapipe.framework.image.MPImage

val argb8888Frame =
    if (frame.config == Bitmap.Config.ARGB_8888) frame
    else frame.copy(Bitmap.Config.ARGB_8888, false)

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(argb8888Frame).build()
    

Live streaming

import com.google.mediapipe.framework.image.BitmapImageBuilder
import com.google.mediapipe.framework.image.MPImage

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(rotatedBitmap).build()
    

Nel codice di esempio di Hand Punto di riferimento, la preparazione dei dati viene gestita nel file HandLandmarkerHelper.kt.

Esegui l'attività

A seconda del tipo di dati con cui lavori, utilizza il metodo HandLandmarker.detect...() specifico per quel tipo di dati. Utilizza detect() per le singole immagini, detectForVideo() per i frame nei file video e detectAsync() per gli stream video. Quando esegui rilevamenti su uno stream video, assicurati di eseguirli in un thread separato per evitare di bloccare il thread dell'interfaccia utente.

I seguenti esempi di codice mostrano semplici esempi di come eseguire Punto di riferimento manuale in queste diverse modalità dei dati:

Immagine

val result = handLandmarker?.detect(mpImage)
    

Video

val timestampMs = i * inferenceIntervalMs

handLandmarker?.detectForVideo(mpImage, timestampMs)
    ?.let { detectionResult ->
        resultList.add(detectionResult)
    }
    

Live streaming

val mpImage = BitmapImageBuilder(rotatedBitmap).build()
val frameTime = SystemClock.uptimeMillis()

handLandmarker?.detectAsync(mpImage, frameTime)
    

Tieni presente quanto riportato di seguito:

  • Quando l'esecuzione è 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à Mano del punto di riferimento blocca il thread corrente finché non completa l'elaborazione dell'immagine o del frame di input. Per evitare di bloccare l'interfaccia utente, esegui l'elaborazione in un thread in background.
  • Quando è in esecuzione in modalità live streaming, l'attività Mano del punto di riferimento non blocca il thread corrente, ma torna immediatamente. Richiama il proprio listener dei risultati con il risultato del rilevamento ogni volta che ha terminato l'elaborazione di un frame di input. Se la funzione di rilevamento viene richiamata quando l'attività Indicatore del punto di riferimento manuale è impegnata a elaborare un altro frame, l'attività ignorerà il nuovo frame di input.

Nel codice di esempio del punto di riferimento a mano, le funzioni detect, detectForVideo e detectAsync sono definite nel file HandLandmarkerHelper.kt.

Gestire e visualizzare i risultati

Il Punto di riferimento della mano genera un oggetto risultato del punto di riferimento della mano per ogni esecuzione di rilevamento. L'oggetto risultato contiene punti di riferimento della mano nelle coordinate dell'immagine, punti di riferimento della mano nelle coordinate del mondo e 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à:

Il codice di esempio del punto di riferimento manuale mostra come visualizzare i risultati restituiti dall'attività. Per ulteriori dettagli, consulta la classe OverlayView.