Opções de classificação de poses

Com a API Pose Detection do ML Kit, é possível extrair interpretações significativas de uma pose verificando as posições relativas de várias partes do corpo. Esta página demonstra alguns exemplos.

Classificação de poses e contagem de repetições com o algoritmo k-NN

Um dos aplicativos mais comuns de detecção de pose é o rastreamento de condicionamento físico. Criar um classificador de poses que reconheça poses de condicionamento físico específicas e conte repetições pode ser um desafio para os desenvolvedores.

Nesta seção, vamos descrever como criamos uma pose personalizada usando o MediaPipe Colab. demonstrar um classificador em funcionamento no app de exemplo do Kit de ML.

Se você não conhece o Google Colaboratory, confira o guia de introdução.

Para reconhecer poses, usamos o algoritmo de vizinhos k-mais próximo (k-NN), porque ele é simples e fácil de começar. O algoritmo determina a classe do objeto com base nas amostras mais próximas no conjunto de treinamento.

Siga estas etapas para criar e treinar o reconhecedor:

1. Coletar amostras de imagens

Coletamos amostras de imagens dos exercícios direcionados de várias fontes. Qa e escolheu algumas centenas de imagens para cada exercício, como “para cima” e "down" posições para flexões. É importante coletar amostras que abrangem diferentes ângulos de câmera, condições ambientais, formas do corpo e variações de exercícios.

Figura 1. Posições de flexão para cima e para baixo

2. Executar a detecção de pose nas imagens de amostra

Isso produz um conjunto de pontos de referência de postura a serem usados no treinamento. Não estamos interessados na detecção de pose em si, já que vamos treinar nosso próprio modelo na próxima etapa.

O algoritmo k-NN escolhido para a classificação de poses personalizadas requer uma representação de vetor de recursos para cada amostra e uma métrica para calcular a distância entre dois vetores para encontrar o alvo mais próximo da amostra de pose. Isso significa que precisamos converter os pontos de referência da pose que acabamos de receber.

Para converter os pontos de referência da pose em um vetor de características, usamos as distâncias de pares entre listas predefinidas de articulações de pose, como a distância entre pulso e ombro, tornozelo e quadril e pulsos esquerdo e direito. Como a escala das imagens pode variar, normalizamos as poses para que tenham o mesmo tamanho de tronco e tronco vertical orientação antes de converter os pontos de referência.

3. Treinar o modelo e contar repetições

Usamos o MediaPipe Colab para acessar o código do classificador e treinar o modelo.

Para contar repetições, usamos outro algoritmo do Colab para monitorar o limite de probabilidade de uma posição de pose de destino. Exemplo:

  • Quando a probabilidade da classe de pose "para baixo" ultrapassa um determinado limite pela primeira vez, o algoritmo marca que a classe de pose "para baixo" foi inserida.
  • Quando a probabilidade cai abaixo do limite, o algoritmo marca que a classe de pose "para baixo" foi encerrada e aumenta o contador.
Figura 2. exemplo de contagem de repetições

4. Integrar com o app de início rápido do Kit de ML

O Colab acima produz um arquivo CSV que pode ser preenchido com todas as posições de amostra. Nesta seção, você vai aprender a integrar seu arquivo CSV com o app de início rápido do ML Kit para Android e conferir a classificação de pose personalizada em tempo real.

Testar a classificação de pose com amostras incluídas no app de início rápido

  • Confira o projeto do app de início rápido do Kit de ML para Android no GitHub e verifique se ele é criado e executado corretamente.
  • Acesse LivePreviewActivity e ative a detecção de posições Run classification em "Configurações" página. Agora você deve ser capaz de classificar flexões e agachamentos.

Adicionar seu próprio CSV

  • Adicione o arquivo CSV à pasta de recursos do app.
  • Em PoseClassifierProcessor, atualize as variáveis POSE_SAMPLES_FILE e POSE_CLASSES para corresponder CSV e amostras de poses.
  • Compile e execute o aplicativo.

A classificação pode não funcionar bem se não houver amostras suficientes. Geralmente, você precisa de cerca de 100 amostras por classe de pose.

Para saber mais e testar isso, consulte o MediaPipe Colab e o guia de classificação do MediaPipe.

Reconhecer gestos simples calculando a distância do ponto de referência

Quando dois ou mais pontos de referência estão próximos, eles podem ser usados para e reconhecer gestos. Por exemplo, quando o marco de um ou mais dedos de uma mão está próximo ao marco do nariz, é possível inferir que o usuário provavelmente está tocando no rosto.

Figura 3. Como interpretar uma pose

Reconhecer uma postura de ioga com heurística de ângulos

Você pode identificar uma postura de ioga calculando os ângulos de várias articulações. Para exemplo, a Figura 2 abaixo mostra a postura de ioga do Guerreiro II. Os ângulos aproximados que identificam esta posição estão escritas em:

Figura 4. Dividir uma pose em ângulos

Esta posição pode ser descrita como a seguinte combinação de movimentos aproximados ângulos parciais:

  • Ângulo de 90 graus nos dois ombros
  • 180 graus nos dois cotovelos
  • Ângulo de 90 graus na perna da frente e na cintura
  • Ângulo de 180 graus na parte de trás do joelho
  • Ângulo de 135 graus na cintura

Você pode usar os pontos de referência da pose para calcular esses ângulos. Por exemplo, o ângulo na perna dianteira direita e na cintura é o ângulo entre a linha a partir da direita ombro para o quadril direito e a linha que vai do quadril direito até o joelho direito.

Depois de calcular todos os ângulos necessários para identificar a pose, você pode conferir para ver se há uma correspondência. Nesse caso, você reconheceu a pose.

O snippet de código abaixo demonstra como usar as coordenadas X e Y para calcular o ângulo entre duas partes do corpo. Essa abordagem de classificação tem algumas limitações. Ao verificar apenas X e Y, os ângulos calculados variam de acordo com o ângulo entre o objeto e a câmera. Você receberá o melhores resultados com uma imagem nivelada, direta e de frente. Você também pode tentar estender esse algoritmo usando a coordenada Z e conferir se ele tem um desempenho melhor para seu caso de uso.

Como calcular ângulos de pontos de referência no Android

O método a seguir calcula o ângulo entre três pontos de referência. Ele garante que o ângulo retornado esteja entre 0 e 180 graus.

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

Confira como calcular o ângulo no quadril direito:

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

Como calcular ângulos de pontos de referência no iOS

O método a seguir calcula o ângulo entre três pontos de referência. Ele garante que o ângulo retornado esteja entre 0 e 180 graus.

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

Veja como calcular o ângulo no quadril direito:

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