Options de classification des postures

L'API ML Kit Pose Detection permet d'obtenir des interprétations pertinentes d'une pose en vérifiant les positions relatives des différentes parties du corps. Cette page en présente quelques-uns.

Classification des postures et comptage des répétitions avec l'algorithme k-NN

Le suivi de l'activité physique est l'une des applications les plus courantes de la détection des postures. Créer un classificateur de postures qui reconnaît des postures et des nombres de postures spécifiques les répétitions peut être un exploit difficile pour les développeurs.

Dans cette section, nous décrivons comment nous avons créé une pose personnalisée. classificateur à l'aide de MediaPipe Colab dans notre exemple d'application ML Kit.

Si vous ne connaissez pas Google Colaboratory, veuillez consulter le guide d'introduction.

Pour reconnaître les poses, nous utilisons l'algorithme des k plus proches voisins (k-NN), car il est simple et facile à utiliser. L'algorithme détermine la classe de l'objet en fonction les échantillons les plus proches de l'ensemble d'entraînement.

Pour créer et entraîner le lecteur :

1. Collecter des échantillons d'images

Nous avons collecté des exemples d'images des exercices cibles à partir de diverses sources. Nous avons choisi quelques centaines d'images pour chaque exercice, comme les positions "haut" et "bas" pour les pompes. Il est important de collecter des échantillons couvrant plusieurs caméras les angles, les conditions de l'environnement, les formes du corps et les variations d'exercices.

Figure 1 Positions de pompes à la hausse et à la baisse

2. Exécuter la détection des postures sur les exemples d'images

Cela produit un ensemble de repères de pose à utiliser pour l'entraînement. La détection de la pose elle-même ne nous intéresse pas, car nous allons entraîner notre propre modèle à l'étape suivante.

L'algorithme k-NN que nous avons choisi pour la classification des poses personnalisées nécessite une représentation de vecteur de caractéristiques pour chaque exemple et une métrique pour calculer la distance entre deux vecteurs afin de trouver la cible la plus proche de l'exemple de pose. Cela signifie que nous devons convertir les points de repère de pose que nous venons d'obtenir.

Pour convertir les repères de la pose en vecteur de caractéristiques, nous utilisons les distances par paires entre des listes prédéfinies de joints de la pose, telles que la distance entre le poignet et l'épaule, la cheville et la hanche, et les poignets gauche et droit. Puisque l'échelle des images peut varier, nous avons normalisé les postures pour qu'elles aient la même taille de torse et le même torse vertical avant de convertir les points de repère.

3. Entraîner le modèle et compter les répétitions

Nous avons utilisé MediaPipe Colab pour accéder au code du classificateur. entraîner le modèle.

Pour compter les répétitions, nous avons utilisé un autre algorithme Colab pour surveiller le seuil de probabilité d'une position de pose cible. Exemple :

  • Lorsque la probabilité de l'« arrêt » la classe "pose" dépasse un seuil donné pour la première fois, l'algorithme indique que l'état "en panne" la classe de pose.
  • Lorsque la probabilité passe sous le seuil, l'algorithme indique que la classe de position "bas" a été quittée et augmente le compteur.
Figure 2. Exemple de comptage des répétitions

4. Intégrer l'application de démarrage rapide ML Kit

Le Colab ci-dessus génère un fichier CSV dans lequel vous pouvez remplir tous vos paramètres échantillons. Dans cette section, vous apprendrez à intégrer votre fichier CSV à l'API Application de démarrage rapide de ML Kit pour Android permettant d'afficher la classification personnalisée des postures en temps réel.

Essayez la classification de postures à l'aide d'exemples regroupés dans l'application de démarrage rapide

  • Obtenez le projet de démarrage rapide de ML Kit pour Android. depuis GitHub pour vous assurer qu'il se crée et fonctionne correctement.
  • Accédez à LivePreviewActivity et activez la détection des postures Run classification dans les paramètres . Vous devriez maintenant pouvoir classer les pompes et les squats.

Ajouter votre propre fichier CSV

  • Ajoutez votre fichier CSV au dossier d'éléments de l'application.
  • Dans PoseClassifierProcessor, modifiez les variables POSE_SAMPLES_FILE et POSE_CLASSES pour qu'elles correspondent à votre fichier CSV et à vos exemples de poses.
  • Créez et exécutez l'application.

Notez que la classification peut ne pas fonctionner correctement si le nombre d'échantillons est insuffisant. En règle générale, vous avez besoin d'environ 100 échantillons par classe de pose.

Pour en savoir plus et essayer par vous-même, consultez MediaPipe Colab et le guide de classification MediaPipe.

Reconnaître des gestes simples en calculant la distance d'un point de repère

Lorsque deux points de repère ou plus sont proches l'un de l'autre, ils peuvent être utilisés pour reconnaître les gestes. Par exemple, lorsque le repère d'un ou de plusieurs doigts d'une main est proche du repère du nez, vous pouvez en déduire que l'utilisateur se touche probablement le visage.

Figure 3 : Interpréter une pose

Reconnaître une posture de yoga à l'aide de la méthode heuristique de l'angle

Vous pouvez identifier une posture de yoga en calculant les angles de différentes articulations. Pour exemple, la figure 2 ci-dessous montre la posture de yoga du Guerrier II. Les angles approximatifs qui identifient cette posture sont écrits dans:

Figure 4 : Diviser une pose en différents angles

Cette pose peut être décrite comme la combinaison approximative des angles des parties du corps suivants :

  • Angle de 90 degrés aux deux épaules
  • 180 degrés aux deux coudes
  • Angle de 90 degrés au niveau de la jambe avant et de la taille
  • Angle de 180 degrés au genou arrière
  • Angle de 135 degrés au niveau de la taille

Vous pouvez utiliser les repères de la pose pour calculer ces angles. Par exemple, l'angle de la jambe avant droite et de la taille correspond à l'angle entre la ligne de l'épaule droite à la hanche droite et la ligne de la hanche droite au genou droit.

Une fois que vous avez calculé tous les angles nécessaires pour identifier la pose, vous pouvez vérifier pour voir s'il y a une correspondance, auquel cas vous avez reconnu la pose.

L'extrait de code ci-dessous montre comment utiliser les coordonnées X et Y pour calculer l'angle entre deux parties du corps. Cette approche de la classification présente certaines limites. Si vous ne cochez que X et Y, les angles calculés varient en fonction de l'angle entre le sujet et l'appareil photo. Vous obtiendrez les meilleurs résultats avec une image frontale, droite et de face. Vous pouvez également essayez d'étendre cet algorithme en utilisant Coordonnée Z et voyez s'il est plus performant pour votre cas d'utilisation.

Calculer les angles des repères sur Android

La méthode suivante calcule l'angle entre trois repères. Il garantit que l'angle renvoyé est compris entre 0 et 180 degrés.

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

Voici comment calculer l'angle de la hanche droite:

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

Calculer des angles de points de repère sur iOS

La méthode suivante calcule l'angle entre points de repère. Il garantit que l'angle renvoyé est compris entre 0 et 180 degrés.

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

Voici comment calculer l'angle au niveau de la hanche droite :

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