mediapipe-pose-detection について
MediaPipe Pose Detection は、動画の姿勢ランドマーク分析を扱うスキルで、カウンタームーブメントジャンプ分析に重点を置いています。kinemotion を使う開発者向けに、信頼度調整、平滑化、動画処理、可視化、手動検証を説明します。
主な機能
- 01ジャンプ分析向け身体ランドマーク資料
- 02検出・追跡信頼度のプリセット
- 03ランドマークのフィルタリングと平滑化
- 04動画回転と座標の解説
- 05骨格デバッグオーバーレイ
- 06フェーズ検出の手動検証
活用シーン
- 01ジャンプ動画の姿勢追跡の調整
- 02揺れるランドマークの平滑化
- 03ランドマーク欠落や左右入れ替わりの調査
- 04踏み切りと着地フレーム検出の検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ kinemotioninc/ kinemotion --skill mediapipe-pose-detectionインストール後、Claude Code で/mediapipe-pose-detectionを入力して読み込まれたか確認します。
詳細
MediaPipe のポーズ検出
ジャンプ分析に重要なランドマーク
下半身(ジャンプで主に使用)
| ランドマーク | 左のインデックス | 右のインデックス | 使用例 |
|---|---|---|---|
| 股関節 | 23 | 24 | 重心、ジャンプの高さ |
| 膝 | 25 | 26 | トリプルエクステンション、着地 |
| 足首 | 27 | 28 | 接地の検出 |
| かかと | 29 | 30 | 踏み切り/着地のタイミング |
| つま先 | 31 | 32 | 前足部の接地 |
上半身(補助的に使用)
| ランドマーク | 左のインデックス | 右のインデックス | 使用例 |
|---|---|---|---|
| 肩 | 11 | 12 | 腕振りの追跡 |
| 肘 | 13 | 14 | 腕の動作 |
| 手首 | 15 | 16 | 腕振りのタイミング |
参照点
| ランドマーク | インデックス | 使用例 |
|---|---|---|
| 鼻 | 0 | 頭の位置 |
| 左目 | 2 | 顔の向き |
| 右目 | 5 | 顔の向き |
信頼度のしきい値
デフォルト設定
min_detection_confidence = 0.5 # Initial pose detection
min_tracking_confidence = 0.5 # Frame-to-frame tracking
品質プリセット(auto_tuning.py)
| プリセット | 検出 | 追跡 | 使用例 |
|---|---|---|---|
fast | 0.3 | 0.3 | 高速処理。誤差を許容します |
balanced | 0.5 | 0.5 | デフォルト。精度は良好です |
accurate | 0.7 | 0.7 | 最高精度ですが、処理は遅くなります |
調整のガイドライン
- しきい値を上げる場合:ランドマークが揺れる、誤検出がある
- しきい値を下げる場合:ランドマークが欠落する、追跡が失われる
- 一般的な調整幅:±0.1刻み
よくある問題と解決方法
ランドマークの揺れ
症状:ランドマークがフレーム間で不規則に跳ねます
解決方法:
- Butterworth ローパスフィルターを適用します(カットオフ周波数 6-10 Hz)
- 追跡信頼度を上げます
- リアルタイムアプリケーションでは One-Euro フィルターを使用します
# Butterworth filter (filtering.py)
from kinemotion.core.filtering import butterworth_filter
smoothed = butterworth_filter(landmarks, cutoff=8.0, fps=30)
# One-Euro filter (smoothing.py)
from kinemotion.core.smoothing import one_euro_filter
smoothed = one_euro_filter(landmarks, min_cutoff=1.0, beta=0.007)
左右の取り違え
症状:動画の途中で MediaPipe が左右のランドマークを入れ替えます
原因:カメラが90°の側面角度にあるときに発生するオクルージョン
解決方法:
- 45°の斜めのカメラ角度を使用します(推奨)
- 後処理で入れ替わりを検出して修正します
- 可能な場合は片脚の追跡を使用します
追跡の喪失
症状:ランドマークが数フレームにわたって消えます
原因:
- アスリートがフレームの外に出る
- 高速動作によるモーションブラー
- 用具/衣服によるオクルージョン
解決方法:
- 動画全体を通してアスリートが完全に映るようにします
- より高いフレームレート(60 fps 以上)を使用します
- 欠落したフレームを補間します(最大3~5フレーム)
# Simple linear interpolation for gaps
import numpy as np
def interpolate_gaps(landmarks, max_gap=5):
# Fill NaN gaps with linear interpolation
for i in range(landmarks.shape[1]):
mask = np.isnan(landmarks[:, i])
if mask.sum() > 0 and mask.sum() <= max_gap:
landmarks[:, i] = np.interp(
np.arange(len(landmarks)),
np.where(~mask)[0],
landmarks[~mask, i]
)
return landmarks
信頼度スコアが低い
症状:可視性スコアが一貫してしきい値を下回ります
原因:
- 照明が不十分(逆光、影)
- 衣服と背景のコントラストが低い
- 部分的なオクルージョン
解決方法:
- 照明を改善します(正面から照らし、均一にします)
- 衣服と背景のコントラストを確保します
- カメラの視界から障害物を取り除きます
動画処理(video_io.py)
回転の処理
モバイル動画には、処理が必要な回転メタデータが含まれていることがよくあります。
# video_io.py handles this automatically
# Reads EXIF rotation and applies correction
from kinemotion.core.video_io import read_video_frames
frames, fps, dimensions = read_video_frames("mobile_video.mp4")
# Frames are correctly oriented regardless of source
手動での回転(必要な場合)
# FFmpeg rotation options
ffmpeg -i input.mp4 -vf "transpose=1" output.mp4 # 90° clockwise
ffmpeg -i input.mp4 -vf "transpose=2" output.mp4 # 90° counter-clockwise
ffmpeg -i input.mp4 -vf "hflip" output.mp4 # Horizontal flip
フレームの寸法
メタデータではなく、必ず最初のフレームから実際のフレーム寸法を読み取ります。
# Correct approach
cap = cv2.VideoCapture(video_path)
ret, frame = cap.read()
height, width = frame.shape[:2]
# Incorrect (may be wrong for rotated videos)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
座標系
MediaPipe の出力
- 正規化座標: (0.0, 0.0) ~ (1.0, 1.0)
- 原点:左上隅
- X:左から右
- Y:上から下
- Z:深度(相対値。カメラ側が負)
ピクセルへの変換
def normalized_to_pixel(landmark, width, height):
x = int(landmark.x * width)
y = int(landmark.y * height)
return x, y
可視性スコア
各ランドマークには可視性スコア(0.0~1.0)があります。
-
0.5:おそらく可視で、精度も高い
- < 0.5:オクルージョンされているか、推定値の可能性がある
- = 0.0:検出されていない
デバッグオーバーレイ(debug_overlay.py)
骨格の描画
# Key connections for jump visualization
POSE_CONNECTIONS = [
(23, 25), (25, 27), (27, 29), (27, 31), # Left leg
(24, 26), (26, 28), (28, 30), (28, 32), # Right leg
(23, 24), # Hips
(11, 23), (12, 24), # Torso
]
色分け
| 要素 | 色(BGR) | 意味 |
|---|---|---|
| 骨格 | (0, 255, 0) | 緑 - 通常のトラッキング |
| 低信頼度 | (0, 165, 255) | オレンジ - 可視性 < 0.5 |
| キー角度 | (255, 0, 0) | 青 - 測定された角度 |
| フェーズマーカー | (0, 0, 255) | 赤 - 離陸/着地 |
パフォーマンスの最適化
レイテンシの削減
- 推論を最速にするには
model_complexity=0を使用します - バッチ分析では N フレームごとに処理します
- 利用可能な場合は GPU アクセラレーションを使用します
import mediapipe as mp
pose = mp.solutions.pose.Pose(
model_complexity=0, # 0=Lite, 1=Full, 2=Heavy
min_detection_confidence=0.5,
min_tracking_confidence=0.5,
static_image_mode=False # False for video (uses tracking)
)
メモリ管理
- 処理後にポーズ推定器を解放します:
pose.close() - 大きなファイルでは動画をチャンク単位で処理します
- フレームの反復処理にはジェネレーターを使用します
kinemotion との統合
ファイルの場所
- ポーズ推定:
src/kinemotion/core/pose.py - 動画 I/O:
src/kinemotion/core/video_io.py - フィルタリング:
src/kinemotion/core/filtering.py - 平滑化:
src/kinemotion/core/smoothing.py - 自動チューニング:
src/kinemotion/core/auto_tuning.py
一般的なパイプライン
Video → read_video_frames() → pose.process() → filter/smooth → analyze
検証のための手動観察
開発中は、手動でフレームごとに観察し、正解データを確立してポーズ検出の精度を検証します。
手動観察を使用する場面
- アルゴリズム開発:新しいフェーズ検出方法を検証する場合
- パラメーター調整:検出されたフレームと実際のフレームを比較する場合
- デバッグ:ポーズ検出の失敗を調査する場合
- 正解データの収集:検証用データセットを構築する場合
正解データの収集手順
ステップ 1:デバッグ動画を生成する
uv run kinemotion cmj-analyze video.mp4 --output debug.mp4
ステップ 2:フレームごとに手動で分析する
フレーム送りに対応したツール(QuickTime、フレーム送り機能付きの VLC、または動画編集ソフト)でデバッグ動画を開きます。
ステップ 3:観察結果を記録する
各主要フェーズについて、イベントが発生するフレーム番号を記録します。
=== MANUAL OBSERVATION: PHASE DETECTION ===
Video: ________________________
FPS: _____ Total Frames: _____
PHASE DETECTION (frame numbers)
| Phase | Detected | Manual | Error | Notes |
|-------|----------|--------|-------|-------|
| Standing End | ___ | ___ | ___ | |
| Lowest Point | ___ | ___ | ___ | |
| Takeoff | ___ | ___ | ___ | |
| Peak Height | ___ | ___ | ___ | |
| Landing | ___ | ___ | ___ | |
LANDMARK QUALITY (per phase)
| Phase | Hip Visible | Knee Visible | Ankle Visible | Notes |
|-------|-------------|--------------|---------------|-------|
| Standing | Y/N | Y/N | Y/N | |
| Countermovement | Y/N | Y/N | Y/N | |
| Flight | Y/N | Y/N | Y/N | |
| Landing | Y/N | Y/N | Y/N | |
フェーズ検出の基準
立位の終了:股関節が下がり始める直前の最後のフレーム
- 確認事項:股関節が下降し始め、膝が曲がり始める
最低点:股関節が最も低い位置に達するフレーム
- 確認事項:最も深くしゃがんだ姿勢で、股関節の Y 座標が最も低い
離陸:両足が地面から離れる最初のフレーム
- 確認事項:つま先/かかとのランドマークが地面の平面から離れる
- 注:検出の遅れにより、目視で離地を確認できるタイミングより 1~2 フレーム遅れる場合があります
最高点:股関節が最も高い位置に達するフレーム
- 確認事項:滞空中に股関節の Y 座標が最も高くなる
着地:足が地面に接触する最初のフレーム
- 確認事項:かかとまたはつま先のランドマークが地面の平面に触れる
- 注:アルゴリズムは 1~2 フレーム遅れて検出する場合があります(速度ベース)
ランドマークの品質評価
各ランドマークについて、次のように観察します。
| 品質 | 基準 |
|---|---|
| 良好 | ランドマークが安定し、身体の部位に正しく配置されている |
| 揺れあり | ランドマークがフレーム間で ±5~10 ピクセル振動する |
| ずれ | ランドマークが実際の位置から一貫してずれている |
| 消失 | ランドマークが欠落している、または大きく誤っている |
| 入れ替わり | 左右のランドマークが入れ替わっている |
観察結果の記録形式
検証時は、構造化データを提示します。
## Ground Truth: [video_name]
**Video Info:**
- Frames: 215
- FPS: 60
- Duration: 3.58s
- Camera: 45° oblique
**Phase Detection Comparison:**
| Phase | Detected | Manual | Error (frames) | Error (ms) |
|-------|----------|--------|----------------|------------|
| Standing End | 64 | 64 | 0 | 0 |
| Lowest Point | 91 | 88 | +3 (late) | +50 |
| Takeoff | 104 | 104 | 0 | 0 |
| Landing | 144 | 142 | +2 (late) | +33 |
**Error Analysis:**
- Mean absolute error: 1.25 frames (21ms)
- Bias detected: Landing consistently late
- Accuracy: 2/4 perfect, 4/4 within ±3 frames
**Landmark Issues Observed:**
- Frame 87-92: Hip jitter during lowest point
- Frame 140-145: Ankle tracking unstable at landing
許容誤差のしきい値
60fps(1 フレームあたり 16.67ms)の場合:
| 誤差レベル | フレーム | 時間 | 解釈 |
|---|---|---|---|
| 完全 | 0 | 0ms | 完全一致 |
| 非常に良好 | ±1 | ±17ms | 人間の観察によるばらつきの範囲内 |
| 良好 | ±2 | ±33ms | ほとんどの指標で許容可能 |
| 許容範囲 | ±3 | ±50ms | 精密なタイミング指標に影響する可能性があります |
| 要調査 | >3 | >50ms | アルゴリズムの調整が必要な場合があります |
バイアス検出
複数の動画にわたる系統的なパターンを確認します。
| パターン | 意味 | 対応 |
|---|---|---|
| 一貫して +N フレーム | アルゴリズムの検出が遅い | しきい値を早めに調整する |
| 一貫して -N フレーム | アルゴリズムの検出が早い | しきい値を遅めに調整する |
| ±N フレームで変動 | 通常のばらつき | 対応は不要です |
| 誤差が増加 | トラッキングの精度が低下 | ランドマークの品質を確認する |
basic-memory との連携
グラウンドトゥルースの観察結果を保存します。
# Save validation results
write_note(
title="CMJ Phase Detection Validation - [video_name]",
content="[structured observation data]",
folder="biomechanics"
)
# Search previous validations
search_notes("phase detection ground truth")
# Build context for analysis
build_context("memory://biomechanics/*")
例:CMJ 検証研究の参照資料
検証研究の全容については、basic-memory を参照してください。
biomechanics/cmj-phase-detection-validation-45deg-oblique-view-ground-truthbiomechanics/cmj-landing-detection-bias-root-cause-analysisbiomechanics/cmj-landing-detection-impact-vs-contact-method-comparison
検証で得られた主な結果:
- 立位終了:精度 100%(誤差 0 フレーム)
- 離地:約 0.7 フレームの平均誤差(非常に優秀)
- 最低点:約 2.3 フレームの平均誤差(ばらつきあり)
- 着地:一貫して +1〜2 フレームのバイアス(要調査)