ML Kit Pose Detection API を使用すると、意味のある解釈を導き出すことができます。 さまざまな部位の相対位置を確認することで、ポーズのモデルを評価します。このページ いくつか例を示します
k-NN アルゴリズムによる姿勢分類と繰り返しカウント
姿勢検出の最も一般的な用途の 1 つは、フィットネス トラッキングです。 特定のフィットネスのポーズとカウントを認識するポーズ分類器の作成 繰り返しはデベロッパーにとって厄介な作業です
このセクションでは、カスタムポーズの作成方法について説明します。 MediaPipe Colab を使用した分類器 ML Kit サンプルアプリで機能する分類器のデモを行います。
Google Colaboratory についてよく知らない場合は、 概要ガイドをご覧ください。
ポーズを認識するには、単純な k 最近傍アルゴリズム(k-NN)を使用します。 簡単に始められますオブジェクトのクラスは、アルゴリズムが 最も近いサンプルを取得します
認識ツールを作成してトレーニングする手順は次のとおりです。
1. 画像サンプルを収集する
さまざまなソースから対象のエクササイズの画像サンプルを収集しました。水 トレーニング用の画像を数百枚ほど「down」と入力します。位置 腕立て伏せに使用していますさまざまなカメラをカバーするサンプルを収集することが重要 角度、環境条件、体の形状、運動のバリエーションなどがあります。
![](https://developers.google.cn/static/ml-kit/images/vision/pose-detection/terminal_pose.png?authuser=0000&hl=ja)
2. サンプル画像に対して姿勢検出を実行する
これにより、トレーニングに使用するポーズ ランドマークのセットが生成されます。私たちは ポーズ検出機能に興味がある方もいるでしょう。このトレーニングでは、 独自のモデルを作成します。
カスタムのポーズ分類用に選択した k-NN アルゴリズムでは、 各サンプルの特徴ベクトル表現と計算する指標 2 つのベクトル間の距離を計算し、ポーズ サンプルに最も近いターゲットを見つけます。 つまり、先ほど取得したポーズ ランドマークを変換する必要があります。
ポーズ ランドマークを特徴ベクトルに変換するには、特徴ベクトルのペアごとの距離を使用します。 リスト間の距離(手首と指の間の距離など)を 肩、足首、腰、左手首と右手首です。画像のスケールは、 変化があるため、胴体のサイズと胴体の垂直方向が同じになるようにポーズを正規化しました。 画像の向きを確認します
3. モデルをトレーニングして繰り返しをカウントする
MediaPipe Colab を使用して分類器のコードにアクセスし、 モデルをトレーニングします。
繰り返し回数をカウントするために、別の Colab アルゴリズムを使用して、 ターゲットポーズ位置のしきい値です。例:
- 「ダウン」の確率がポーズクラスは、トレーニング中に与えられた 最初の段階では、アルゴリズムはポーズクラスが入力されました。
- 確率がしきい値を下回ると、アルゴリズムは 「下」ポーズクラスが終了し、カウンタが増加します。
![](https://developers.google.cn/static/ml-kit/images/vision/pose-detection/pose_classification.gif?authuser=0000&hl=ja)
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 本以上の指のランドマークが 手が鼻のランドマークに近い場合は、ユーザーが最も 顔に触れている可能性が高まります
![](https://developers.google.cn/static/ml-kit/images/vision/pose-detection/touching_face.gif?authuser=0000&hl=ja)
アングル ヒューリスティックでヨガのポーズを認識する
さまざまな関節の角度を計算することで、ヨガのポーズを特定できます。対象 たとえば、以下の図 2 は、「Warrior II」ヨガのポーズを示しています。おおよその角度 ポーズを表す表は、次のように書かれます。
![](https://developers.google.cn/static/ml-kit/images/vision/pose-detection/warrier2_sketch.png?authuser=0000&hl=ja)
このポーズは、次のようなおおよその体の組み合わせとして表現できます。 部分角:
- 両肩を 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]];