姿勢の分類オプション

ML Kit Pose Detection API を使用すると、意味のある解釈を導き出すことができます。 さまざまな部位の相対位置を確認することで、ポーズのモデルを評価します。このページ いくつか例を示します

k-NN アルゴリズムによる姿勢分類と繰り返しカウント

姿勢検出の最も一般的な用途の 1 つは、フィットネス トラッキングです。 特定のフィットネスのポーズとカウントを認識するポーズ分類器の作成 繰り返しはデベロッパーにとって厄介な作業です

このセクションでは、カスタムポーズの作成方法について説明します。 MediaPipe Colab を使用した分類器 ML Kit サンプルアプリで機能する分類器のデモを行います。

Google Colaboratory についてよく知らない場合は、 概要ガイドをご覧ください。

ポーズを認識するには、単純な k 最近傍アルゴリズム(k-NN)を使用します。 簡単に始められますオブジェクトのクラスは、アルゴリズムが 最も近いサンプルを取得します

認識ツールを作成してトレーニングする手順は次のとおりです。

1. 画像サンプルを収集する

さまざまなソースから対象のエクササイズの画像サンプルを収集しました。水 トレーニング用の画像を数百枚ほど「down」と入力します。位置 腕立て伏せに使用していますさまざまなカメラをカバーするサンプルを収集することが重要 角度、環境条件、体の形状、運動のバリエーションなどがあります。

図 1. 上下腕立て伏せのポーズ

2. サンプル画像に対して姿勢検出を実行する

これにより、トレーニングに使用するポーズ ランドマークのセットが生成されます。私たちは ポーズ検出機能に興味がある方もいるでしょう。このトレーニングでは、 独自のモデルを作成します。

カスタムのポーズ分類用に選択した k-NN アルゴリズムでは、 各サンプルの特徴ベクトル表現と計算する指標 2 つのベクトル間の距離を計算し、ポーズ サンプルに最も近いターゲットを見つけます。 つまり、先ほど取得したポーズ ランドマークを変換する必要があります。

ポーズ ランドマークを特徴ベクトルに変換するには、特徴ベクトルのペアごとの距離を使用します。 リスト間の距離(手首と指の間の距離など)を 肩、足首、腰、左手首と右手首です。画像のスケールは、 変化があるため、胴体のサイズと胴体の垂直方向が同じになるようにポーズを正規化しました。 画像の向きを確認します

3. モデルをトレーニングして繰り返しをカウントする

MediaPipe Colab を使用して分類器のコードにアクセスし、 モデルをトレーニングします。

繰り返し回数をカウントするために、別の Colab アルゴリズムを使用して、 ターゲットポーズ位置のしきい値です。例:

  • 「ダウン」の確率がポーズクラスは、トレーニング中に与えられた 最初の段階では、アルゴリズムはポーズクラスが入力されました。
  • 確率がしきい値を下回ると、アルゴリズムは 「下」ポーズクラスが終了し、カウンタが増加します。
図 2. 繰り返しカウントの例

4. ML Kit クイックスタート アプリと統合する

上記の Colab では、すべてのポーズを入力できる CSV ファイルが生成されます 提供しますこのセクションでは、CSV ファイルを カスタムの姿勢分類をリアルタイムで表示する ML Kit Android クイックスタート アプリ

クイックスタート アプリにバンドルされたサンプルでポーズ分類を試す

  • ML Kit Android クイックスタート アプリ プロジェクトを入手する ビルドして動作することを確認します。
  • LivePreviewActivity に移動し、姿勢検出 Run classification を有効にしてください [設定]でできます。これで、腕立て伏せとスクワットを分類できるようになりました。

独自の CSV を追加

  • CSV ファイルをアプリのアセット フォルダに追加します。
  • PoseClassifierProcessor で、 POSE_SAMPLES_FILE 変数と POSE_CLASSES 変数を、 CSV ファイルとポーズのサンプル。
  • アプリをビルドして実行します。

サンプルが十分でない場合、分類がうまく機能しない場合があります。 通常、ポーズクラスごとに約 100 個のサンプルが必要です。

詳細を確認して試すには、MediaPipe Colab をご覧ください。 および MediaPipe 分類ガイドをご覧ください。

ランドマーク距離を計算して単純なジェスチャーを認識する

2 つ以上のランドマークが互いに近接している場合、 ジェスチャーを認識できます。たとえば、画面上の 1 本以上の指のランドマークが 手が鼻のランドマークに近い場合は、ユーザーが最も 顔に触れている可能性が高まります

図 3. ポーズを解釈する

アングル ヒューリスティックでヨガのポーズを認識する

さまざまな関節の角度を計算することで、ヨガのポーズを特定できます。対象 たとえば、以下の図 2 は、「Warrior II」ヨガのポーズを示しています。おおよその角度 ポーズを表す表は、次のように書かれます。

図 4. ポーズを複数の角度に分割する

このポーズは、次のようなおおよその体の組み合わせとして表現できます。 部分角:

  • 両肩を 90 度に曲げる
  • 左右両肘 180 度
  • 前脚とウエストを 90 度に開けた状態
  • 後ろ膝を 180 度開けた状態
  • ウエストの角度 135 度

ポーズ ランドマークを使用して、これらの角度を計算できます。たとえば、 右前足とウエストの角度は、右からの線間の角度 右腰から右膝までの線を描きます。

ポーズの特定に必要な角度をすべて計算したら、 一致するものがあるかどうかを確認します。一致する場合はポーズを認識します。

以下のコード スニペットは、X 座標と Y 座標を使用して、 2 つの部位の間の角度を計算します。この分類アプローチ いくつかの制限があります。X と Y だけをチェックすると、計算される角度が変わります。 被写体とカメラの角度に応じて決まります。こちらの 水平で正面から見ると、最善の結果が得られます。また、 このアルゴリズムを拡張するために、 Z 座標 ユースケースに適したパフォーマンスが 得られるか試してみましょう

Android でのランドマーク角度の計算

次のメソッドでは、任意の 3 つの線間の角度が 使用できます。これにより、返される角度は、 0 度と 180 度です。

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

右臀部の角度を計算する方法は次のとおりです。

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

iOS でのランドマーク角度の計算

次のメソッドでは、任意の 3 つの線間の角度が 使用できます。これにより、返される角度は、 0 度と 180 度です。

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

右臀部の角度を計算する方法は次のとおりです。

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