mcpField
M
mediapipe-pose-detection

mediapipe-pose-detection

github.com/kinemotioninc开发194 次安装34 周前更新
代码仓库

关于 mediapipe-pose-detection

MediaPipe Pose Detection 是用于分析视频姿态关键点的技能,内容侧重反向跳分析。它为使用 kinemotion 的开发者介绍置信度调整、平滑、视频处理、可视化和人工验证。

主要功能

  1. 01面向跳跃的身体关键点参考
  2. 02检测与跟踪置信度预设
  3. 03关键点滤波与平滑
  4. 04视频旋转和坐标说明
  5. 05骨架调试叠加层
  6. 06人工验证阶段检测

适用场景

  1. 01调整跳跃视频的姿态跟踪
  2. 02平滑抖动的关键点
  3. 03排查关键点丢失或左右互换
  4. 04验证起跳与落地帧检测

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/kinemotioninc/kinemotion --skill mediapipe-pose-detection

安装后在 Claude Code 中输入/mediapipe-pose-detection确认已加载。

详细介绍

MediaPipe 姿态检测

跳跃分析的关键地标

下半身(跳跃分析的重点)
地标左侧索引右侧索引用途
髋部2324质心、跳跃高度
膝盖2526三关节伸展、落地
脚踝2728检测是否触地
脚跟2930起跳/落地时机
脚趾3132前脚掌触地
上半身(次要)
地标左侧索引右侧索引用途
肩部1112跟踪手臂摆动
肘部1314手臂动作
手腕1516手臂摆动时机
参考点
地标索引用途
鼻子0头部位置
左眼2面部朝向
右眼5面部朝向

置信度阈值

默认设置
min_detection_confidence = 0.5  # Initial pose detection
min_tracking_confidence = 0.5   # Frame-to-frame tracking
质量预设(auto_tuning.py)
预设检测跟踪用途
fast0.30.3快速处理,可容忍错误
balanced0.50.5默认设置,准确度良好
accurate0.70.7准确度最高,但速度较慢
调整指南
  • 提高阈值的情况:地标抖动、误检测
  • 降低阈值的情况:地标缺失、跟踪丢失
  • 典型调整幅度:每次 ±0.1

常见问题及解决方案

地标抖动

症状:地标在不同帧之间不规则跳动

解决方案:

  1. 应用 Butterworth 低通滤波器(截止频率为 6-10 Hz)
  2. 提高跟踪置信度
  3. 在实时应用中使用 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° 侧向角度时发生遮挡

解决方案:

  1. 使用 45° 斜向摄像机角度(推荐)
  2. 后处理以检测并纠正交换
  3. 尽可能使用单腿跟踪
跟踪丢失

症状:地标连续数帧消失

原因:

  • 运动员移出画面
  • 快速运动导致运动模糊
  • 器材/衣物造成遮挡

解决方案:

  1. 确保视频中始终能看到运动员全身
  2. 使用更高的帧率(60+ fps)
  3. 对缺失帧进行插值(最多 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
置信度分数较低

症状:可见度分数持续低于阈值

原因:

  • 光线不佳(逆光、阴影)
  • 衣物与背景对比度低
  • 部分遮挡

解决方案:

  1. 改善光线(正面照明、光线均匀)
  2. 确保衣物与背景形成对比
  3. 移除摄像机视野中的障碍物

视频处理(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)红色 - 起跳/落地

性能优化

降低延迟
  1. 使用 model_complexity=0 以实现最快推理
  2. 批量分析时,每隔 N 帧处理一帧
  3. 如果可用,使用 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. 算法开发:验证新的阶段检测方法
  2. 参数调优:比较检测到的帧与实际帧
  3. 调试:调查姿势检测失败问题
  4. 真实值收集:构建验证数据集
真实值数据收集流程

步骤 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 下(每帧 16.67ms):

误差级别帧数时间解释
完美00ms完全匹配
极佳±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-truth
  • biomechanics/cmj-landing-detection-bias-root-cause-analysis
  • biomechanics/cmj-landing-detection-impact-vs-contact-method-comparison

验证研究的主要发现:

  • 站立结束:准确率 100%(误差 0 帧)
  • 起跳:平均误差约 0.7 帧(极佳)
  • 最低点:平均误差约 2.3 帧(波动较大)
  • 落地:持续偏差 +1-2 帧(需调查)

评论

支持 Markdown