news 2026/10/4 22:18:21

人体姿势识别YOLOv8预训练模型:从环境搭建到关键点提取

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
人体姿势识别YOLOv8预训练模型:从环境搭建到关键点提取

简介:这是一份可直接运行的YOLOv8人体姿势识别预训练模型资源,面向Python开发者和计算机视觉初学者,解决从零搭建姿势识别环境门槛高的问题。包内含1个pt格式的yolov8s-pose模型文件、1个完整Python运行脚本及2张效果展示图片,压缩包约31.33MB,共4个文件。该资源既可直接用于图片或视频中的人体关键点检测与姿态估计,也可作为基础模型进行迁移学习或进一步微调。内置效果示例中,唐朝诡事录经典站位图的识别结果清晰标注了面部和躯体关键点。模型基于公开人体姿势数据训练,能够识别站立、坐下、跑步、跳跃等常见姿势,并输出各身体部位的位置关系,适用于运动动作分析、康复训练监测、虚拟现实交互等场景。已有559人浏览学习,适合希望快速上手姿态识别项目、或需要轻量级预训练权重开展实验的开发者。

1. 人体姿势识别YOLOv8预训练模型:拿到手先跑通一张图和一个视频

人体姿势识别这两年从“实验室玩具”变成了真正能落地的工程组件,核心原因是YOLOv8预训练模型的普及。它不像早期姿态估计算法需要你自己从零训练一个几十层的卷积网络,而是官方直接把在COCO数据集上训练好的pose权重开放出来,你只需要写十几行Python运行代码,就能从一张图片或一段视频里拿到每个人的骨架关键点:鼻子、眼睛、肩膀、手肘、手腕、髋、膝盖、脚踝,共17个点。这个流程非常适合快速验证业务想法,比如跌倒检测、动作计数、运动姿势纠正。

但实际跑起来时,我见过太多人卡在第一关:代码还没开始写,环境先翻车;环境装好了,权重下载又超时;好不容易跑通了,关键点画出来却是歪的。所以这篇笔记不打算讲姿态估计的数学原理,而是按一条“能直接复现”的路径走:先搭环境,再把图片和视频推理跑通,然后学会读取关键点坐标,最后把几个最容易踩坑的地方一次性说掉。读完你手里应该有一套真正可运行、可改参数、可接到自己项目里的YOLOv8人体姿势识别代码。

2. 搭建Python推理环境:安装Ultralytics与预训练权重的一次性准备

2.1 创建虚拟环境并安装ultralytics:CPU也能跑姿势识别的基础

无论你用的是Windows、macOS还是Linux,我都建议先把Python环境隔离出来,不要直接往系统Python里乱装包。YOLOv8姿势识别依赖的库有好几个,互相之间版本错位是家常便饭,虚拟环境是成本最低的后悔药。

python -m venv pose_env source pose_env/bin/activate # Windows下执行: pose_env\Scripts\activate pip install --upgrade pip pip install ultralytics opencv-python

这段命令的意思很直白:先创建名为pose_env的虚拟环境,然后用source激活它;升级pip后,安装ultralytics和opencv-python。ultralytics是YOLOv8官方的Python推理库,里面封装了检测、分类、分割、姿态估计四个方向的模型加载和推理接口;opencv-python则负责读取图片、读视频、画结果。这里有一个容易被忽略的点:ultralytics会自动依赖torch、torchvision、numpy等核心库,所以你不用单独去装torch。pip会拉取CPU版本的PyTorch,CPU机器也能直接跑,只不过速度慢一些,后面我会专门讲速度问题。

装完之后,先验证一下安装结果:

python -c "from ultralytics import YOLO; print('ok')"

能打印ok,说明环境这关过了。如果这里报ModuleNotFoundError,基本就是pip安装没完成,或者你当前激活的虚拟环境和运行python命令的终端不是同一个,这种细节最容易让人摸不着头脑。

2.2 下载人体姿势识别预训练模型:yolov8n-pose.pt和yolov8x-pose.pt怎么选

YOLOv8官方给人体姿势识别准备了多个尺寸的预训练模型,文件名的规律是yolov8{尺寸}-pose.pt。你不需要从零训练,直接下载这些权重文件就能推理。常见尺寸从快到慢排列:nano、small、medium、large、xlarge,分别对应n、s、m、l、x。

模型文件体积范围推理速度关键点精度适用场景
yolov8n-pose.pt较小最快可用实时摄像头、CPU调试
yolov8s-pose.pt中等较快较好视频处理、普通项目
yolov8m-pose.pt中等偏大较慢好离线批处理、精度优先
yolov8x-pose.pt很大最慢最好学术实验、服务器端

我的建议是:第一次跑通流程用nano,也就是yolov8n-pose.pt,因为下载快、CPU也能拖得动;等流程验证没问题了,再根据你的硬件条件换s或m。不要一上来就追x,那会让你以为是自己电脑坏了。

权重文件怎么拿?最简单的方式是不用管,YOLO("yolov8n-pose.pt")这段代码会在第一次运行时自动下载到当前目录。如果网络不稳定导致下载失败,就手动用浏览器打开Ultralytics的GitHub release页面,找到pose模型权重下载后放到代码同级目录。手动下载后,YOLO类的构造函数会优先加载本地同名文件,不会再触发网络请求。网络慢的解决办法是断点续传下载工具或换一个空闲时段,不要反复删掉重试,那会一直浪费你时间。

2.3 用三分排查法确认模型加载成功:权重文件、依赖库、第一张测试图

很多人代码明明和网上一样,结果一运行就报“Model file not found”或“RuntimeError”。这不是模型玄学,是环境细节没对齐。我按三个维度排查:

第一,确认当前目录下有没有.pt文件,并且文件大小是几十MB以上。如果只有几KB,说明下载到的是一个HTML错误页面,直接删掉重新下载。第二,确认依赖库完整。运行下面这段Python代码,能打印出模型网络结构就说明加载成功:

from ultralytics import YOLO model = YOLO("yolov8n-pose.pt") print(model)

如果这里抛出AttributeError: 'NoneType' object has no attribute 'yaml',一般是PyTorch和ultralytics版本不匹配,解决办法是统一升级到最新版:pip install -U ultralytics。第三,准备一张包含完整人体的测试图片,越普通越好,不要逆光、不要半身、不要多人重叠。把图片命名为test.jpg放到代码目录,作为后续所有验证的基准。

3. 图片与视频的人体姿势识别:完整可运行代码与参数拆解

3.1 图片推理:cv2读图、模型预测、关键点可视化

先跑通最简图片推理,这是整个姿势识别的地基。下面这段代码可以直接复制运行:

import cv2 from ultralytics import YOLO # 加载预训练模型,模型文件不存在时自动下载 model = YOLO("yolov8n-pose.pt") # 用OpenCV读图,读进来是BGR顺序,正好是模型训练时的内部格式 frame = cv2.imread("test.jpg") if frame is None: raise FileNotFoundError("图片读取失败,先检查test.jpg是否正确放在当前目录") # predict返回一个Results列表,列表长度等于输入图片数量 results = model.predict(frame, conf=0.5, iou=0.45) # 取第一张图的结果,plot()会把检测框、关键点、骨骼连线都画到图上 annotated = results[0].plot() cv2.imwrite("output.jpg", annotated) print("检测到的人数:", len(results[0].boxes))

逻辑说明:model.predict内部会自动完成图像缩放、归一化、前向推理、非极大值抑制和后处理,你不用自己预处理,也基本不用碰黑匣子内部的东西。results[0].plot()是YOLOv8封装好的可视化方法,会返回一张新图像,原图不会改动。最后用cv2.imwrite保存,画出来的骨骼图就在output.jpg里。

参数说明:conf是置信度阈值,0.5是保守值,低于这个分值的检测结果会被丢弃。调低到0.3能多召回一些模糊人体,但噪声也多;调高到0.7能减少误检,但可能漏掉侧身、遮挡的人体。iou是NMS交并比阈值,多人密集重叠场景建议调到0.3,普通场景保持0.45即可。

3.2 视频推理:VideoCapture逐帧处理与输出保存

视频推理本质上就是把每一帧图片送入模型,再把结果写进一个新的视频文件。代码如下:

from ultralytics import YOLO import cv2 model = YOLO("yolov8n-pose.pt") cap = cv2.VideoCapture("input.mp4") if not cap.isOpened(): raise IOError("视频打开失败,先确认文件路径") fps = int(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") writer = cv2.VideoWriter("output.mp4", fourcc, fps, (width, height)) while True: ret, frame = cap.read() if not ret: break results = model.predict(frame, conf=0.5, verbose=False) frame = results[0].plot() writer.write(frame) cap.release() writer.release()

这里有两个容易犯的错。第一个是VideoWriter必须传入原始视频的fps和分辨率,如果你写死成(1280, 720)而原始视频是1920x1080,生成的视频要么报错要么画幅变形。我用cap.get读出来,就是为了避免这种手抖。第二个是model.predict默认会在终端打印一轮进度条,在逐帧循环里会刷屏,所以设置verbose=False关闭它。

视频推理速度通常慢于视频帧率,比如一个30fps的视频,CPU上只能做到每秒处理5帧,这是正常现象,不表示代码卡死。如果急着看效果,先拿一段短视频测试,不要直接丢一个半小时的电影进去。

3.3 必调参数:conf、iou、device、verbose背后的效果差异

Ultralytics还提供了一套命令行等效操作,适合不想写Python代码的时候快速验证:

yolo pose predict model=yolov8n-pose.pt source=./input.mp4 save=True

这行命令会生成runs/pose/predict/目录并保存结果。命令行对我来说主要用于确认“模型在这台机器上到底能不能跑”,真正接入业务我还是用Python,因为要拿关键点坐标做后续计算。

Python代码里最值得调的四个参数,一个是device:不写就自动选择GPU,没有GPU就用CPU。如果你想强制用CPU,写成device="cpu";多卡机器可以写device=[0,1]。第二个是imgsz:控制输入图片缩放尺寸,默认640。CPU上跑视频可以降到320,速度快一倍以上,但小目标关键点会变糊,我用这个值只在测试性能时用。第三个是vid_stride:这是给视频输入用的跳帧参数,设为2表示每隔一帧推理一次,能显著提速。第四个是classes:如果你只想检测人,其实pose模型只负责检测人,这个参数用处不大,但可以帮你避免误用其他模型。

4. 关键点数据解读:从17个点坐标到自定义骨骼图

4.1 YOLOv8 pose的输出结构:boxes、keypoints、keypoints_xy

很多人跑通了可视化,却不知道如何取出“某个人的左手腕坐标”。接下来要打开YOLOv8推理结果的黑匣子,看清数据结构:

import torch result = results[0] boxes = result.boxes.xyxy # 每个人体矩形框,格式为[x1, y1, x2, y2]像素坐标 keypoints = result.keypoints.data # 关键点张量,形状[N, 17, 3] print("人体框数量:", boxes.shape[0]) print("关键点形状:", keypoints.shape)

keypoints.data的形状是[N, 17, 3],N是一张图中检测到的人数,17是关键点数,3代表每个点的(横坐标, 纵坐标, 置信度)。这里要特别注意坐标单位:它已经是原始图像像素坐标,不是归一化坐标。如果你用的是result.keypoints.xy,得到的是[N, 17, 2]的像素坐标;如果用的是result.keypoints.xyn,则是归一化坐标,范围在0到1之间。大多数后续计算,比如画框、量距离,直接用keypoints.data即可。

17个关键点的顺序是COCO姿态约定的,官方文档里是固定的:0鼻子、1左眼、2右眼、3左耳、4右耳、5左肩、6右肩、7左肘、8右肘、9左腕、10右腕、11左髋、12右髋、13左膝、14右膝、15左踝、16右踝。这里说的左右是人物自己的左右,不是画面中的左右。画面左侧人的右手,对应索引10,而不是9。

4.2 坐标换算:从归一化坐标到图像像素坐标的落地

你拿到的结果可能来自多种渠道,有的代码给你归一化坐标,有的给你像素坐标。我一般统一转成像素坐标再处理:

import numpy as np xy = result.keypoints.xy.cpu().numpy() # 像素坐标,形状[N, 17, 2] conf = result.keypoints.conf.cpu().numpy() # 每个关键点置信度,形状[N, 17] for person_id in range(xy.shape[0]): nose = xy[person_id][0] left_shoulder = xy[person_id][5] left_elbow = xy[person_id][7] left_wrist = xy[person_id][9] print(f"第{person_id}人 左手腕坐标: {left_wrist}, 置信度: {conf[person_id][9]:.2f}")

这里使用.cpu().numpy()是因为PyTorch张量默认可能放在GPU上,直接转numpy会报类型错误。在CPU环境上,你可能不需要.cpu(),但我建议留着,它能让代码在GPU和CPU机器之间无缝切换。

还有一个细节:置信度为0或接近0的关键点,表示模型没能在该位置找到关节,通常是因为遮挡、身体出画或动作幅度过大。这类点不能直接拿来算角度,否则结果会离谱。

4.3 为业务场景接后处理:算角度、画骨骼、统计人数

拿到关键点坐标之后,最常用的动作是计算关节角度,比如判断一个人有没有举手、有没有蹲下。以左臂肘关节角度为例,用肩、肘、腕三个点:

import math def calc_angle(a, b, c): ba = [a[0] - b[0], a[1] - b[1]] bc = [c[0] - b[0], c[1] - b[1]] dot = ba[0] * bc[0] + ba[1] * bc[1] norm_ba = math.hypot(ba[0], ba[1]) norm_bc = math.hypot(bc[0], bc[1]) cos_theta = dot / (norm_ba * norm_bc + 1e-6) cos_theta = max(-1.0, min(1.0, cos_theta)) return math.degrees(math.acos(cos_theta)) left_angle = calc_angle(left_shoulder, left_elbow, left_wrist) print("左肘弯曲角度:", left_angle)

这段角度计算在运动检测里很常见,但要记住前提:三个关键点的置信度都足够高,比如都大于0.5。如果腕点置信度接近0,这个角度就是瞎算。统计人数更简单,直接取boxes的行数,就是当前帧的人体数量。你可以把这些后处理逻辑放进一个函数,传入result,返回自定义的骨架图或JSON数据,这样姿势识别就能真正嵌进你的业务了。

5. 姿势识别避坑手册:5个让新手当场翻车的经典问题

5.1 权重下载超时或报403:手动下载文件是最后的后悔药

现象:第一次运行YOLO("yolov8n-pose.pt"),程序卡在Downloading进度条,最后报超时,甚至报HTTP 403。

原因:Ultralytics自动下载是从GitHub Release拉取,网络状况不好时经常断流;如果公司网络或校园网对GitHub做了限制,403是常见结果。这跟你的Python代码没有关系,纯粹是网络访问问题。

解决:别反复删文件重试,直接用浏览器打开Ultralytics官方GitHub发布页,找到带-pose.pt的文件下载,保存到当前代码目录。下载后确认文件大小是几十MB,不是几KB的HTML错误页。之后再运行程序,YOLO类会直接加载本地文件,不再走网络。如果你下载下来的是一个压缩包或重命名奇怪的文件,手动改成yolov8n-pose.pt即可。

5.2 CPU推理慢到没法用:不是代码问题,是设备与模型不匹配

现象:用yolov8x-pose.pt在CPU上跑视频,每帧处理时间超过两秒,画面像幻灯片。

原因:x模型参数量比n模型大一个数量级,CPU算力根本扛不住;而model.predict默认使用imgsz=640,进一步放大了计算量。

解决:换用yolov8n-pose.pt,并把推理参数改为imgsz=320,同时开启vid_stride=2跳帧。这三招合起来,CPU上能提升好几倍速度,代价是关键点在小目标上会有误差。如果你的应用场景是离线批处理,比如晚上统一处理一批视频,慢一点也可以接受;如果是实时交互,建议要么接受低分辨率,要么上带GPU的机器。在我自己的项目里,CPU只用来做开发和验证,生产环境一定上GPU。

5.3 视频路径带中文打不开:OpenCV的编码问题让人头大

现象:cv2.VideoCapture("测试视频.mp4")返回isOpened()为False,但是把文件名改成test.mp4就完全正常。

原因:Windows下OpenCV的VideoCapture底层调用Video for Windows接口,对中文路径的支持非常差,这算是OpenCV的历史遗留问题。

解决:最简单的方法是把视频文件复制一份,改成英文路径和英文文件名,这也是我一直在用的做法。如果你必须保留中文路径,可以在代码里先用os.chdir()切到视频所在目录,再用相对文件名打开:

import os os.chdir("D:/data/动作视频") cap = cv2.VideoCapture("demo.mp4")

顺便说一句,图片读取用cv2.imread对中文路径的宽容度稍高,但也不保证所有环境都能读,你最好统一用英文路径,这能省掉很多莫名的麻烦。

5.4 关键点错位或抖动:问题多半出在前处理而非模型

现象:同一段视频里,一个人的手肘坐标在相邻帧之间来回跳,看起来骨骼在疯狂抽搐。

原因:模型本身是逐帧独立推理的,天然没有时间一致性。当某个关键点置信度不高、人体重叠或动作过快时,不同帧的预测点会漂移。另一个常见原因是分辨率太低,小尺寸下关节位置本身就不稳定。

解决:先调高conf到0.6,过滤掉置信度低的关键点;再换用更大的模型,比如s或m,以提高关节定位精度。如果还抖,就在后处理里做一阶低通滤波,对关键点坐标做时间平滑:

def smooth_point(prev, cur, alpha=0.4): return prev * alpha + cur * (1 - alpha)

这里alpha控制平滑强度,0.4表示保留40%的历史位置,越小越平滑但延迟越大。对实时性要求高的场景,alpha别超过0.5,否则动作会变得滞后。这个平滑方法是通用思路,不是Ultralytics的特有功能。

5.5 摄像头画面频闪或卡顿:VideoCapture和线程的配合问题

现象:用摄像头实时跑姿势识别,画面一卡一卡,帧率极低,感觉像PPT。

原因:普通的cap.read()是同步阻塞的,模型推理一帧可能要几百毫秒,读摄像头也跟着阻塞,导致画面延迟越来越大。

解决:要么降低摄像头分辨率,比如cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)、cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480);要么更彻底一点,单独开一个线程不断读帧,主线程拿最新帧做推理。下面是一个最小线程方案:

import threading import cv2 cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) lock = threading.Lock() latest_frame = None def reader(): global latest_frame while True: ret, frame = cap.read() if not ret: break with lock: latest_frame = frame.copy() t = threading.Thread(target=reader, daemon=True) t.start()

你用主线程从latest_frame取帧推理,就能把“读摄像头”和“推理”解耦,画面流畅度提升明显。注意加锁保护latest_frame,否则多线程访问同一变量容易出不可预料的崩溃。

6. 再进一步:把姿势识别跑进实时摄像头,并用跳跃动作做实测

当你上面的图片和视频推理都稳定跑通后,下一步自然是想把它接到摄像头做实时演示。这里有一个很实在的技巧:只画关键点和骨架,不画检测框。YOLOv8自带的plot()会把检测框、置信度文本、关键点、连线全画出来,视觉上很热闹,但文本框和检测框会占据不少绘制时间。实时场景里,我习惯自己画骨骼,把绘制开销压到最低:

skeleton_edges = [ (5, 6), (5, 7), (7, 9), (6, 8), (8, 10), (5, 11), (6, 12), (11, 12), (11, 13), (13, 15), (12, 14), (14, 16) ] def draw_skeleton(frame, xy): for person_id in range(xy.shape[0]): pts = xy[person_id] for idx1, idx2 in skeleton_edges: x1, y1 = pts[idx1] x2, y2 = pts[idx2] cv2.line(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) return frame

把上一帧的关键点保存下来,下一帧如果检测到同样数量的人,就把imgsz临时降到320跑,这样能在实时场景里挤出更多帧。当画面里的人数变化时,再自动切回640,保证检测效果稳定。这个动态分辨率技巧是我在落地项目里最常用的性能优化手段,效果比调很多模型参数都明显。

验证方法上,我建议找一个动作幅度大的场景,比如原地跳跃。你站在摄像头前连续跳十次,记录每一帧的左膝盖弯曲角度,画成一条波形。正常情况下,起跳和落地瞬间角度有明显峰值,腾空阶段角度变化平滑且稳定。如果波形接近一条直线或者数值严重跳变,说明你的关键点置信度阈值太低或模型尺寸太小,应该回头调整conf和模型选型。这种验证方式不需要额外的标注数据,几分钟就能判断当前方案是否靠谱。

最后说一个我自己的教训:一开始总想把参数一次调到完美,结果反复改模型、改阈值,反而忘了先固定测试视频。后来我练成一个习惯,永远准备同一段包含单人、多人、遮挡、快速动作的测试视频,任何改动都拿它验证。这样踩坑的定位速度快很多,也避免被短期运气误导。人体姿势识别YOLOv8预训练模型这条路,真正难的不是模型,而是你愿意把细节一点点抠清楚。希望这篇笔记能帮你少走一段弯路。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/4 22:17:26

Flutter 鸿蒙化实战:flutter_tts 适配 OpenHarmony,文本转语音

Flutter 鸿蒙化实战:flutter_tts 适配 OpenHarmony## 前言随着鸿蒙生态的快速发展,越来越多的 Flutter 应用需要适配 OpenHarmony 平台。但生态早期,大量常用三方库只有 Android / iOS 实现,鸿蒙侧只能自己造轮子。为了解决这个问…

作者头像 李华
网站建设 2026/10/4 22:04:30

5分钟手把手教你开发一个MCP服务:从零到接入TaoToken统一API通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/4 21:57:15

C# Winform实现HTTP POST提交JSON并解析响应完整指南

简介:基于Winform的HTTP POST JSON通信示例,面向需要快速实现客户端与服务端JSON交互的C#开发者。程序通过HttpClient提供PostJsonAsync异步方法,配合Newtonsoft.Json完成序列化与解析,同时区分成功与失败响应,便于直接…

作者头像 李华