ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

YOLOv8-pose多人姿态估计与关键点检测工程实战

YOLOv8-pose多人姿态估计与关键点检测工程实战

简介:面向人体姿态关键点检测学习与实践的完整项目包,围绕YOLOV8-pose模型展开,适合计算机视觉初学者、课程设计与毕业设计开发者,以及需要快速复现姿态估计实验的研究者。包内提供可直接跑通的训练、推理与验证源码,配套人体关键点标注数据集、预训练权重和依赖配置,省去从零搭建网络、整理标注文件与调试运行环境的重复劳动。压缩包共1369个文件,约89.04MB,以jpg图像、md说明文档、txt标注与配置、py脚本为主体,辅以yaml训练参数、pt权重、json记录及ipynb、png可视化结果,覆盖数据准备、模型训练、日志记录与使用文档等环节。已有6223人学习,反映出姿态识别与关键点检测方向具有较高关注度。读者可据此完成关键点检测模型的训练、评估与推理,理解数据增强、损失函数设计和预训练迁移等流程;README与脚本也有助于快速复现结果、排查环境配置和运行问题。

1. 姿态关键点检测落地:为什么我选 YOLOV8-pose 而不是先啃 HRNet

上个月帮朋友做一个健身动作纠偏的小工具,需求很朴素:摄像头对着人,能把肩、肘、腕、髋、膝、踝这些关键点标出来,判断深蹲有没有塌腰、手肘有没有外翻。第一反应是去找姿态识别里口碑好的 HRNet 系列,结果光是把预测热图转回原图坐标、再对齐翻转和缩放这一套后处理,就调了大半天,玄学得很。后来换成 YOLOV8-pose,一个模型文件丢进去,predict出来直接是归一化的关键点坐标,十七个点带置信度,画骨架、算角度、判姿态全都能接上。这份源码包做的就是这件事——一套带数据集、能直接跑通的姿态关键点检测工程,适合想快速把姿态识别接进自己业务、又不想在模型复现上耗掉一周的开发者。下面按“它能干什么、目录长什么样、怎么跑、怎么改”讲透。

2. 项目定位与技术选型:单阶段多人姿态估计的取舍

2.1 它到底解决什么问题

这个项目的核心任务是多人 2D 姿态估计(Multi-Person Pose Estimation):给一张图或一帧视频,输出画面里每个人的 17 个 COCO 标准关键点(鼻、左右眼、左右耳、左右肩、左右肘、左右腕、左右髋、左右膝、左右踝),每个点带 x、y 坐标和置信度。注意“多人”两个字很关键——早期很多姿态方案是“先检测人框、再对每个人单独跑一遍关键点”,两阶段串行,人一多帧率就崩。YOLOV8-pose 走的是单阶段路线:一次前向同时回归人框和该框内的关键点,N 个人就是 N 组输出,不额外多跑一遍网络。

从工程角度看,这个取舍非常划算。姿态估计在业务里很少是终点,通常是上游特征提取:健身纠偏要算关节角,行为识别要喂骨架序列,动画驱动要做重定向。这些下游任务真正在意的是“关键点稳不稳、延迟够不够低”,而不是“学术榜单上 PCKh 高 0.3 个点”。单阶段模型在 640×640 输入下,中端显卡能跑到实时甚至超实时,CPU 上降分辨率也能凑合用,这是它落地的最大底气。

2.2 为什么是 YOLOV8-pose 这套技术栈

把技术栈拆开看,其实是三层:

层次组成作用
骨干与颈部CSPDarknet 系列 backbone + PAN-FPN多尺度特征提取与融合
检测头解耦头,分类/框回归/关键点回归分支输出人框与 17 点热图式回归
训练与推理框架Ultralytics 封装(PyTorch 后端)数据加载、增强、损失、导出、预测一条龙

关键点在检测头里是这么处理的:对每个人框,模型回归 17 组(x, y, visibility),其中 x、y 是相对于该人框的归一化偏移,visibility 是该点是否可见的置信度。这种“框内相对坐标”的设计让模型不必在全图尺度上直接回归绝对坐标,收敛更稳,也让同一个模型天然支持多人——每个 anchor/query 只负责自己那个人。

提示:visibility不是“这个点在画面里被遮挡的概率”这么简单,它同时承担了“该点是否在图像边界内”的语义。做下游角度计算时,通常要把 visibility 低于阈值(比如 0.5)的点直接丢掉,否则会出现用低置信点算出来的诡异角度。

选型上还有两个现实考量。一是生态:Ultralytics 这套接口的训练、验证、导出(ONNX、TensorRT、OpenVINO)几乎是模板化的,换个部署环境不用重写推理逻辑。二是数据集门槛低:YOLO 格式的 pose 标注就是一个 txt 文件,每行一个人,类别 cx cy w h kx1 ky1 kv1 ... kx17 ky17 kv17,全部归一化。自己标几十张图就能微调,比 COCO-WholeBody 那种 133 点的重型标注友好太多。

2.3 源码包的目录骨架

拿到这种工程,我一般先tree一遍看结构。这个包的组织方式基本是“训练脚本 + 配置 + 数据集 + 推理示例”四块,典型布局如下:

yolov8-pose-project/ ├── ultralytics/ # 框架源码(含 cfg 与 nn 模块) │ ├── cfg/models/v8/ # yolov8-pose.yaml 等模型结构定义 │ └── nn/ # 骨干、颈部、检测头、损失实现 ├── datasets/ │ └── pose-demo/ │ ├── images/{train,val}/ │ ├── labels/{train,val}/ │ └── data.yaml # 数据配置:路径、关键点形状、类别名 ├── weights/ │ └── yolov8n-pose.pt # 预训练权重,用来做迁移学习起点 ├── train.py # 训练入口 ├── val.py # 验证入口 ├── predict.py # 图片/视频推理演示 └── requirements.txt

这个结构里最容易被忽视的是data.yaml,它决定了模型头部的输出维度。文件大致长这样:

# datasets/pose-demo/data.yaml path: ./datasets/pose-demo train: images/train val: images/val kpt_shape: [17, 3] # 17 个关键点,每个点 3 个值 (x, y, visibility) flip_idx: [0, 2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11, 14, 13, 16, 15] # 水平翻转时左右点的索引交换 names: 0: person

flip_idx是很多人第一次改数据集时会栽的地方——它用于数据增强里的水平翻转。如果你自己定义了 5 个关键点,却忘了同步改这个数组,训练时翻转增强会把“左肩”的标签贴到“右肩”位置上,模型学出来的骨架会左右乱窜,loss 看着在降,实际预测全是错的。这个坑后面还会细说。

3. 跑通流程:从环境到第一张骨架图

3.1 环境准备与依赖安装

这套工程对环境的要求不算苛刻,Python 3.8 以上、PyTorch 1.8 以上就能起步。GPU 训练建议 CUDA 11.x 配对应的 torch 版本,CPU 也能跑但训练会慢到让人怀疑人生。我一般的做法是单独开一个 conda 环境,避免和机器上其他项目的 torch 版本打架:

# 创建并激活环境 conda create -n pose python=3.10 -y conda activate pose # 先装 torch(按自己的 CUDA 版本选对应命令,这里以 CUDA 11.8 为例) pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 再装工程依赖 pip install -r requirements.txt # requirements 里通常包含 ultralytics、opencv-python、numpy、pyyaml、tqdm

安装完先做一次体检,确认 torch 能吃上 GPU:

python -c "import torch; print(torch.__version__, torch.cuda.is_available())"

输出里True才算 GPU 就绪。如果显示False,多半是装成了 CPU 版 torch,或者驱动版本和 CUDA runtime 不匹配,这时候别急着往下跑训练,先在nvidia-smi里核对驱动支持的 CUDA 上限。这个检查看着多余,但我见过太多次训练跑了两小时才发现一直在 CPU 上爬的情况。

3.2 数据集组织与标注格式核对

数据集这块,工程里自带了一份演示数据,目录结构在data.yaml里已经声明好了。跑通前必须核对两件事:图片和标签同文件名、同相对路径,标签是 YOLO pose 格式的 txt。

标注文件里每一行的格式是这样的:

# labels/train/0001.txt # class cx cy w h x1 y1 v1 x2 y2 v2 ... x17 y17 v17 0 0.512 0.603 0.284 0.791 0.501 0.312 2 0.487 0.305 2 ... 0.402 0.881 1

所有数值都是归一化到 [0,1] 的(相对于图片宽高),关键点坐标是相对于整张图而不是人框——这点和推理阶段的输出不同,推理输出是相对框的,后处理时框架会自动转回去,但如果自己写标注转换脚本,这是最容易搞混的一处。

v的取值一般是 0/1/2:0 表示未标注,1 表示标注但被遮挡,2 表示可见且标注。如果你的标注工具只输出 0/1,也问题不大,但flip_idx和kpt_shape必须和实际点数严格一致。

正确性校验有个很实用的小脚本,把标签还原成骨架画到图上,肉眼过一遍:

import cv2 import numpy as np IMG = "datasets/pose-demo/images/train/0001.jpg" LBL = "datasets/pose-demo/labels/train/0001.txt" # COCO 17 点的骨架连接对,用来连线可视化 SKELETON = [(5,7),(7,9),(6,8),(8,10),(5,6),(5,11),(6,12),(11,12), (11,13),(13,15),(12,14),(14,16),(0,1),(0,2),(1,3),(2,4)] img = cv2.imread(IMG) h, w = img.shape[:2] for line in open(LBL): parts = np.array(line.split(), dtype=float) kpts = parts[5:].reshape(-1, 3) # 从第 6 个值起是 17*3 的关键点 pts = (kpts[:, :2] * [w, h]).astype(int) # 反归一化回像素坐标 for a, b in SKELETON: if kpts[a, 2] > 0 and kpts[b, 2] > 0: # 两端都有效才连线 cv2.line(img, tuple(pts[a]), tuple(pts[b]), (0, 255, 0), 2) for (x, y), v in zip(pts, kpts[:, 2]): if v > 0: cv2.circle(img, (x, y), 3, (0, 0, 255), -1) cv2.imwrite("check.jpg", img)

这段代码做了三件事:按行解析每个目标的标注、把关键点反归一化、按骨架连接对画线画点。参数上SKELETON是 COCO 标准连接关系,kpts[a, 2] > 0这个判断是为了跳过未标注的点,否则会在图上的 (0,0) 附近画出一堆乱线。跑完打开check.jpg,如果骨架是贴在人体上的,说明标注没问题;如果整个人是歪的或者骨架飘在别处,那基本是归一化基准错了(比如按人框而不是整图归一化)。

3.3 训练命令与关键参数

环境、数据都确认后,训练就是一条命令的事:

python train.py \ --model weights/yolov8n-pose.pt \ --data datasets/pose-demo/data.yaml \ --epochs 100 \ --imgsz 640 \ --batch 16 \ --device 0 \ --workers 4 \ --project runs/pose --name demo

几个参数我按重要性排一下:

  • --model:预训练权重起点。即使你的关键点数和 COCO 不同(比如只标 5 个点),也可以加载,框架会自动裁掉/重建头部,但骨干权重仍然有用,收敛比从零训快得多。
  • --imgsz:输入分辨率。640 是性能和精度的平衡点;远距离小目标多就上 960,但显存和延迟一起涨。
  • --batch:按显存调,OOM 就先减半,别硬撑。
  • --workers:DataLoader 进程数,Windows 上建议设小一点甚至设 0,否则容易卡死在多进程上。
  • --project/--name:输出目录,权重存runs/pose/demo/weights/best.pt,训练曲线、混淆矩阵、验证集预测图都在同目录下。

训练脚本里真正干活的部分一般是对框架 API 的封装,早期版本写法大致是这样:

from ultralytics import YOLO # 加载带 pose 头的预训练权重 model = YOLO("weights/yolov8n-pose.pt") # 开始训练,内部会读取 data.yaml 里的 kpt_shape 构建头部 results = model.train( data="datasets/pose-demo/data.yaml", epochs=100, imgsz=640, batch=16, device=0, workers=4, project="runs/pose", name="demo", # 姿态任务常用的增强开关 fliplr=0.5, # 水平翻转,依赖 data.yaml 的 flip_idx degrees=10.0, # 小幅旋转,应对拍摄角度 scale=0.5, # 随机缩放,提升尺度鲁棒性 mosaic=1.0, # 马赛克增强,前期提升明显 )

这里要点一下fliplr和flip_idx的联动关系:fliplr=0.5意味着每张图有一半概率被水平翻转,翻转时标签坐标要镜像(x -> 1-x),同时左右关键点的语义要对调(左肩变右肩)。框架靠data.yaml里的flip_idx完成后者。所以flip_idx不是可选装饰,它是增强正确性的前提。同理mosaic=1.0把四张图拼成一张,对小目标友好,但训练末段通常要关掉(框架默认最后 10 个 epoch 自动关闭),否则真实场景的构图分布和训练分布偏差会拉低最终指标。

3.4 推理与骨架可视化

训练完最爽的一步是看效果。工程里的predict.py一般会做图片、视频、摄像头三种输入的分支,核心调用只有几行:

from ultralytics import YOLO model = YOLO("runs/pose/demo/weights/best.pt") # 对单张图片推理,save=True 会把带骨架的结果图写到 runs/pose/predict 下 results = model.predict("test.jpg", imgsz=640, conf=0.4, save=True) for r in results: if r.keypoints is None: continue # keypoints.xy: (人数, 17, 2) 像素坐标; keypoints.conf: (人数, 17) 置信度 xy = r.keypoints.xy.cpu().numpy() conf = r.keypoints.conf.cpu().numpy() for person_xy, person_conf in zip(xy, conf): # 只保留置信度够高的点,避免下游算角度时用到垃圾数据 valid = person_conf > 0.5 print("有效关键点数:", valid.sum())

conf=0.4是人框的置信度阈值,不是关键点的;关键点置信度要单独在keypoints.conf里过滤。这两个阈值混用是新手高频翻车点:把人框阈值调得很高,结果远处的人整个被丢掉;或者只看人框置信度就直接拿所有关键点去算角度,被遮挡点的坐标其实是一团噪声。

推理速度上,yolov8n-pose在 640 输入、单张中端卡上通常是毫秒级到十几毫秒;换yolov8s/m精度涨一点、延迟也涨。做实时视频建议先用 n 版跑通链路,再按精度需求往上换型号,别一上来就上大模型然后抱怨卡。

4. 核心模块拆解:一个关键点是怎么被回归出来的

4.1 检测头里的关键点分支

框架的检测头在ultralytics/nn/modules/head.py里,pose 版本的头继承自检测头,多出一条关键点回归分支。结构上的关键点是:关键点不是独立预测的,而是绑定在每个人框上的。简化后的前向逻辑大致是:

# 伪代码,保留关键结构,省略了大量广播与形状处理 class PoseHead(nn.Module): def __init__(self, nc, kpt_shape, ch=()): super().__init__() self.nc = nc # 类别数,姿态任务通常就是 1(人) self.nk = kpt_shape[0] # 关键点数量,COCO 是 17 self.no = nc + 4 + self.nk * 3 # 每框输出: 类别 + 框4 + 关键点(17*3) # 三条并行分支:分类、框回归、关键点回归 self.cv2 = nn.ModuleList(...) # 分类 + 框 self.cv3 = nn.ModuleList(...) # 关键点 self.cv4 = nn.ModuleList(...) # 关键点可见性/精修 def forward(self, x): for i in range(self.nl): # 遍历 P3/P4/P5 三个尺度 cls_box = self.cv2[i](x[i]) # (B, 4+nc, H, W) kpt = self.cv3[i](x[i]) # (B, nk*3, H, W) # 关键点坐标用 sigmoid 约束到 [0,1],表示相对网格/框的偏移 kpt[..., 0::3] = kpt[..., 0::3].sigmoid() kpt[..., 1::3] = kpt[..., 1::3].sigmoid() # 第三维(visibility)不套 sigmoid,直接作为 logit 参与 BCE 损失

这段里最值得记住的是self.no = nc + 4 + self.nk * 3:它决定了每个预测位置输出多少维。你改关键点数量时,kpt_shape一变,这个维度自动跟着变,所以永远改data.yaml和模型 yaml 里的kpt_shape,不要去手改no。另外x、y走 sigmoid 是有意的——把坐标压进 [0,1],语义上是“相对该人框左上角的归一化偏移”,这让不同大小的目标共享同一套回归目标尺度,训练稳定得多。

后处理阶段,框架会把这些相对偏移乘上对应人框的宽高、再加上框左上角坐标,还原成原图像素坐标。这条链路藏在ops.py的kpt_decode一类函数里,平时不用碰,但排查“预测点整体偏移”类问题时,就得顺着这条链一路看下来。

4.2 姿态损失函数的三部分构成

训练姿态模型,loss 由三块加起来:框回归损失、分类损失、关键点损失。前两块和普通检测一致(CIoU + BCE),姿态特有的第三块是重点。关键点损失一般是OKS-based 的加权 BCE或者直接的坐标回归损失,实现里大致是:

# 简化示意:关键点损失的核心思想 # 1) 对每个 GT 关键点,找到负责它的预测点 # 2) 坐标用 L1/L2 回归,visibility 用 BCE # 3) 按 OKS 的 sigmoid 权重对不同关键点加权 loss_kpt = 0.0 for gt_kpt, pred_kpt, vis in zip(gt_kpts, pred_kpts, gt_vis): if vis == 0: # 未标注的点不参与坐标损失 continue loss_kpt += (pred_kpt - gt_kpt).abs().mean() loss_kpt = loss_kpt / max(vis.sum(), 1) # 按有效点数归一化 loss_vis = BCEWithLogits(pred_vis, (gt_vis > 0).float())

两个细节决定成败。第一,vis == 0的点必须 mask 掉,不然模型会被迫去拟合“未标注”的位置,等价于教它胡说。第二,归一化要按有效点数而不是总点数,否则一个大部分人只有半身可见的 batch,loss 尺度会忽大忽小,学习率都不好调。OKS 那套权重的作用是让眼睛、手腕这类小且难的点在总 loss 里占比合理,避免被肩髋这些大关节淹没。

4.3 数据增强对姿态任务的特殊处理

检测任务的增强搬到姿态上,核心矛盾是:任何几何变换都必须同步作用到关键点上,且左右翻转要处理语义交换。马赛克增强在姿态里尤其危险——四张图拼接后,原来的人可能被裁掉一半,关键点坐标随之越界,框架内部会做裁剪和过滤,但如果你自己改增强流程,一定要保证越界点被正确标记为不可见,而不是硬留在 [0,1] 之外。

常见的正确做法是:先算好图片的仿射矩阵,同时对图像做 warpAffine、对关键点做同一矩阵的坐标变换,再根据变换后坐标是否落在图内更新 visibility。翻转时按flip_idx交换点序并x -> 1 - x。这两步看似机械,但只要漏一步,训练集会悄悄变脏,loss 曲线照样好看,mAP 就是上不去——这类“黑匣子”式的指标异常,十有八九要回到增强代码里找。

4.4 验证指标怎么看

姿态任务的验证不能只看 mAP。工程val.py跑完会输出几类指标:框的 mAP50-95、以及基于 OKS 的关键点 AP。OKS(Object Keypoint Similarity)是姿态版的 IoU,按每个关键点的标注方差加权算相似度,再取平均。实际看的时候我会重点关注三件事:

一是AP 随 OKS 阈值的变化,如果 AP50 很高但 AP75 掉得厉害,说明点位普遍差几个像素,多半是输入分辨率不够或者小目标太多。二是分关键点看误差,手腕、脚踝通常是最差的,如果差得离谱,检查这几类点在训练集里的可见比例。三是看验证集的预测可视化图,框架会自动存一批,肉眼看骨架有没有系统性偏移(比如整体偏右下),有的话基本是坐标解码环节或标注归一化基准出了问题。

5. 常见问题排查:我踩过的五个坑

5.1 训练 loss 正常但预测骨架全乱

现象:训练 loss 平稳下降,验证指标看着也还行,但拿best.pt预测,骨架连到了错误的人身上,或者所有点挤在一小块区域。

原因:data.yaml里kpt_shape和模型 yaml 里的kpt_shape不一致,或者flip_idx长度与点数不匹配。框架在某些版本下不会直接报错,而是按较小维度截断,导致关键点顺序错位。

解决:训练前打印一次模型头的实际输出维度,和kpt_shape[0] * 3对一遍;flip_idx用脚本自动生成,COCO 17 点就用标准数组,自定义点数时手写并校验长度。

5.2 水平翻转增强后左右肢体识别反了

现象:不翻转的图预测正常,一遇到镜像自拍或前置摄像头画面,左右手腕、左右脚踝全部对调。

原因:fliplr开了,但flip_idx是默认的 COCO 顺序而你的数据集点数不同,或者干脆没配。翻转时坐标镜像了,语义没对调。

解决:把flip_idx改成和数据点定义严格对应的交换数组;如果暂时不想处理,直接把fliplr设 0,先保证正确性再谈增强收益。

5.3 显存 OOM 或训练中途进程被杀

现象:训练跑几十个 iteration 后报 CUDA out of memory,或者 Linux 下进程被 OOM killer 干掉。

原因:batch与imgsz组合超出显存;或者workers开太大,每个 worker 都缓存了一份数据,内存被吃光。

解决:先把batch减半、imgsz降到 512 试一轮,确认能稳定跑再往上加;workers在内存紧张的机器上设 2 到 4,Windows 上设 0。真需要在有限显存上跑大分辨率,用梯度累积模拟大 batch。

5.4 关键点置信度普遍偏低、下游角度算不准

现象:人明明站得端正,预测出来的手腕、脚踝置信度只有 0.3 左右,按 0.5 过滤后点数不够,算关节角直接崩。

原因:训练集里这类点标注稀疏或被大量遮挡,模型学不到高置信输出;也可能是验证/推理时的imgsz与训练不一致,尺度变化让本来就不稳的小关键点更飘。

解决:补标一批包含完整四肢的样本,训练时适当降低degrees和scale的强度让模型先学好基本点位;推理侧把关键点阈值和“可见性”分开处理,用 visibility 做软加权而不是硬阈值,角度计算时对低置信点做邻近帧平滑。

5.5 导出 ONNX 后推理结果和 PyTorch 对不上

现象:PyTorch 下骨架正常,导出 ONNX 用 onnxruntime 跑,关键点整体偏移或数量不对。

原因:导出时没指定opset,或者输入尺寸动态化导致后处理里的坐标还原逻辑假设失效;也有版本是导出时把 NMS 一起打包,后处理重复做了一次。

解决:导出时固定imgsz、显式指定opset=12以上,导出后先用同一张图对比两边输出的最大绝对误差(正常应在 1e-3 量级);NMS 是否内置要确认清楚,避免二次过滤。真对不上就退回导出去掉 NMS 的版本,自己在外部做后处理,链路反而清晰。

6. 二次开发:把关键点接进自己的业务逻辑

跑通只是起点,真正花时间的是把 17 个点变成业务结论。我一般会在工程里加一个独立的后处理模块,和模型推理解耦,这样换模型、调阈值都不用动业务代码。最常用的是关节角计算,比如判断手肘弯曲程度:

import numpy as np def angle_between(a, b, c): """计算 b 为顶点时,a-b-c 的夹角(角度制)""" ba = np.array(a) - np.array(b) bc = np.array(c) - np.array(b) # 加 eps 防止零向量导致除零 cos = np.dot(ba, bc) / (np.linalg.norm(ba) * np.linalg.norm(bc) + 1e-8) return np.degrees(np.arccos(np.clip(cos, -1.0, 1.0))) # COCO 索引: 5左肩 7左肘 9左腕 L_SHOULDER, L_ELBOW, L_WRIST = 5, 7, 9 elbow_angle = angle_between(kpts[L_SHOULDER], kpts[L_ELBOW], kpts[L_WRIST])

参数上要守住两条:一是传入前先确认这三个点的置信度都过阈值,否则算出来的角度毫无意义;二是np.clip不能省,浮点误差会让arccos的输入冒出 1.0000001 直接变 NaN。这就是典型的“算法没问题、工程细节翻车”。

改造思路上有三条路值得展开。第一条是换数据集适配自己的场景:比如只关心上半身,可以把kpt_shape改成[5, 3]甚至更少,同步改flip_idx,模型更轻、小样本下更稳。注意改点数等于换任务,预训练头要重建,但骨干权重照样能加载,这一点前面提过。第二条是做时序平滑:单帧姿态抖动是常态,视频场景里对每个关键点维护一个滑动窗口做中值滤波或 One-Euro 滤波,能显著降低骨架“抽搐”,代价是引入几帧延迟,实时纠偏类应用要权衡。第三条是模型蒸馏或换小模型:先用yolov8m-pose训一个高精度版本,再用它的输出当软标签训yolov8n-pose部署,是端侧性能不够时最省事的路线。

验证改造是否有效,我的习惯是固定一套“回归样本”:挑 30 到 50 张覆盖不同姿态、遮挡、光照的图,每次改完代码都跑一遍,比对关键点坐标的平均像素误差和下游业务指标(比如动作判定准确率)。这套样本不进训练集,专门当后悔药用。从那以后我每次动kpt_shape、flip_idx或者增强参数,都强制先跑一遍这套回归样本再提交,省下来的返工时间远多于维护它的成本。希望这些能帮你在接姿态识别时少绕几个弯。

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

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进