Opzioni di classificazione delle pose

Con l'API ML Kit Pose Detection, puoi ricavare interpretazioni significative di una posa controllando le posizioni relative di varie parti del corpo. Questa pagina mostra alcuni esempi.

Classificazione delle pose e conteggio delle ripetizioni con l'algoritmo k-NN

Una delle applicazioni più comuni del rilevamento delle posizioni è il monitoraggio dell'attività fisica. Creare un classificatore di pose che riconosca determinate posizioni di fitness e conti le ripetizioni può essere un'impresa difficile per gli sviluppatori.

In questa sezione descriviamo come abbiamo creato un classificatore di pose personalizzato utilizzando MediaPipe Colab e mostriamo un classificatore di lavoro nella nostra app di esempio ML Kit.

Se non hai dimestichezza con Google Colaboratory, consulta la guida introduttiva.

Per riconoscere le pose, utilizziamo l'algoritmo dei vicini più vicini k (k-NN) perché è semplice e con cui iniziare è facile. L'algoritmo determina la classe dell'oggetto in base ai campioni più vicini del set di addestramento.

Per creare e addestrare il riconoscimento, segui questi passaggi:

1. Raccogli esempi di immagini

Abbiamo raccolto campioni di immagini degli esercizi target da varie fonti. Abbiamo scelto qualche centinaio di immagini per ogni esercizio, ad esempio posizioni "in alto" e "in basso" per le flessioni. È importante raccogliere campioni che coprono diverse angolazioni della videocamera, condizioni ambientali, forme del corpo e variazioni di allenamento.

Figura 1. Posizioni in posa flessioni verso l'alto e verso il basso

2. Esegui il rilevamento della posa sulle immagini di esempio

In questo modo si ottiene una serie di punti di riferimento per le pose da utilizzare per l'addestramento. Non siamo interessati al rilevamento della posizione in sé, dato che addestraremo il nostro modello nel passaggio successivo.

L'algoritmo k-NN che abbiamo scelto per la classificazione personalizzata delle posizioni richiede una rappresentazione vettoriale delle caratteristiche per ogni campione e una metrica per calcolare la distanza tra due vettori al fine di trovare il target più vicino al campione di posa. Ciò significa che dobbiamo convertire i punti di riferimento per la posa appena ottenuti.

Per convertire i punti di riferimento per la posa in un vettore di caratteristiche, utilizziamo le distanze a coppie tra gli elenchi predefiniti di articolazioni per la posa, ad esempio la distanza tra polso e spalla, caviglia e fianchi e polsi sinistro e destro. Poiché la scala delle immagini può variare, abbiamo normalizzato le pose in modo che avessero le stesse dimensioni e lo stesso orientamento verticale del tronco prima di convertire i punti di riferimento.

3. Addestra il modello e conta le ripetizioni

Abbiamo utilizzato il Colab MediaPipe per accedere al codice del classificatore e addestrare il modello.

Per conteggiare le ripetizioni, abbiamo usato un altro algoritmo Colab per monitorare la soglia di probabilità di una posizione di posa target. Ad esempio:

  • Quando la probabilità della classe di posizioni "giù" supera una determinata soglia per la prima volta, l'algoritmo contrassegna che viene inserita la classe di posizioni "giù".
  • Quando la probabilità scende al di sotto della soglia, l'algoritmo contrassegna che la classe di pose "down" è stata chiusa e aumenta il contatore.
Figura 2. Esempio di conteggio delle ripetizioni

4. Integrazione con l'app di avvio rapido di ML Kit

Il Colab riportato sopra produce un file CSV che puoi completare con tutti i tuoi esempi di posa. In questa sezione imparerai a integrare il file CSV con l'app di avvio rapido per Android ML Kit, per visualizzare la classificazione delle pose personalizzata in tempo reale.

Prova la classificazione delle pose con esempi integrati nell'app Guida rapida

  • Scarica il progetto dell'app di avvio rapido per Android ML Kit da GitHub e assicurati che si crei e funzioni correttamente.
  • Vai su LivePreviewActivity e abilita il rilevamento di posizioni Run classification dalla pagina Impostazioni. Ora dovresti essere in grado di classificare le flessioni e gli squat.

Aggiungi il tuo file CSV

  • Aggiungi il file CSV alla cartella degli asset dell'app.
  • In PoseClassifierProcessor, aggiorna le variabili POSE_SAMPLES_FILE e POSE_CLASSES in modo che corrispondano al file CSV e posa degli esempi.
  • Crea ed esegui l'app.

Tieni presente che la classificazione potrebbe non funzionare correttamente se non sono disponibili campioni sufficienti. In genere, sono necessari circa 100 campioni per classe di posa.

Per scoprire di più e provare tu stesso questa funzionalità, consulta la guida alla classificazione di MediaPipe Colab e la guida alla classificazione di MediaPipe.

Riconoscimento di gesti semplici mediante il calcolo della distanza dei punti di riferimento

Quando due o più punti di riferimento sono vicini, possono essere utilizzati per riconoscere i gesti. Ad esempio, quando il punto di riferimento per una o più dita su una mano si trova vicino al punto di riferimento per il naso, puoi dedurre che l'utente è più probabile che si tocchi il volto.

Figura 3. Interpretare una posa

Riconoscimento di una posizione yoga con l'euristica angolare

Puoi identificare una posizione di yoga calcolando gli angoli delle varie articolazioni. Ad esempio, la Figura 2 di seguito mostra la posizione yoga del Guerriero II. Gli angoli approssimativi che identificano questa posa sono scritti in:

Figura 4. Suddividere la posa in più angolazioni

Questa posa può essere descritta come la seguente combinazione di angoli approssimativi delle parti del corpo:

  • Angolo di 90° su entrambe le spalle
  • 180 gradi a entrambi i gomiti
  • Angolo di 90 gradi sulla gamba anteriore e sulla vita
  • Angolo di 180 gradi sul ginocchio posteriore
  • Angolo di 135 gradi alla vita

Puoi utilizzare i punti di riferimento della posa per calcolare questi angoli. Ad esempio, l'angolo tra la gamba anteriore destra e la vita è l'angolo tra la linea dalla spalla destra all'anca destra e la linea dal fianco destro al ginocchio destro.

Dopo aver calcolato tutte le angolazioni necessarie per identificare la posa, puoi controllare se c'è una corrispondenza, nel qual caso l'hai riconosciuta.

Lo snippet di codice riportato di seguito mostra come utilizzare le coordinate X e Y per calcolare l'angolo tra due parti del corpo. Questo approccio alla classificazione presenta alcune limitazioni. Se controlli solo X e Y, gli angoli calcolati variano a seconda dell'angolo tra il soggetto e la fotocamera. Otterrai i migliori risultati con un'immagine livellata e diretta. Puoi anche provare a estendere questo algoritmo utilizzando la coordinata Z e vedere se funziona meglio per il tuo caso d'uso.

Calcolo di angolazioni importanti su Android

Il seguente metodo calcola l'angolo tra tre punti di riferimento. Assicura che l'angolo restituito sia compreso tra 0 e 180 gradi.

Kotlin

fun getAngle(firstPoint: PoseLandmark, midPoint: PoseLandmark, lastPoint: PoseLandmark): Double {
        var result = Math.toDegrees(atan2(lastPoint.getPosition().y - midPoint.getPosition().y,
                lastPoint.getPosition().x - midPoint.getPosition().x)
                - atan2(firstPoint.getPosition().y - midPoint.getPosition().y,
                firstPoint.getPosition().x - midPoint.getPosition().x))
        result = Math.abs(result) // Angle should never be negative
        if (result > 180) {
            result = 360.0 - result // Always get the acute representation of the angle
        }
        return result
    }

Java

static double getAngle(PoseLandmark firstPoint, PoseLandmark midPoint, PoseLandmark lastPoint) {
  double result =
        Math.toDegrees(
            atan2(lastPoint.getPosition().y - midPoint.getPosition().y,
                      lastPoint.getPosition().x - midPoint.getPosition().x)
                - atan2(firstPoint.getPosition().y - midPoint.getPosition().y,
                      firstPoint.getPosition().x - midPoint.getPosition().x));
  result = Math.abs(result); // Angle should never be negative
  if (result > 180) {
      result = (360.0 - result); // Always get the acute representation of the angle
  }
  return result;
}

Ecco come calcolare l'angolo sul fianco destro:

Kotlin

val rightHipAngle = getAngle(
                pose.getPoseLandmark(PoseLandmark.Type.RIGHT_SHOULDER),
                pose.getPoseLandmark(PoseLandmark.Type.RIGHT_HIP),
                pose.getPoseLandmark(PoseLandmark.Type.RIGHT_KNEE))

Java

double rightHipAngle = getAngle(
                pose.getPoseLandmark(PoseLandmark.Type.RIGHT_SHOULDER),
                pose.getPoseLandmark(PoseLandmark.Type.RIGHT_HIP),
                pose.getPoseLandmark(PoseLandmark.Type.RIGHT_KNEE));

Calcolo di angolazioni importanti su iOS

Il seguente metodo calcola l'angolo tra tre punti di riferimento. Assicura che l'angolo restituito sia compreso tra 0 e 180 gradi.

Swift

func angle(
      firstLandmark: PoseLandmark,
      midLandmark: PoseLandmark,
      lastLandmark: PoseLandmark
  ) -> CGFloat {
      let radians: CGFloat =
          atan2(lastLandmark.position.y - midLandmark.position.y,
                    lastLandmark.position.x - midLandmark.position.x) -
            atan2(firstLandmark.position.y - midLandmark.position.y,
                    firstLandmark.position.x - midLandmark.position.x)
      var degrees = radians * 180.0 / .pi
      degrees = abs(degrees) // Angle should never be negative
      if degrees > 180.0 {
          degrees = 360.0 - degrees // Always get the acute representation of the angle
      }
      return degrees
  }

Objective-C

(CGFloat)angleFromFirstLandmark:(MLKPoseLandmark *)firstLandmark
                      midLandmark:(MLKPoseLandmark *)midLandmark
                     lastLandmark:(MLKPoseLandmark *)lastLandmark {
    CGFloat radians = atan2(lastLandmark.position.y - midLandmark.position.y,
                            lastLandmark.position.x - midLandmark.position.x) -
                      atan2(firstLandmark.position.y - midLandmark.position.y,
                            firstLandmark.position.x - midLandmark.position.x);
    CGFloat degrees = radians * 180.0 / M_PI;
    degrees = fabs(degrees); // Angle should never be negative
    if (degrees > 180.0) {
        degrees = 360.0 - degrees; // Always get the acute representation of the angle
    }
    return degrees;
}

Ecco come calcolare l'angolo sul fianco destro:

Swift

let rightHipAngle = angle(
      firstLandmark: pose.landmark(ofType: .rightShoulder),
      midLandmark: pose.landmark(ofType: .rightHip),
      lastLandmark: pose.landmark(ofType: .rightKnee))

Objective-C

CGFloat rightHipAngle =
    [self angleFromFirstLandmark:[pose landmarkOfType:MLKPoseLandmarkTypeRightShoulder]
                     midLandmark:[pose landmarkOfType:MLKPoseLandmarkTypeRightHip]
                    lastLandmark:[pose landmarkOfType:MLKPoseLandmarkTypeRightKnee]];