基于YOLOv8的健身动作指导系统:从姿态估计到部署避坑
简介这份资源是面向计算机、人工智能、自动化等专业学生与教师的YOLOv8健身动作指导系统完整项目包可作为毕业设计、课程设计或大作业的参考方案帮助解决目标检测落地与可视化展示的问题。压缩包共97个文件约24.21MB以70个Python源码为核心辅以4个pt权重文件、5个xml配置、12个pyc缓存及mp4演示视频等覆盖模型训练、推理检测与界面交互等模块。项目包含源码、完整数据集、可视化页面和部署说明可生成核心指标曲线、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果与标签分布图便于答辩展示与结果分析。目前已有88人学习下载适合具备一定基础的学习者在此基础上修改扩展实现更多功能。1. 从一段手机拍摄的深蹲视频说起YOLOv8 健身动作指导系统到底在做什么健身房里最常见的场景学员对着镜子做深蹲膝盖内扣了自己却看不见教练在旁边喊“膝盖打开”学员一脸茫然。如果换成一段手机拍摄的侧面视频系统能在屏幕上实时画出骨骼线并在膝盖角度小于 90 度时弹出“下蹲过深”的提示这件事就从“凭感觉”变成了“看得见”。基于 YOLOv8 的健身动作指导系统本质上就是把人体姿态估计和动作分类串成一条流水线先用 YOLOv8 系列模型把画面里的人框出来并定位关键点再根据关键点之间的夹角、位移和时序变化判断动作是否标准最后通过一个可视化界面把结果反馈给用户。它适合三类人正在找毕设或课程设计题目的学生、想快速搭一个可演示原型的产品验证者、以及想把姿态估计落地到健身/康复/体育教学场景的工程师。整套方案包含源码、完整数据集、可视化界面和部署教程简单部署即可运行但“能跑”和“跑得准”之间隔着数据标注、关键点筛选和阈值调参三道坎下面按落地顺序拆开讲。2. 姿态估计与动作判定的技术选型为什么是 YOLOv8 而不是 OpenPose2.1 YOLOv8-pose 的关键点输出格式与推理链路YOLOv8 在姿态估计任务上用的是yolov8n-pose.pt这类权重输出的是每个检测框对应的 17 个 COCO 关键点每个点包含x, y, confidence三个值。相比 OpenPose 那种自底向上的热力图聚合YOLOv8-pose 是单阶段检测加关键点回归推理速度在 CPU 上也能做到接近实时这对“简单部署即可运行”这个诉求非常关键。常见做法是先用ultralytics库加载模型把视频帧逐帧送进去拿到results[0].keypoints之后再做角度计算。下面这段代码是推理链路的最小骨架from ultralytics import YOLO import cv2 import numpy as np # 加载姿态估计模型n 表示 nano 版本速度优先 model YOLO(yolov8n-pose.pt) cap cv2.VideoCapture(squat_demo.mp4) while cap.isOpened(): ret, frame cap.read() if not ret: break # 单帧推理verboseFalse 关闭日志刷屏 results model(frame, verboseFalse) keypoints results[0].keypoints if keypoints is not None: # xy 形状为 (num_persons, 17, 2)conf 为 (num_persons, 17) xy keypoints.xy.cpu().numpy() conf keypoints.conf.cpu().numpy() for person_xy, person_conf in zip(xy, conf): # 只保留置信度大于 0.5 的关键点 valid person_conf 0.5 left_hip person_xy[11] left_knee person_xy[13] left_ankle person_xy[15] if valid[11] and valid[13] and valid[15]: angle calculate_angle(left_hip, left_knee, left_ankle) # 膝盖角度小于 90 度判定为下蹲过深 if angle 90: cv2.putText(frame, Too Deep, (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) cv2.imshow(pose, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这段代码里calculate_angle需要自己实现输入三个点返回夹角用向量点积公式即可。参数上conf 0.5是经验阈值低于这个值的关键点抖动会非常明显宁可丢掉也不要用来算角度。yolov8n-pose.pt在 CPU 上单帧大约 80 到 120 毫秒如果换成yolov8s-pose.pt精度会好一些但速度掉一半毕设演示用 nano 足够。2.2 动作判定该用规则还是分类模型规则判定和分类模型是两条路。规则判定就是上面那种算关节夹角深蹲看膝盖角度、卧推看肘部角度、平板支撑看躯干是否成直线。优点是零训练成本、可解释性强、调阈值就能改行为缺点是遇到遮挡、侧身角度变化、个体差异时容易翻车。分类模型则是把关键点序列当成时序输入训练一个 LSTM 或 ST-GCN 来判断动作类别和标准度。优点是泛化好缺点是需要标注时序数据训练周期长。我一般会建议毕设或课程设计先用规则判定把系统跑通把可视化界面和部署流程做扎实如果时间充裕再补一个分类模型做对比实验。这样既保证了“简单部署即可运行”又有进阶空间。2.3 数据集的组织方式与标注要点标题里提到包含完整数据集这类项目的数据集通常有两种形态一种是已经标注好关键点的 COCO 格式 JSON另一种是原始视频加动作类别标签。如果要用 YOLOv8 训练自己的姿态模型目录结构要按下面这样组织dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yamldata.yaml里写清楚train、val路径和kpt_shape: [17, 3]。标注工具用 Labelme 或 CVAT 都可以Labelme 导出后需要转成 YOLO 格式转换脚本的核心逻辑是把多边形或点坐标归一化到 0 到 1 之间。这里有个血泪经验关键点标注的顺序必须和 COCO 的 17 点定义完全一致否则训练出来的模型关键点会错位表现为骨骼线交叉或跳到画面外。常见做法是先拿一张图标注完用可视化脚本画出来确认顺序再批量标。3. 从零跑通系统环境配置、训练与界面启动3.1 Ubuntu 20.04 下 CPU 版本环境搭建的完整命令很多人手里没有 GPU或者毕设环境就是一台普通笔记本所以 CPU 版本的部署路径必须走通。下面是在 Ubuntu 20.04 上从零搭环境的命令序列Python 版本建议 3.8 到 3.10# 创建虚拟环境避免污染系统 Python python3 -m venv venv source venv/bin/activate # 升级 pip老版本 pip 装 ultralytics 会报依赖冲突 pip install --upgrade pip # 安装 PyTorch CPU 版本注意 index-url 指向 cpu pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu # 安装 ultralytics 和界面依赖 pip install ultralytics opencv-python pillow pyqt5装完之后用python -c from ultralytics import YOLO; print(ok)验证。如果报libGL.so.1找不到执行sudo apt install libgl1-mesa-glx。CPU 版本推理时记得在model()调用里不要传device0否则会报 CUDA 不可用。这套环境在 8GB 内存的机器上跑 nano 模型没问题但训练就别想了训练至少需要一张 6GB 显存的卡GTX 1660 Ti 是底线。3.2 用自有数据集微调 YOLOv8-pose 的参数设置如果现成模型对你的动作场景识别不准就需要微调。训练命令如下yolo pose train datadataset/data.yaml modelyolov8n-pose.pt epochs100 imgsz640 batch8 lr00.001参数含义epochs100是迭代轮数数据量小于 2000 张时 100 轮足够再多容易过拟合imgsz640是输入分辨率调大到 1280 能提升小目标关键点精度但显存翻倍batch8在 6GB 显存上是安全值lr00.001是初始学习率默认 0.01 对微调来说偏大容易把预训练权重带偏。训练过程中用yolo pose val看 OKS 指标OKS 低于 0.6 说明标注质量或数据量有问题先别急着调模型。训练完成后权重在runs/pose/train/weights/best.pt把它替换到推理代码里即可。3.3 可视化界面的启动方式与交互逻辑可视化界面通常用 PyQt5 或 Gradio 实现。PyQt5 适合本地桌面应用Gradio 适合浏览器访问。启动方式一般是python app.py或python main.py界面里会有视频上传、摄像头开关、动作选择下拉框和实时反馈区域。交互逻辑是用户选择动作类型后系统加载对应的角度阈值配置视频帧经过 YOLOv8-pose 推理后计算关键角度和阈值比较后在画面上叠加文字提示。如果界面卡顿优先检查是不是每帧都在重新加载模型模型应该在启动时加载一次并常驻内存。另一个常见问题是 OpenCV 的imshow和 Qt 事件循环冲突解决办法是把推理放在子线程里通过信号槽更新界面。4. 避坑与排查那些让系统“看起来能跑但结果不对”的问题4.1 关键点置信度不筛选导致骨骼线乱跳现象画面上骨骼线频繁闪烁角度数值在 30 度到 170 度之间跳变。原因YOLOv8-pose 在遮挡或快速运动时会输出低置信度的关键点这些点的坐标是模型猜的直接拿来算角度必然抖动。解决在计算角度前加置信度过滤conf 0.5是底线对稳定性要求高的场景可以提到 0.7同时用滑动窗口对连续 5 帧的角度取中位数能明显压住抖动。4.2 左右侧关键点混用导致判定逻辑错乱现象同一个人做深蹲系统一会儿说左腿标准一会儿说右腿不标准。原因代码里固定取了左侧关键点索引 11、13、15但人在转身或侧对镜头时左侧关键点可能被遮挡模型把右侧的点补到了左侧索引上。解决同时计算左右两侧角度取置信度更高的一侧作为判定依据或者要求用户固定侧面朝向镜头。这个坑在演示时特别容易翻车因为演示者往往会不自觉地转身。4.3 训练时 OKS 不升反降的排查顺序现象训练到第 30 轮左右验证集 OKS 开始下降训练集 loss 还在降。原因过拟合数据量太少或增强不够。解决先看数据量小于 1000 张就加数据增强flipud0.5 fliplr0.5是姿态任务的安全增强再看学习率微调时lr0降到 0.0005 试试最后检查标注用可视化脚本随机抽 20 张图看关键点是否对齐标注错位是 OKS 上不去的头号原因。4.4 CPU 推理延迟过高导致界面卡死现象界面上传视频后进度条不动或者摄像头画面延迟好几秒。原因CPU 推理单帧耗时超过 100 毫秒如果每帧都同步推理界面线程被阻塞。解决把推理放到独立线程主线程只负责显示同时降低输入分辨率到 480p 做推理显示再用原始分辨率如果还是慢把yolov8n-pose.pt换成更小的量化版本或者跳帧推理每 3 帧处理一次。4.5 部署到 RK3588 等边缘设备时的模型转换问题现象在 PC 上跑得好好的模型转到 RK3588 上推理结果全错。原因RK3588 的 NPU 需要 RKNN 格式转换过程中关键点输出的解码方式可能和 ONNX 不一致尤其是 anchor 和 stride 的处理。解决先用rknn-toolkit2把 ONNX 转成 RKNN转换时开启量化校准校准集用训练集里的 100 张图转换后在 PC 上用 RKNN 模拟器验证输出和 ONNX 是否一致一致了再上板。这一步没有后悔药转换参数错了只能重来所以校准集和量化配置要一次做对。5. 让判定更稳的一个技巧用角度变化速度替代单帧阈值规则判定最大的问题是单帧角度受噪声影响大一个更稳的做法是看角度变化速度。深蹲的典型曲线是膝盖角度从 170 度降到 90 度再回到 170 度如果只看某一帧小于 90 度就报警偶尔的抖动就会误报。改成计算连续 10 帧的角度序列用线性回归拟合斜率当斜率绝对值超过阈值且角度进入判定区间时才触发提示误报率能降一个数量级。下面是一个简化的实现import numpy as np from collections import deque class AngleSmoother: def __init__(self, window10): # 滑动窗口保存最近 window 帧的角度 self.buffer deque(maxlenwindow) def update(self, angle): self.buffer.append(angle) if len(self.buffer) self.buffer.maxlen: return None, None arr np.array(self.buffer) # 用最小二乘拟合斜率x 为帧序号 x np.arange(len(arr)) slope np.polyfit(x, arr, 1)[0] # 返回平滑后的角度和变化速度 return float(np.median(arr)), float(slope) smoother AngleSmoother(window10) smoothed_angle, speed smoother.update(raw_angle) if smoothed_angle is not None and smoothed_angle 90 and abs(speed) 2.0: trigger_feedback(下蹲过深请调整)这段代码里window10对应大约 0.3 到 0.5 秒的时间窗口取决于帧率speed 2.0表示角度每秒变化超过 2 度这个阈值需要根据实际动作速度调深蹲慢速控制时可能只有 1 度每秒快速下蹲能到 5 度以上。用中位数替代均值是为了抗离群点偶尔一帧跳变不会带偏整体判断。这个技巧在卧推和硬拉上同样适用把角度换成肘部或髋部角度即可。我自己做这类系统时习惯先把原始角度曲线画出来看一遍确认动作的典型波形之后再定阈值比拍脑袋设数字靠谱得多。希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联
返回资讯列表 →