
简介面向Python开发者与计算机视觉初学者的YOLOv8人体姿势识别资源包可直接用于图片或视频中的人体关键点检测也可作为基础预训练模型继续微调帮助快速建立属于自己的姿态估计流程。压缩包共4个文件整体约31.33MB内部包含一个预训练权重文件、一个完整的Python推理脚本以及两张分别用于原图对比和效果验证的PNG图片兼顾了模型权重复现与运行示例。目前已有559人浏览学习内置的唐朝诡事录经典站位图识别演示展示了多人体同时检测能力能够准确识别面部与躯体关键点方便使用者直观评估模型精度。得益于开箱即用的脚本设计和紧凑的包体结构用户下载后只需准备基础Python环境即可快速运行并查看识别结果还可以参考代码结构将识别能力接入运动分析、医疗康复或虚拟现实等项目若需特定动作识别还能进一步使用自定义数据对现有模型进行再训练以适配不同场景需求。这一设计同时适用于快速原型验证与初步部署为个人学习或团队开发节约大量调试验证时间。1. 人体姿势识别选型为什么是 YOLOv8 预训练模型而不是从头训练做人体姿势识别最容易被绕进去的一个念头是「我要自己搭网络、自己找数据、自己训练」。作为跑过几轮完整训练流程的人我得先泼一盆冷水如果你不是要发论文、不是有特殊骨骼点定义只是想把「图片/视频里的人的姿势」稳定识别出来直接用 YOLOv8 预训练模型 Python 推理代码是投入产出比最高的路线。YOLOv8 官方提供的 pose 预训练权重在 COCO 关键点数据集上训过覆盖 17 个身体关键点单张图片推理在 CPU 上也能跑到百毫秒级换 GPU 更是快到可以按帧处理视频。这个资源的核心就是把这条路线完整打包好了模型权重文件、整套可运行的 Python 推理代码图片和视频两条输入路径都能直接跑通不需要你再碰训练流程。适合谁用一类是刚接触姿态识别的 Python 开发者想先看到一个能出结果的项目另一类是做安防、健身计数、人机交互原型的工程师需要一个能快速集成到现有 Python 工程里的推理模块。适合的前提是你懂基础 Python 语法会装依赖。下面我从环境准备讲起把模型加载、图片推理、视频推理和排错全部过一遍。2. 环境准备与模型加载Python 侧依赖安装和 pose 权重文件2.1 为什么依赖集中在 ultralytics 这一个库上YOLOv8 的官方实现在 ultralytics 这个 Python 包里。跟早期 YOLO 系列要手动拼一堆 OpenCV 和 PyTorch 代码不同YOLOv8 把模型定义、权重加载、前处理、后处理、NMS、关键点解码全部封装在库里了对外暴露的接口非常薄。这对做应用的工程师来说是个大好事你不用关心 17 个关键点的热力图是怎么解码出来的只要把图片传进去拿回来的结果里就有每个检测框、每个关键点的坐标和置信度。安装上老手可能直接 pip install ultralytics但我建议新手先确认 Python 版本。这个库对 Python 3.8 以上支持比较稳3.7 以下容易遇到依赖冲突。另外 ultralytics 会依赖 PyTorch如果你机器上有 NVIDIA 显卡建议先装好 CUDA 版 PyTorch 再装 ultralytics否则它会默认拉 CPU 版 torch后面视频按帧跑会很吃力。# 先确认 Python 版本3.8 ~ 3.11 之间最稳 python --version # 有 NVIDIA GPU 的话先装 CUDA 版 PyTorch以 cu118 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 再装 ultralytics它会自动带上依赖的 opencv-python、numpy 等 pip install ultralytics这段逻辑里有两个关键决定先装 torch 是为了避免 ultralytics 安装时把 CPU 版 torch 当依赖拉进来用 cu118 的 index-url 是因为 PyTorch 官方源把不同 CUDA 版本的 wheel 分开存放了不加这个参数在 Windows 上很容易装成 CPU 版本。装完后可以用 python -c import torch; print(torch.cuda.is_available()) 验证 GPU 是否可用输入 True 说明显卡被正确识别。2.2 模型文件到底长什么样yolov8n-pose.pt 与自动下载机制姿势识别用的权重文件和普通目标检测不一样文件名带 pose 标记常见的几个规格是 yolov8n-pose.pt、yolov8s-pose.pt、yolov8m-pose.ptn 是 nano 最小版m 是中等精度版。n 版权重只有 6MB 左右CPU 上跑得快m 版精度更高但推理时间翻几倍。这个资源里默认用的是 yolov8n-pose.pt。你第一次调用 YOLO(yolov8n-pose.pt) 时如果本地不存在这个文件ultralytics 会自动去官方 GitHub 下载。这个机制在联网顺畅时很省事但有两个隐患一是网络差的地方会卡住不报错二是下载到哪个目录你不知道的话排查困难。本地缓存路径是 ~/.cache/ultralyticsWindows 上是 C:\Users\你的用户名\AppData\Local\ultralytics\确认文件是否存在可以用 ls 看一下。from ultralytics import YOLO # 模型文件若不存在会自动下载到本地缓存目录 model YOLO(yolov8n-pose.pt) # 打印模型结构确认是 pose 模型而不是 detect 模型 print(model.task) # 输出应该是 pose这里 model.task 输出 pose 是重要自检点。如果你下错成普通检测模型task 字段会是 detect后面拿不到关键点数据报错方式还挺隐晦——results 对象里没有 keypoints 属性。文件命名里带 n 的版本参数量是 3.2M对应 COCO 预训练权重如果换 s 或 m 版本后面推理时把模型加载路径改成对应 .pt 文件名就行其余代码不用改。2.3 验证推理链路最快的方法单张图片跑通环境装好后的第一件事不是直接跑视频而是先拿单张图片把推理链路打通。这里最怕的情况是模型加载成功、但推理时爆出一堆底层库错误比如 OpenCV 解码异常或者 torch 张量设备不匹配。先跑一张图把变量范围缩到最小。from ultralytics import YOLO model YOLO(yolov8n-pose.pt) results model(test.jpg, saveTrue) print(results[0].keypoints.data.shape) # 期望输出形状 torch.Size([1, 17, 3])saveTrue 会把标注好骨架的图片保存在 runs/pose/predict 目录下默认命名是原文件名加下划线。keypoints.data 这个属性在后续代码里会经常用到它存的就是每个检测到的行人对应的 17 个关键点坐标和置信度形状是 [检测人数, 17, 3]最后一维的 3 分别是 x 坐标、y 坐标、置信度。如果这个 shape 打印出来不符合预期要么图片里没人要么模型权重加载错了。到这里单张图片的推理链路就算验证完成了。3. 图片推理代码拆解一行代码出骨架关键点坐标怎么读3.1 单图片推理的完整流程加载、推理、绘制、保存直接调用 model(图片路径) 在代码层面只有一行但实际落到工程里我们需要的是能拿到「人体检测框 关键点坐标 骨架绘制图」的完整结果。下面这段代码演示了最常用的图片推理写法带详细参数控制。from ultralytics import YOLO model YOLO(yolov8n-pose.pt) results model.predict( sourceinput.jpg, conf0.5, # 关键点置信度阈值低于该值的点会被过滤 iou0.45, # NMS 的 IoU 阈值调大允许更多重叠框保留 devicecpu, # 没 GPU 时指定 cpu有 GPU 可改成 0 saveTrue, # 保存标注后的图片 projectpose_output, # 输出目录名 nameimage_result, # 子目录名 exist_okTrue # 允许重复写入同名目录 ) keypoints_data results[0].keypoints.data boxes results[0].boxes.xyxy print(f检测到 {len(boxes)} 个人关键点张量形状: {keypoints_data.shape})predict 方法和直接调用 model 的区别在于 predict 暴露了全部推理参数适合工程化场景。conf 参数很关键默认值是 0.25但实际做姿势识别时 0.4 到 0.5 体验更好低了会出现大量抖动点iou 参数控制两个检测框的合并策略默认 0.7 针对密集人群会漏检我一般调到 0.45 到 0.5。device 参数建议显式指定否则 ultralytics 会自己探测在部分机器上会出现「有显卡但没装好 CUDA 导致崩掉」的情况。3.2 关键点坐标的含义COCO 17 点索引表与置信度过滤拿到 keypoints_data 只是第一步你得知道每个索引对应身体哪个部位。YOLOv8 的 pose 模型沿用 COCO 数据集的关键点定义17 个点的索引顺序是固定的0 鼻子、1 左眼、2 右眼、3 左耳、4 右耳、5 左肩、6 右肩、7 左肘、8 右肘、9 左腕、10 右腕、11 左髋、12 右髋、13 左膝、14 右膝、15 左踝、16 右踝。这个顺序不少人在第一次拿数据时吃过亏因为它既不是从头到脚的排列也不是从左到右的排列左右是混着来的。实际代码里你需要根据置信度把不可靠的点过滤掉。COCO 数据集中标记为不可见的点模型输出的置信度会极低如果不过滤直接用于距离计算算出来的关节角度会非常离谱。import torch keypoints results[0].keypoints.data # [人数, 17, 3] for person_idx in range(keypoints.shape[0]): person_kpts keypoints[person_idx] for kpt_idx in range(17): x, y, conf person_kpts[kpt_idx] if conf 0.5: print(f行人 {person_idx} 的 {kpt_idx} 号点左肩置信度过低忽略) continue print(f行人 {person_idx} 的 {kpt_idx} 号点坐标: ({x:.1f}, {y:.1f}), 置信度: {conf:.2f})这段代码的核心在 torch 张量的索引方式上person_kpts[kpt_idx] 拿到的是一维张量直接解包成 x、y、conf 三个变量。注意这里的坐标是原始图片像素坐标不是归一化坐标所以用的时候可以直接拿来在图上画点或者换算成像素距离。部分场景下你会需要归一化坐标可以用 results[0].keypoints.xyn 拿到它是 xy 坐标除以图片宽高后的结果范围在 0 到 1 之间适合做姿态对比时消除图片尺寸影响。3.3 骨架连线与检测框绘制plot 方法的输出对象上面用 saveTrue 保存图片底层其实是 ultralytics 调用了 results[0].plot() 方法。这个方法返回一个 numpy 数组格式的图片骨架连线逻辑已经内置好了比如左肩到左肘、左肘到左腕会自动连起来。如果你想在保存之前对标注结果做二次加工——比如叠加自己的文字、画特殊的区域标注就需要先拿到 plot() 的返回值再处理。import cv2 from ultralytics import YOLO model YOLO(yolov8n-pose.pt) results model(input.jpg) annotated_frame results[0].plot() # 返回 BGR 格式的 numpy 数组 cv2.imwrite(annotated_custom.jpg, annotated_frame) # 在图上额外叠加一个提示文字 cv2.putText(annotated_frame, pose detected, (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) cv2.imwrite(annotated_with_text.jpg, annotated_frame)plot() 返回的数组就是 OpenCV 的 BGR 三通道图可以直接用 cv2.imwrite 保存。就算你不想用 OpenCV 做额外处理理解 plot 这个方法也有价值因为视频推理里每一帧都要调用一次 plot()把返回值填到 VideoWriter 里才能生成带骨架标注的视频。4. 视频推理代码实战按帧处理的人体姿势识别流程与性能平衡4.1 直接调用 predict 做视频推理的写法与它的局限视频推理最省事的写法是直接把视频文件路径传给 model.predictultralytics 会自己拆帧、推理、合成输出视频。但这有个前提——你的视频文件格式是它支持的常见编码比如 H.264 编码的 mp4。如果遇到特殊编码或者视频很长导致内存不够直接传路径就不够稳了。另外这种方式对每帧都做完整推理不做任何跳帧处理帧率低且文件特别大。from ultralytics import YOLO model YOLO(yolov8n-pose.pt) results model.predict( sourceinput_video.mp4, conf0.5, saveTrue, projectpose_output, namevideo_result )这种写法适合快速验证模型在视频上的效果输出文件默认在 pose_output/video_result 目录下。局限很明显你不能在推理过程中干预单帧结果比如视频里出现特定姿态时你想在那一帧额外叠加报警信息也不能做跳帧处理。所以真正做项目时我一般不用这种写法而是用 OpenCV 自己拆帧再逐帧喂给模型。4.2 逐帧处理的标准循环VideoCapture 与 VideoWriter 配合自己拆帧的好处是每一帧的结果都在你手里你可以做目标跟踪、计数、姿态判断或者自定义画框逻辑。核心是把 OpenCV 的读取循环和 ultralytics 的推理结果拼在一起下面是一个完整可跑的逐帧处理模板。import cv2 from ultralytics import YOLO model YOLO(yolov8n-pose.pt) cap cv2.VideoCapture(input_video.mp4) fps cap.get(cv2.CAP_PROP_FPS) width int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fourcc cv2.VideoWriter_fourcc(*mp4v) out cv2.VideoWriter(output_video.mp4, fourcc, fps, (width, height)) frame_count 0 while cap.isOpened(): ret, frame cap.read() if not ret: break frame_count 1 results model(frame, conf0.5, devicecpu) annotated results[0].plot() out.write(annotated) # 处理进度提示 if frame_count % 50 0: print(f已处理 {frame_count} 帧) cap.release() out.release() print(f视频处理完成共 {frame_count} 帧)这段代码里值得说明的参数有三个fourcc 用 mp4v 而不是 avc1 是因为 OpenCV 自带的 H.264 编码器支持不完整mp4v 兼容性最好代价是输出文件体积略大VideoWriter 的尺寸必须和输入帧尺寸一致否则 write 会静默失败这是最常见的坑devicecpu 是我故意写的方便没显卡的人直接跑有 GPU 改成 0 会让处理速度快一个数量级。4.3 性能平衡策略跳帧、降分辨率、批处理逐帧推理在 CPU 上处理 720p 视频nano 模型大概每帧需要 80 到 150 毫秒视频实际帧率可能只有 7 到 10 帧每秒实时性不够。三个常用的优化手段第一是跳帧处理。人体姿势识别任务里相邻两帧的骨架变化很小没必要每帧都推理。每 3 帧推理一次中间两帧直接复用上一帧的骨架数据处理速度基本可以翻三倍。代价是快速动作下骨架会比画面慢半拍。inference_interval 3 # 每 3 帧推理一次 last_keypoints None while cap.isOpened(): ret, frame cap.read() if not ret: break frame_count 1 if frame_count % inference_interval 0: results model(frame, conf0.5) last_keypoints results[0].keypoints.data else: # 中间帧不推理沿用上一帧的骨架 if last_keypoints is not None: pass # 这里可以执行基于骨架的自定义逻辑第二是降分辨率。把输入帧 resize 到 640 甚至 416 宽度再喂给模型速度提升立竿见影代价是远距离小目标容易漏检。适用于监控画面里人比较大的场景。第三是批处理。如果视频是离线处理不是实时流可以把多帧拼成一个 batch 传给 model.predict在 GPU 上能显著提升吞吐量但 CPU 上收益不大。实际项目中我一般是「跳帧 降分辨率」组合用实时性要求不高的场景直接逐帧搞定。5. 常见问题避坑模型下载、显存、关键点索引和视频编码5.1 模型首次加载卡住不动几十分钟没反应现象执行 YOLO(yolov8n-pose.pt) 后程序停在加载阶段不报错也不继续像死了一样。原因ultralytics 在本地缓存目录找不到权重文件触发了自动下载下载过程没有进度条展示网络慢或者被墙时就像卡死一样。解决自己手动下载权重文件放到指定缓存目录。具体做法是用浏览器直接访问 ultralytics 的 GitHub release 页面下载 yolov8n-pose.pt然后放到 ~/.cache/ultralytics 目录下。不放缓存目录也行直接把模型文件放在项目里用绝对路径加载 YOLO(/your_path/yolov8n-pose.pt)这样最可控也方便后续换不同规格的模型文件。5.2 GPU 显存溢出或程序越来越慢LZM 爆红现象单张图片推理正常跑视频时程序显存占用不断增长最后报 CUDA out of memory或者不报错但速度越来越慢。原因循环里没有释放上一帧的张量引用推理结果累积在内存里常见情况是 results 列表不断追加没有清空。解决确认显存是否真的不够用yolov8n-pose 在 640 分辨率下单帧推理只需约 2GB 显存如果报 OOM优先查代码里有没有把历史帧的 results 全部保存下来。处理逐帧视频时每次循环结束把不再用的变量置 None或者用 del results再配合 torch.cuda.empty_cache() 主动释放缓存。import torch # 在每一帧推理后调用 del results torch.cuda.empty_cache()如果还不行就把输入分辨率从默认 640 降到 480或用 nano 模型显存占用能降一半。5.3 关键点画出来位置错乱左右肩膀和左右肘对不上现象单张图片推理结果看起来骨架线乱七八糟比如左肘连线到了右手腕或者自己用 keypoints 坐标画点时位置和画面明显对不上。原因COCO 17 点的索引是固定的但你从代码里取坐标时把索引写错了。常见误区是想当然地认为 0 是左肩、1 是右肩——实际 0 是鼻子。另一个原因是没有乘缩放系数输入给 model 前你把图片 resize 过但用坐标时忘了映射回原图尺寸。解决对照 17 点索引表逐个验证打印出坐标后用 OpenCV 在图上画圆点核对位置不要靠猜。涉及 resize 时保存原图尺寸用 (原图宽/输入宽) 和 (原图高/输入高) 两个缩放系数把关键点坐标换算回去。5.4 视频推理输出文件打不开或只有几帧现象模型跑完了输出 video 文件播放器打不开或者文件只有开头几帧后面全黑。原因VideoWriter 的编码器选择不对或者写入帧的尺寸和初始化时不一致。mp4v 编码器写出的文件在部分播放器上兼容性差。解决换 fourcc 用 avc1 配合 GPU 编码器或者输出用 .avi 格式配 MJPG 编码器兼容性最好。另外确认 write 的帧尺寸和 VideoWriter 初始化尺寸完全一致一旦不一致OpenCV 不会报错但写入会失败最终文件损坏。工程里我会在写入前打印 frame.shape 对照检查。5.5 虚拟环境装完 import 报错提示某底层库不匹配现象pip install ultralytics 装好后import 时报 DLL load failed、numpy 版本冲突或者 cv2 属性不存在。原因Python 版本过老或者本地已有旧版 numpy、opencv 与新版本冲突Windows 上常见的是 torch 的 CUDA 运行时 DLL 路径问题。解决优先在虚拟环境里重装不要用系统 Python锁定依赖版本安装用 pip install ultralytics8.2.0 这类明确版本号避免装到刚发布的新版本踩兼容问题。若报 numpy 相关错误用 pip install numpy --upgrade 强制升级到 1.26 以上的版本。6. 验证与进阶把关键点坐标用起来前先做三个自检模型跑通只是起点真正把它集成进业务前我建议先做三个自检能省后面大量排查时间。第一个自检是确认关键点坐标的比例关系。找一张人站在画面中间的图片打印出左肩索引 5和右肩索引 6的坐标计算两点连线的水平距离再和鼻子索引 0到左肩的垂直距离做比较正常人肩宽大约是头高的两倍左右。如果这个比例明显失调说明你用的坐标不是像素坐标而是归一化坐标或者模型加载错了。第二个自检是置信度分布检查。截取视频里连续 30 帧统计每帧 17 个关键点的平均置信度如果平均置信度长期低于 0.4说明输入画面里人太小或者模糊需要调大输入分辨率而不是模型参数。第三个自检是稳定性验证同一段视频连续跑两次逐帧对比关键点坐标是否有明显差异正常情况下两次结果应该完全一致如果不一致说明代码里可能用了随机采样或者输入图片有随机增强这对推理来说属于隐患。自检通过后一个实用的进阶方向是根据关键点坐标做简单的姿态判断。比如检测摔倒最直接的特征是头部关键点鼻子或眼睛的 y 坐标突然大幅下降同时髋部索引 11 和 12的 y 坐标变化不大且这一状态持续了若干帧。从三个关键点的夹角计算关节弯曲程度也是健身计数类应用的常见起点。import math def calculate_angle(a, b, c): 计算三点之间的夹角a 和 c 是端点b 是顶点 ab (a[0] - b[0], a[1] - b[1]) bc (c[0] - b[0], c[1] - b[1]) dot ab[0] * bc[0] ab[1] * bc[1] norm_ab math.sqrt(ab[0] ** 2 ab[1] ** 2) norm_bc math.sqrt(bc[0] ** 2 bc[1] ** 2) if norm_ab 0 or norm_bc 0: return 0.0 cos_angle dot / (norm_ab * norm_bc) cos_angle max(-1.0, min(1.0, cos_angle)) return math.degrees(math.acos(cos_angle)) # 例计算右肘索引 8的弯曲角度 # right_shoulder keypoints[6][:2], right_elbow keypoints[8][:2], right_wrist keypoints[10][:2]这段代码后面可以接业务逻辑比如肘关节角度在 15 到 35 度之间且持续 20 帧以上判定为手臂弯曲动作做俯卧撑计数的基础就是它。我的血泪经验是不管你接了多复杂的业务逻辑先强制自己走一遍「单张图坐标自检 — 置信度过滤 — 连续帧稳定性验证」这套流程再谈功能开发否则模型换一个版本、换一个场景你的坐标系就全乱了。从那以后我每次接新的姿态识别需求都先把这套自检脚本跑一遍再动业务代码。希望帮到你。本文还有配套的精品资源点击获取