Opciones de clasificación de poses

Con la API de detección de poses del Kit de AA, puedes obtener interpretaciones significativas de una postura si verificas las posiciones relativas de varias partes del cuerpo. En esta página, se muestran algunos ejemplos.

Clasificación y recuento de repeticiones de posturas con el algoritmo k-NN

Una de las aplicaciones más comunes de la detección de poses es el seguimiento de la actividad física. Crear un clasificador de posturas que reconozca poses específicas de ejercicios y cuenta repeticiones puede ser una tarea difícil para los desarrolladores.

En esta sección, describimos cómo compilamos un clasificador de posturas personalizado con MediaPipe Colab y mostramos un clasificador en funcionamiento en nuestra app de ejemplo del Kit de AA.

Si no estás familiarizado con Google Colaboratory, consulta la guía de introducción.

Para reconocer las posturas, usamos el algoritmo k-vecino más cercano (k-NN), ya que es simple y fácil de comenzar. El algoritmo determina la clase del objeto según las muestras más cercanas en el conjunto de entrenamiento.

Sigue estos pasos para compilar y entrenar el reconocedor:

1. Recopila muestras de imágenes

Recolectamos muestras de imágenes de los ejercicios objetivo de varias fuentes. Elegimos unos cientos de imágenes para cada ejercicio, como las posiciones “hacia arriba” y “abajo” para las flexiones. Es importante recopilar muestras que abarquen diferentes ángulos de cámara, condiciones del entorno, formas del cuerpo y variaciones de los ejercicios.

Figura 1: Posiciones de postura de flexiones hacia arriba y abajo

2. Ejecuta la detección de poses en las imágenes de muestra

Esto produce un conjunto de puntos de referencia de postura que se usarán para el entrenamiento. No nos interesa la detección de poses en sí, ya que entrenaremos nuestro modelo en el siguiente paso.

El algoritmo k-NN que elegimos para la clasificación personalizada de posturas requiere una representación de vector de atributos para cada muestra y una métrica con el fin de calcular la distancia entre dos vectores y encontrar el objetivo más cercano a la muestra de postura. Esto significa que debemos convertir los puntos de referencia de postura que acabamos de obtener.

Para convertir los puntos de referencia de postura en un vector de atributos, usamos las distancias en pares entre listas predefinidas de articulaciones de postura, como la distancia entre muñeca y hombro, tobillo y cadera, y muñecas izquierda y derecha. Dado que la escala de las imágenes puede variar, normalizamos las poses para que tengan el mismo tamaño y la misma orientación vertical del torso antes de convertir los puntos de referencia.

3. Entrenar el modelo y contar repeticiones

Usamos MediaPipe Colab para acceder al código del clasificador y entrenar el modelo.

Para contar las repeticiones, usamos otro algoritmo de Colab a fin de supervisar el umbral de probabilidad de una posición de pose objetivo. Por ejemplo:

  • Cuando la probabilidad de la clase de pose "abajo" pasa un umbral por primera vez, el algoritmo marca que se ingresó la clase de pose "abajo".
  • Cuando la probabilidad cae por debajo del umbral, el algoritmo marca que se salió de la clase de pose "hacia abajo" y aumenta el contador.
Figura 2: Ejemplo de recuento de repeticiones

4. Realiza la integración en la app de inicio rápido del Kit de AA

El Colab anterior genera un archivo CSV que puedes propagar con todas tus muestras de poses. En esta sección, aprenderás a integrar tu archivo CSV con la app de inicio rápido de Android para ML Kit a fin de ver la clasificación de posturas personalizadas en tiempo real.

Prueba la clasificación de poses con muestras agrupadas en la app de inicio rápido

Agrega tu propio CSV

  • Agrega el archivo CSV a la carpeta de recursos de la app.
  • En PoseClassifierProcessor, actualiza las variables POSE_SAMPLES_FILE y POSE_CLASSES para que coincidan con tu archivo CSV y muestras de poses.
  • Compila y ejecuta la app.

Ten en cuenta que es posible que la clasificación no funcione bien si no hay suficientes muestras. Por lo general, se necesitan alrededor de 100 muestras por clase de pose.

Para obtener más información y probarlo por tu cuenta, consulta MediaPipe Colab y la guía de clasificación de MediaPipe.

Reconocer gestos simples a través del cálculo de la distancia de los puntos de referencia

Cuando dos o más puntos de referencia están cerca uno del otro, se pueden usar para reconocer gestos. Por ejemplo, cuando el punto de referencia de uno o más dedos de una mano está cerca del punto de referencia de la nariz, puedes inferir que es más probable que el usuario toque su rostro.

Figura 3: Cómo interpretar una pose

Reconocer una postura de yoga con heurística de ángulos

Puedes identificar una postura de yoga calculando los ángulos de varias articulaciones. Por ejemplo, en la Figura 2 que aparece a continuación, se muestra la pose de yoga del guerrero II. Los ángulos aproximados que identifican esta pose se escriben de la siguiente manera:

Figura 4: Dividir una postura en ángulos

Esta postura se puede describir como la siguiente combinación de ángulos aproximados de las partes del cuerpo:

  • Ángulo de 90 grados en ambos hombros
  • 180 grados en ambos codos
  • Ángulo de 90 grados en la parte delantera de la pierna y la cintura
  • Ángulo de 180 grados en la rodilla posterior
  • Ángulo de 135 grados en la cintura

Puedes usar los puntos de referencia de las posturas para calcular estos ángulos. Por ejemplo, el ángulo en la pierna delantera y la cintura derecha es el ángulo entre la línea desde el hombro derecho hasta la cadera derecha, y la línea desde la cadera derecha hasta la rodilla derecha.

Una vez que calcules todos los ángulos necesarios para identificar la pose, puedes comprobar si hay una coincidencia, en cuyo caso reconociste la pose.

En el siguiente fragmento de código, se muestra cómo usar las coordenadas X e Y para calcular el ángulo entre dos partes del cuerpo. Este enfoque para la clasificación tiene algunas limitaciones. Si solo marcas X e Y, los ángulos calculados varían según el ángulo entre el sujeto y la cámara. Obtendrás los mejores resultados con una imagen nivelada, directa y de frente. También puedes intentar extender este algoritmo con la coordenada Z y ver si tiene un mejor rendimiento para tu caso de uso.

Calcula ángulos de referencia en Android

El siguiente método calcula el ángulo entre tres puntos de referencia cualquiera. Garantiza que el ángulo que se muestra esté entre 0 y 180 grados.

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

A continuación, te mostramos cómo calcular el ángulo en la cadera derecha:

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

Calcula ángulos de referencia en iOS

El siguiente método calcula el ángulo entre tres puntos de referencia cualquiera. Garantiza que el ángulo que se muestra esté entre 0 y 180 grados.

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

A continuación, te mostramos cómo calcular el ángulo en la cadera derecha:

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