← 归档 / 健身科技

用 AI 记录每一次深蹲:健身姿态识别入门

从一颗摄像头到一份实时反馈,聊聊我如何用姿态识别把「动作对不对」这件事变得可被看见、可被纠正。

训练里最难的从来不是坚持一次,而是每一次都做对。一个人练深蹲,最缺的其实是一双能在旁边提醒你的眼睛。于是我想:能不能让一颗普通的摄像头,成为那双眼睛。

这篇文章记录我做 AI 智能健身助手时,姿态识别部分从零到可用的思路。它不追求炫技,只想把「动作对不对」这件模糊的事,变成可被看见、可被纠正的小步骤——像劈竹一样,第一节最难,之后顺势而下。

为什么是姿态识别

传统的计次 App 只知道你「动了」,却不知道你「动得对不对」。而大多数运动损伤,恰恰来自那些没被察觉的细节:膝盖内扣、腰椎代偿、幅度不够。

姿态识别的价值在于,它能把身体的关键点实时抽取出来,让「发力是否到位」这种主观感受,第一次拥有了客观的度量。

能被测量的东西,才能被温柔地改进。

整体流程

从一帧画面到一句提示,中间只需要四步。用一张图就能说清:

flowchart LR
  A[摄像头帧] --> B[关键点检测]
  B --> C[关节角度计算]
  C --> D{是否达标}
  D -->|是| E[记录一次有效动作]
  D -->|否| F[实时纠正提示]

整个链路刻意保持轻量:检测在本地完成,不上传任何画面,既快又让人安心。

计算关节角度

判断深蹲是否到位,核心是膝关节的角度。给定髋、膝、踝三个关键点,我们用向量夹角求出膝盖弯曲的程度:

θ=arccos((ab)ab)\theta = \arccos\left( \frac{(\vec{a} \cdot \vec{b})}{\lVert \vec{a} \rVert \, \lVert \vec{b} \rVert} \right)

其中 a\vec{a} 是膝到髋的向量,b\vec{b} 是膝到踝的向量。当 θ\theta 小于设定阈值时,说明蹲得足够深。

落到代码里,它其实很短:

import numpy as np

def joint_angle(hip, knee, ankle):
    """返回膝关节角度(度)。三个点均为 (x, y)。"""
    a = np.array(hip) - np.array(knee)
    b = np.array(ankle) - np.array(knee)
    cos = np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b) + 1e-8)
    return np.degrees(np.arccos(np.clip(cos, -1.0, 1.0)))

def is_valid_squat(angle, threshold=95.0):
    # 角度越小,蹲得越深;小于阈值视为一次有效深蹲
    return angle <= threshold

1e-8 是为了避免除零;np.clip 则确保浮点误差不会让 arccos 收到超出 [-1, 1] 的输入。这些小心思,往往是稳定运行的关键。

阈值不是拍脑袋定的

不同身高、不同柔韧度的人,「标准深蹲」的角度并不一样。我采集了一小批样本,观察有效与无效动作的角度分布:

动作质量平均膝角建议阈值提示语气
过浅118°> 100°「再往下一点」
达标88°85°–95°「很好,保持」
过深62°< 70°「注意膝盖压力」

于是阈值从固定值,变成了一个会根据个人历史微调的区间。这一步之后,误报明显少了。

一些还没解决的事

  • 侧面遮挡时,踝关节的关键点会抖动,需要做时序平滑;
  • 光线很暗时检测置信度下降,得给用户一个诚实的「暂时看不清」状态;
  • 计划把「一组动作」的节奏也纳入评估,而不只是单次。

这些留待下一篇慢慢写。做产品和练身体一样,忍耐便是必修课——先把一节竹子劈开,剩下的自然会顺。

如果你也在做类似的事,欢迎在评论里聊聊你的思路。

写于 2025-05-12 · 最后更新 2025-05-15。

评论

0 条
温和一点,这里是安静的角落。

正在加载评论…