尧图精选

基于 YOLOv8 姿势估计的 AI 健身房动作计数:`AIGym` 模块原理与实战指南

🕒 发布时间:2026/9/15 11:28:21 📁 来源:尧图网络
基于 YOLOv8 姿势估计的 AI 健身房动作计数AIGym模块原理与实战指南【免费下载链接】yolov10YOLOv10: Real-Time End-to-End Object Detection [NeurIPS 2024]项目地址: https://gitcode.com/GitHub_Trending/yo/yolov10导读本文围绕当前仓库 ultralytics/solutions/ai_gym.py 中实现的AIGym类讲解如何利用 YOLOv8 姿态估计模型在实时视频流中对俯卧撑pushup、引体向上pullup和卷腹abworkout三类健身动作进行自动计数与阶段判定。读完本文你将掌握AIGym的核心状态机逻辑、关键点角度计算原理、set_args全部配置参数的用法并能写出一个可直接运行的健身动作计数 结果保存的完整脚本。一、AIGym是什么从姿态估计到动作计数YOLOv8 的 pose 任务docs/en/tasks/pose.md会为画面中每个人输出 17 个关键点COCO 关键点集每个关键点包含[x, y, confidence]三维坐标。姿态估计回答了人的关节在哪里的问题但某个动作做了几次还需要额外的逻辑来判断。AIGym正是负责这层逻辑的解决方案模块它接收姿态估计的推理结果选取 3 个与动作强相关的关键点计算它们构成的关节角度再依据角度大小切换动作的阶段stage从而完成计数。从源码看AIGym类ultralytics/solutions/ai_gym.py#L9的核心状态数据包括self.keypoints None # 当前帧的关键点数据 self.poseup_angle None # 动作举起/起身状态的角度阈值 self.posedown_angle None # 动作下压/下放状态的角度阈值 self.threshold 0.001 self.angle None # 每次计算的关节角度 self.count None # 每个人累计的动作次数 self.stage None # 当前阶段up/down/- self.pose_type pushup # 支持的动作类型需要说明的是AIGym同时是 Ultralytics 官方库的通用组件当前仓库中的实现是同一代码路径因此下文所有结论均可直接在 ultralytics/solutions/ai_gym.py 与 ultralytics/utils/plotting.py 中验证。二、动作计数的工作原理角度阈值 阶段状态机1. 关节角度如何计算AIGym自身不重新发明角度计算而是调用Annotator.estimate_pose_angle(a, b, c)静态方法ultralytics/utils/plotting.py#L397a, b, c np.array(a), np.array(b), np.array(c) radians np.arctan2(c[1] - b[1], c[0] - b[0]) - np.arctan2(a[1] - b[1], a[0] - b[0]) angle np.abs(radians * 180.0 / np.pi) if angle 180.0: angle 360 - angle return angle其中b是关节的顶点如肘部a、c是它的两个邻接点如肩与腕。方法先计算两条边相对水平线的反正切角差再换算成度数最后将大于 180° 的角度归一化到 [0, 180] 区间返回值单位是度degree。2. 三种动作的阶段状态机AIGym.start_counting()ultralytics/solutions/ai_gym.py#L66对每帧、每个人执行一次状态判断。代码为每种pose_type实现了独立的判定逻辑它们的状态转换规则如下表动作类型角度大于pose_up_angle时角度小于pose_down_angle时计数时机pushup俯卧撑阶段置为up若处于up置为down每次up → down计 1 次pullup引体向上阶段置为down若处于down置为up每次down → up计 1 次abworkout卷腹阶段置为down若处于down置为up每次down → up计 1 次以俯卧撑为例对应源码逻辑ultralytics/solutions/ai_gym.py#L112if self.pose_type pushup: if self.angle[ind] self.poseup_angle: self.stage[ind] up if self.angle[ind] self.posedown_angle and self.stage[ind] up: self.stage[ind] down self.count[ind] 1关键点在于计数依赖阶段先置位再靠状态切换触发而不是简单地角度低于阈值就加一。这能有效避免动作在阈值附近抖动导致的重复计数也解释了为什么pose_up_angle与pose_down_angle两个阈值必须拉开差距默认 145° 与 90°形成一段滞回区间。3. 初始化与多目标支持start_counting会在第一帧为每个检测对象分配独立的计数容器ultralytics/solutions/ai_gym.py#L76-L79if frame_count 1: self.count [0] * len(results[0]) self.angle [0] * len(results[0]) self.stage [- for _ in results[0]]从源码结构看AIGym是按帧内检测对象索引管理计数器的。若同一人跨帧位置变化或出现遮挡独立计数可能中断因此官方在示例中明确推荐配合model.track()使用由跟踪器提供跨帧稳定的对象关联这也是下一节实战脚本中优先选用跟踪而非纯检测的原因。三、实战健身动作计数完整脚本官方在 docs/en/guides/workouts-monitoring.md 中给出了可直接运行的示例下面给出实时预览与保存结果两个版本并补充逐行注释。1. 实时预览版本from ultralytics import YOLO from ultralytics.solutions import ai_gym import cv2 model YOLO(yolov8n-pose.pt) # 加载 COCO 关键点预训练 pose 模型 cap cv2.VideoCapture(path/to/video/file.mp4) assert cap.isOpened(), Error reading video file w, h, fps (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS)) gym_object ai_gym.AIGym() # 初始化 AI Gym 模块 gym_object.set_args(line_thickness2, view_imgTrue, pose_typepushup, kpts_to_check[6, 8, 10]) # 左肩、左肘、左腕 frame_count 0 while cap.isOpened(): success, im0 cap.read() if not success: print(Video frame is empty or video processing has been successfully completed.) break frame_count 1 results model.track(im0, verboseFalse) # 推荐使用跟踪保证跨帧计数稳定 # results model.predict(im0) # 纯检测同样受支持 im0 gym_object.start_counting(im0, results, frame_count) # 按 q 键可退出窗口 cv2.destroyAllWindows()2. 保存输出视频版本from ultralytics import YOLO from ultralytics.solutions import ai_gym import cv2 model YOLO(yolov8n-pose.pt) cap cv2.VideoCapture(path/to/video/file.mp4) assert cap.isOpened(), Error reading video file w, h, fps (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS)) video_writer cv2.VideoWriter(workouts.avi, cv2.VideoWriter_fourcc(*mp4v), fps, (w, h)) gym_object ai_gym.AIGym() gym_object.set_args(line_thickness2, view_imgTrue, pose_typepushup, kpts_to_check[6, 8, 10]) frame_count 0 while cap.isOpened(): success, im0 cap.read() if not success: print(Video frame is empty or video processing has been successfully completed.) break frame_count 1 results model.track(im0, verboseFalse) im0 gym_object.start_counting(im0, results, frame_count) video_writer.write(im0) # 将带标注的帧写入视频文件 cv2.destroyAllWindows() video_writer.release()start_counting返回的是已经叠加标注的im0ultralytics/solutions/ai_gym.py#L146因此两个版本的核心循环结构完全一致区别仅在是否把返回帧交给cv2.VideoWriter。3. 输出画面里有什么start_counting每帧会依次调用Annotator的三个绘制方法ultralytics/solutions/ai_gym.py#L90-L139draw_specific_points(k, kpts_to_check, shape(640, 640), radius10)以绿色圆点标出参与角度计算的 3 个关键点ultralytics/utils/plotting.py#L416该方法会跳过置信度低于 0.5 的关键点plot_angle_and_count_and_stage(...)以指定关键点为锚点绘制当前角度值、Steps : N计数和up/down阶段三行文本ultralytics/utils/plotting.py#L437kpts(k, shape(640, 640), radius1, kpt_lineTrue)绘制全身 17 个关键点与骨架连线。同时若满足env_check环境支持imshow且view_imgTrue窗口标题为Ultralytics YOLOv8 AI GYM按下q键即可结束循环ultralytics/solutions/ai_gym.py#L141-L144。四、set_args参数详解与关键点选择AIGym的set_args方法ultralytics/solutions/ai_gym.py#L39负责注入全部可配置项参数含义如下参数类型默认值说明kpts_to_checklist无参与角度计算的 3 个关键点索引按关键点映射表选取如俯卧撑用[6, 8, 10]左肩、左肘、左腕line_thicknessint2文本与标注线条的粗细同时影响字体缩放font_scale 0.6 line_thickness / 10.0view_imgboolFalse是否实时弹窗显示带计数的画面pose_up_anglefloat145.0动作上状态的角度阈值pose_down_anglefloat90.0动作下状态的角度阈值pose_typestrpullup动作类型pushup、pullup、abworkout注官方文档参数表中pose_type默认值标注为pushup而本仓库set_args签名中的默认值为pullupultralytics/solutions/ai_gym.py#L46。由于在实际调用中该参数通常显式传入两者并不冲突但若要严格对齐本仓库源码请以pullup为准。关键点映射COCO 17 点YOLOv8 pose 模型输出 17 个 COCO 关键点kpts_to_check的索引即对应下表编号yolov8-pose模型的kpt_shape: [17, 3]见 ultralytics/cfg/models/v8/yolov8-pose.yaml索引关键点索引关键点0鼻子9左腕1左眼10右腕2右眼11左髋3左耳12右髋4右耳13左膝5左肩14右膝6右肩15左踝7左肘16右踝8右肘——官方示例kpts_to_check[6, 8, 10]取的是右肩、右肘、右腕即以右肘为顶点计算手臂夹角若想改用左臂则应传[5, 7, 9]。不同动作建议的关键点组合以官方参数表followed by keypoint Map为准则可结合实际动作微调pushup手臂夹角如[6, 8, 10]右肩-右肘-右腕pullup同样依赖肘部夹角取上臂-前臂组合即可abworkout需要体现躯干屈伸可选取肩-髋组合如[6, 12, 14]这类含髋的关键点组合并按实际动作重新标定上下角度阈值。五、配套推理参数model.predict与model.track动作计数依赖每帧的姿态关键点质量因此推理参数会直接影响计数精度。官方文档给出了两份常用参数表。model.predict关键参数参数类型默认值说明sourcestrultralytics/assets图像或视频来源目录conffloat0.25检测置信度阈值ioufloat0.7NMS 的 IoU 阈值imgszint or tuple640推理尺寸标量或(h, w)列表halfboolFalse是否使用 FP16 半精度推理deviceNone or strNone运行设备如cuda device0/1/2/3或cpumax_detint300单图最大检测数vid_strideboolFalse视频抽帧步长stream_bufferboolFalse缓冲全部流帧True或仅返回最新帧FalsevisualizeboolFalse是否可视化模型特征augmentboolFalse是否对推理源做数据增强agnostic_nmsboolFalse是否使用类别无关 NMSclasseslist[int]None按类别过滤结果retina_masksboolFalse是否使用高分辨率分割掩码embedlist[int]None返回指定层的特征向量/嵌入model.track关键参数参数类型默认值说明sourceim0None图像或视频来源persistboolFalse是否跨帧持久化跟踪轨迹trackerstrbotsort.yaml跟踪器bytetrack或botsortconffloat0.3置信度阈值ioufloat0.5IoU 阈值classeslistNone按类别过滤verboseboolTrue是否打印跟踪结果实战建议视频计数场景优先使用model.track(im0, verboseFalse)并显式传persistTrue以获得跨帧稳定的对象 ID若使用model.predict则多人画面下的计数可能因检测顺序变化而不稳定。六、应用价值与使用限制官方文档从运动监测视角总结了此类AI 健身房方案的价值基于监测数据定制训练方案优化表现、跟踪并调整健身目标目标达成、依据个体数据实现个性化计划个性化、及早发现过度训练等健康信号健康感知、以及用数据驱动的方式调整训练节奏辅助决策。这些描述反映了该模块的典型应用方向属于官方文档表述而非本仓库的评测结论。同时应说明使用限制均可在源码中得到印证计数依赖关键点质量draw_specific_points会跳过置信度低于 0.5 的关键点ultralytics/utils/plotting.py#L432当遮挡严重或人体过小时角度计算与计数将失真需要标定阈值pose_up_angle与pose_down_angle的默认值145°/90°适用于常规俯卧撑视角不同机位、不同体型需要重新标定且两阈值必须拉开滞回区间以避免抖动计数计数按检测对象索引管理第一帧后按对象数量初始化计数器视频开头需保证人物稳定出现结合跟踪器使用可显著改善连续计数体验模型加载脚本首行YOLO(yolov8n-pose.pt)会自动下载对应的 COCO 关键点预训练权重需保持网络可用后续也可换成yolov8s-pose.pt等更大模型以提升精度。七、总结AIGym是 YOLOv8 姿态估计生态中一个精巧的应用层模块它把 17 个关键点的原始坐标通过三点夹角计算与up/down阶段状态机转化为俯卧撑、引体向上、卷腹的实时计数与阶段可视化。本文的核心结论均可回溯到 ultralytics/solutions/ai_gym.py 与 ultralytics/utils/plotting.py 两处源码以及 docs/en/guides/workouts-monitoring.md 的官方示例。若需进一步了解 pose 任务的训练、验证与导出方式可查阅 docs/en/tasks/pose.md。【免费下载链接】yolov10YOLOv10: Real-Time End-to-End Object Detection [NeurIPS 2024]项目地址: https://gitcode.com/GitHub_Trending/yo/yolov10创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →