尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Human3.6M 数据读取实战:Python 解析骨骼点、相机参数与动作标签
简介这份资源面向计算机视觉与机器学习方向的开发者尤其是正在入门或实践3D人体姿态估计的研究者与学生提供用Python获取并处理Human3.6M数据集的完整工具脚本。压缩包共14个文件约34KB以4个Python脚本为核心覆盖数据下载、解压、处理与提取等环节另含txt依赖与校验说明、Dockerfile与docker-compose.yml容器配置、yml、xml元数据、md说明文档及license等便于快速搭建可复现的运行环境。目前已有3634人学习下载说明其在同类资源中具备一定参考价值。借助这些脚本读者可省去手动整理数据流程的繁琐直接对接HDF5读取、3D关节位置提取、格式转换与数据集划分等步骤并在此基础上构建CNN、RNN或seq2seq等姿态估计模型完成训练、评估与可视化对比适合作为3D姿态理解项目的起步脚手架。1. 拿到 Human3.6M 之后Python 读取骨骼点、相机参数与动作标签的完整路径如果你正在做 3D 人体姿态估计、动作识别或者骨骼动画驱动大概率绕不开 Human3.6M 这个数据集。它包含 11 位受试者、17 个动作场景、数百万帧图像以及配套的 2D/3D 关节点坐标和相机标定参数。但真正上手时你会发现原始数据不是一份 CSV 就能搞定——视频帧、MAT 标注、相机内参分散在不同目录标签体系还有两套17 关节和 32 关节。这篇笔记记录的是我用 Python 从零把 Human3.6M 读成可训练张量的过程包括目录结构解析、MAT 文件读取、坐标系对齐、动作标签映射以及几个让我卡了大半天的坑。适合已经下载完数据集、准备写 DataLoader 的开发者。2. 目录结构与数据格式先搞清楚你手里有什么2.1 原始目录的层级逻辑Human3.6M 下载下来通常是一个顶层文件夹下面按受试者编号分目录比如S1、S5、S6、S7、S8、S9、S11。每个受试者目录里再按动作场景分比如Directions、Discussion、Eating、Greeting、Phoning、Posing、Purchases、Sitting、SittingDown、Smoking、Photo、Waiting、Walking、WalkDog、WalkTogether。每个动作目录下一般有imageSequence/或视频文件原始 RGB 帧annotations.mat该动作的 2D 关节点、3D 关节点、相机参数等boundingBoxes.mat人体检测框我拿到的版本里图像是.jpg序列标注是 MATLAB 的.mat文件。这里第一个容易翻车的地方是不同来源的 Human3.6M 副本目录命名和文件组织方式不完全一致。有的把视频单独放在videos/下有的把标注统一放在annotations/里。所以第一步不是写代码而是先用os.walk把目录树打出来看一眼。import os root /path/to/human36m for dirpath, dirnames, filenames in os.walk(root): # 只打印到动作目录层级避免输出爆炸 depth dirpath.replace(root, ).count(os.sep) if depth 2: print(dirpath) for f in filenames[:3]: print( , f)这段代码的作用是快速确认目录深度和文件类型。depth 2限制只看到受试者/动作这一层避免把几万张图片全列出来。如果你发现某个动作目录下没有.mat文件那说明标注可能被集中放在别处需要调整后续读取路径。2.2 MAT 文件里到底存了什么Human3.6M 的标注文件是 MATLAB 的 v7.3 格式普通scipy.io.loadmat读不了必须用h5py。文件里的键通常包括键名含义维度示例S主体结构体包含所有标注structS/pose3D 关节点世界坐标32×NS/pose2d2D 关节点图像坐标32×NS/camParam相机参数structS/box检测框4×N注意不同版本里键名可能是小写s或者嵌套更深。我一般会先写一个探测脚本把顶层键和子键都打印出来。import h5py mat_path /path/to/human36m/S1/Directions/annotations.mat with h5py.File(mat_path, r) as f: def print_keys(name, obj): if isinstance(obj, h5py.Dataset): print(f{name}: shape{obj.shape}, dtype{obj.dtype}) else: print(f{name}: group) f.visititems(print_keys)visititems会递归遍历所有节点。h5py.Dataset是实际存数据的数组h5py.Group是嵌套结构。这一步能帮你确认pose到底是 32 关节还是 17 关节以及数据是否已经转置。我遇到过pose的 shape 是(N, 32)而不是(32, N)如果直接按列取就会全错。2.3 两套关节体系的区别Human3.6M 提供 32 关节和 17 关节两套标注。32 关节包含更多末端节点如手指、脚趾17 关节是常用简化版对应 Human3.6M 论文里的标准评估协议。如果你要做 SOTA 对比必须用 17 关节如果只是做骨骼驱动或可视化32 关节更细腻。17 关节的索引映射在原始 MAT 里不是直接给出的需要自己按论文定义写死。常见做法是定义一个JOINT_MAP列表把 32 关节里的对应索引挑出来。这个映射表在网上有多个版本我建议以你下载的数据集附带的 README 为准不要随便抄。3. 用 Python 读取 3D 关节点与相机参数3.1 读取单帧 3D 坐标假设你已经确认pose的 shape 是(32, N)其中 N 是帧数。读取某一帧的 3D 坐标import h5py import numpy as np def load_3d_pose(mat_path, frame_idx): with h5py.File(mat_path, r) as f: # 注意h5py 读取后需要转置因为 MATLAB 是列优先 pose f[S/pose][:] # shape (32, N) pose pose.T # 转成 (N, 32) frame_pose pose[frame_idx] # (32,) # 转成 (32, 3) 的 xyz xyz frame_pose.reshape(-1, 3) return xyz这里的关键是转置。MATLAB 存矩阵是列优先h5py读出来是原始维度但 Python 习惯行优先。如果不转置pose[frame_idx]取到的就是第 frame_idx 个关节在所有帧上的值完全错了。我当初就是在这里卡了很久可视化出来是一团乱线。reshape(-1, 3)把 32×3 的坐标展平成 32 个关节的 xyz。注意 Human3.6M 的 3D 坐标单位是毫米原点在相机坐标系下不是世界坐标系。如果你要做全局动作分析需要额外做坐标系变换。3.2 相机参数解析与投影相机参数存在S/camParam里通常包含内参矩阵K、旋转R、平移T。读取方式def load_camera(mat_path): with h5py.File(mat_path, r) as f: cam f[S/camParam] # 具体键名需要探测常见为 K, R, T K cam[K][:] # (3, 3) R cam[R][:] # (3, 3) T cam[T][:] # (3, 1) return K, R, T拿到K、R、T后可以把 3D 点投影到 2D 图像平面验证标注是否对齐def project_3d_to_2d(xyz, K, R, T): # xyz: (32, 3) # 转成齐次坐标 ones np.ones((xyz.shape[0], 1)) xyz_h np.hstack([xyz, ones]) # (32, 4) # 外参 RT np.hstack([R, T.reshape(3, 1)]) # (3, 4) cam_coord (RT xyz_h.T).T # (32, 3) # 内参投影 uv (K cam_coord.T).T # (32, 3) uv uv[:, :2] / uv[:, 2:3] # 归一化 return uv这段代码的逻辑是先把 3D 点从世界坐标转到相机坐标乘外参再用内参投影到像素坐标。如果你发现投影结果和pose2d对不上大概率是R和T的方向搞反了或者T需要取负。不同受试者的相机参数是独立的不能混用。3.3 批量读取与内存控制Human3.6M 全量数据很大一次性把所有 MAT 读进内存会爆。我一般用生成器逐动作、逐帧读取def iter_poses(root, subjects, actions): for subj in subjects: for action in actions: mat_path os.path.join(root, subj, action, annotations.mat) if not os.path.exists(mat_path): continue with h5py.File(mat_path, r) as f: pose f[S/pose][:].T # (N, 32) for i in range(pose.shape[0]): yield subj, action, i, pose[i].reshape(-1, 3)yield让每次只返回一帧配合 PyTorch 的DataLoader可以做到流式加载。注意h5py.File在生成器里打开后如果外部提前中断文件句柄可能不会立即释放。稳妥做法是把读取逻辑封装成类在__del__里关闭文件。4. 动作标签映射与数据集划分4.1 动作名称到类别 IDHuman3.6M 的 15 个动作去掉Photo和WalkingDog的某些变体需要映射成整数标签。我一般用字典硬编码ACTION_MAP { Directions: 0, Discussion: 1, Eating: 2, Greeting: 3, Phoning: 4, Posing: 5, Purchases: 6, Sitting: 7, SittingDown: 8, Smoking: 9, Photo: 10, Waiting: 11, Walking: 12, WalkDog: 13, WalkTogether: 14 }注意Photo在某些协议里被排除WalkDog和WalkTogether有时合并。如果你要复现某个论文的结果先去查它的评估协议不要直接用这个表。4.2 标准训练/测试划分Human3.6M 的标准划分是S1、S5、S6、S7、S8 做训练S9、S11 做测试。这个划分在几乎所有 3D 姿态论文里通用。写代码时TRAIN_SUBJECTS [S1, S5, S6, S7, S8] TEST_SUBJECTS [S9, S11]如果你要做跨受试者泛化实验可以进一步从训练集里留一个受试者做验证。但注意不要用测试集调参否则结果没有可比性。4.3 构建 PyTorch Dataset把前面几块拼起来一个最小的 Dataset 长这样import torch from torch.utils.data import Dataset class Human36MDataset(Dataset): def __init__(self, root, subjects, actions, transformNone): self.samples [] for subj in subjects: for action in actions: mat_path os.path.join(root, subj, action, annotations.mat) if os.path.exists(mat_path): self.samples.append((mat_path, ACTION_MAP[action])) self.transform transform def __len__(self): return len(self.samples) def __getitem__(self, idx): mat_path, label self.samples[idx] with h5py.File(mat_path, r) as f: pose f[S/pose][:].T # (N, 32) # 这里取中间帧做示例实际应按帧索引 mid pose.shape[0] // 2 xyz pose[mid].reshape(-1, 3).astype(np.float32) if self.transform: xyz self.transform(xyz) return torch.from_numpy(xyz), label这个 Dataset 把每个动作文件当成一个样本取中间帧。实际训练时应该按帧展开或者用滑动窗口取序列。ACTION_MAP在外部定义transform可以做归一化或随机旋转。5. 避坑与排查那些让我重跑实验的细节5.1 现象读取的 3D 坐标全是 NaN原因MAT 文件里某些帧的pose是空值或填充值h5py读出来是NaN。Human3.6M 原始数据里确实存在少量缺失帧。解决在 Dataset 里加过滤np.isnan(xyz).any()为真就跳过或补零。我一般选择跳过因为补零会引入虚假的骨骼长度。5.2 现象投影后的 2D 点和pose2d偏差几百像素原因相机参数里的R和T是相对于世界坐标系的而pose可能已经是相机坐标系下的值。两者混用会导致双重变换。解决先确认pose的坐标系。如果pose已经是相机坐标投影时只需要乘K不要再乘R、T。可以拿一帧手动算一下看哪个组合能让投影点和pose2d重合。5.3 现象不同受试者的骨骼长度不一致原因Human3.6M 的 3D 坐标是绝对坐标不同受试者身高不同骨骼长度自然不同。如果直接拿绝对坐标训练模型会学到受试者身份而不是动作。解决做骨骼归一化。常见做法是以髋关节为原点用躯干长度做尺度归一化。或者直接预测相对坐标每个关节减去父关节。5.4 现象h5py打开文件报OSError: Unable to open file原因MAT 文件不是 v7.3 格式而是更老的 v7 或 v6。h5py只支持 v7.3。解决用scipy.io.loadmat试一下如果能读就用 scipy。或者用 MATLAB 重新保存为 v7.3。我遇到过混合格式的数据集需要写一个兼容层先试h5py失败再试scipy。5.5 现象训练时 loss 不下降准确率随机原因标签映射错了。比如ACTION_MAP里Walking和WalkDog的 ID 写反或者训练集里混入了测试集受试者。解决打印每个 batch 的标签分布确认没有某个类别全是 0。再检查TRAIN_SUBJECTS和TEST_SUBJECTS是否有交集。这个坑很隐蔽因为数据加载不会报错只是模型学不到东西。6. 进阶用 17 关节协议做标准化评估与可视化验证6.1 17 关节映射与 MPJPE 计算要做论文级对比必须把 32 关节转成 17 关节并计算 MPJPEMean Per Joint Position Error。映射表我一般这样写# 32 关节到 17 关节的索引映射以常见协议为准 JOINT_17 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] # 实际需要根据你的 MAT 文件调整这里只是占位MPJPE 计算def mpjpe(pred, gt): # pred, gt: (N, 17, 3) return np.mean(np.linalg.norm(pred - gt, axis-1))注意计算前要先做根节点对齐通常是髋关节否则误差会被全局平移放大。标准协议里还会做尺度对齐但 Human3.6M 的评估一般只做根对齐。6.2 可视化验证用 Matplotlib 画骨架写完读取代码后一定要可视化验证。我习惯用 Matplotlib 画 3D 骨架import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D def plot_skeleton(xyz, edges): fig plt.figure() ax fig.add_subplot(111, projection3d) for i, j in edges: ax.plot([xyz[i, 0], xyz[j, 0]], [xyz[i, 1], xyz[j, 1]], [xyz[i, 2], xyz[j, 2]], b-) ax.scatter(xyz[:, 0], xyz[:, 1], xyz[:, 2], cr) plt.show()edges是骨骼连接列表需要按 17 关节或 32 关节定义。画出来如果是一个扭曲的人形说明坐标读取正确如果是一团乱麻回去检查转置和 reshape。6.3 一个我常用的验证习惯每次换数据集副本或改读取代码后我会固定做三件事第一取 S1 的Directions第一帧打印 3D 坐标的范围正常应该在 -1000 到 1000 毫米之间第二投影到 2D 和pose2d对比误差应小于 5 像素第三用 17 关节算一遍 MPJPE如果大于 200 毫米说明映射或对齐有问题。这三步走完基本能排除 90% 的读取错误。从那以后我每次接新数据集都强制走一遍这个流程省下了大量重跑实验的时间。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

Flutter离线优先架构鸿蒙适配:brick_offline_first_with_supabase存储与同步实战

Flutter离线优先架构鸿蒙适配:brick_offline_first_with_supabase存储与同步实战

最近把一个 Flutter 业务从传统后端直连改造成brick_offline_first_with_supabase的离线优先架构,过程中顺手适配了鸿蒙 HarmonyOS 设备端。整体做下来最直观的感受是:这套组合真正把"本地物理缓存 远端 Postgres 同步队列"捏成了一个可控的…

📅 2026/10/20 3:14:22
YOLOv10绝缘子缺陷检测系统实战:从数据准备到UI部署全流程

YOLOv10绝缘子缺陷检测系统实战:从数据准备到UI部署全流程

1. 项目起点:绝缘子缺陷检测到底难在哪,以及为什么选YOLOv10先说个实际场景。某巡检队在一次线路巡检中拍了上万张照片,全靠人工在电脑前一张一张看,光是找缺陷就花了两周。最让人头疼的是,绝缘子自爆(也就…

📅 2026/10/20 3:14:22
为什么越来越多人选择Sulphur 2蒸馏版:Base与Distilled工作流选择指南

为什么越来越多人选择Sulphur 2蒸馏版:Base与Distilled工作流选择指南

【免费下载链接】Sulphur-2-base 项目地址: https://ai.gitcode.com/hf_mirrors/SulphurAI/Sulphur-2-base 点击查看 免费下载 Sulphur 2 是一款基于 LTX 2.3(22B)的开源 uncensored 视频生成模型,原生支持文生视频(t…

📅 2026/10/20 3:14:22
MORE NEWS

更多资讯

📰

context-mode实战:构建上下文感知的桌面自动化效率工具

context-mode:把“我现在在干嘛”变成系统行为的实战设计先说个我自己的真实感受。同时维护四五个项目的时候,每天最累的不是写代码,而是频繁切换状态。前一分钟还在看生产环境的日志,后一分钟切回编辑器写需求,再过一…

📰

基于潜在时间图的递归时空图神经网络:原理、实现与实战

1. 问题背景与核心思路:时空预测为什么需要“潜在时间图”前阵子我接手了一个城市传感器流量预测项目,输入是分布在城市不同位置的传感器每小时回传的数值,目标是预测未来 12 个时刻的变化。这类问题我们一般称为“时空预测”。我这次用的方案…

📰

本地部署AI Agent:多模型配置与Skill安装避坑实战

最近我基本把自己泡在一套开源智能体框架里。这东西能本地部署、能接多路大模型、还能用 Skill 把模型从“聊天机器”变成“能干活的执行器”。折腾完之后,我最想说的不是“它有多好用”,而是“文档里没写的坑到底在哪”。这篇就把多模型配置&#xff08…

📰

AI应用落地中的Skills:从提示词到可复用能力封装

最近一两年做AI应用落地,有个词出现频率越来越高:skills。很多人第一次听到它,以为是那种"Excel技能清单""职场软技能列表"之类的东西,结果一问才知道,圈里讨论的完全是另一回事。我最初接触这个概…

📰

Windows 11 优化完整教程:用 Windows11 开源项目快速完成 7 项系统调优

Windows 11 优化完整教程:用 Windows11 开源项目快速完成 7 项系统调优 【免费下载链接】windows11 🌎 Windows 11 Settings, Tweaks, Scripts 项目地址: https://gitcode.com/GitHub_Trending/wi/windows11 Windows11 是一个免费的开源项目&…

📰

法律AI融资背后的渠道逻辑:收银机与等保服务商为何下注

说实话,我是在一个很平常的工作日上午刷到这则融资消息的。某法律AI团队上线刚两个月,宣布完成A轮融资,具体金额没披露,但投资方名单里排头的不是任何一家VC,一个是做智能收银机的厂商,另一个是做等保测评的…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬