
简介面向计算机视觉与人体姿态估计学习者的Human3.6M 3D人体姿态数据集获取资源提供基于Python的完整下载、解压、预处理工具链适用于需要快速获取并解析该数据集的科研人员与开发者。资源共14个文件包含4个Python脚本负责下载、解压、元数据处理等以及配置文件、Dockerfile、依赖清单、说明文档等辅助文件压缩包仅34KB便于下载和部署。已有3624人学习浏览。通过脚本可自动获取Human3.6M数据集并支持后续的3D关节位置提取与格式转换帮助用户跳过繁琐的手动下载与前期处理直接聚焦于姿态估计模型构建与训练是入门和研究中实用的效率工具。 如果你准备用Python做3D人体姿态估计那你迟早会被同一个数据集拦住Human36M。这个数据集在论文里出现得实在太频繁几乎所有姿势估计模型的评测都绕不开它但真要把它下载下来、用Python读进内存新手的体验往往是官网申请要好几天下完的MAT文件打不开好不容易读出来坐标又对不上。这篇文章我就把申请、下载、解析、投影、可视化整条链路完整讲一遍刚起步的同学可以直接照着做踩过的坑也都给你标好了。1. Human3.6M的家底为什么它在一众数据集里地位这么高3D人体姿态估计的任务是从一张图或者一段视频里恢复人体各关节的三维坐标。这个任务看起来简单其实对数据集的要求很高因为你需要“真值”是精确的3D坐标而不是从2D逆推出来的近似结果。Human3.6M就是在这种需求下诞生的经典基准数据集。它由Max Planck智能系统研究所于2014年随CVPR论文《Reconstructing 3D Human Pose from 2D Detections》发布。名字里的“3.6M”指的是动作捕捉数据总共提供约360万个3D姿态标注。采集方式是让受试者在室内完成一系列日常动作同时用Vicon动作捕捉系统记录高精度的3D关节坐标再用4个数字摄像机从不同视角同步拍摄画面。视频帧率是50Hz动作捕捉帧率是100Hz也就是说每个动作序列不仅有多视角的RGB视频还有对应的、一帧不差的3D骨架真值。不过有个地方第一次接触的人很容易懵数据里一共采集了多位受试者对外公开的只有7位分别是S1、S5、S6、S7、S8、S9、S11。编号不是从S1到S11连续排列的没有S2、S3、S4、S10这是正常现象不是你下载漏了。动作类型一般是15类像Directions、Discussion、Eating、Greeting、Jumping、Phoning、Posing、Purchases、Sitting、SittingDown、Smoking、Waiting、WalkDog、Walking、WalkTogether每位受试者的每个动作还会录制多个重复序列。骨架标注方面官方原始标注的关节数量比较密大家实际用的时候多整理成17个关键关节点这种形式也有工程实现会重排成COCO或MPII的骨骼顺序。评测指标里见得最多的是两个一个是MPJPE直接计算预测关节和真值关节的平均欧氏距离单位是毫米另一个是PA-MPJPE先把预测结果做一次刚性对齐再计算误差。还有一个绕不开的概念叫Protocol。Protocol 1输入用的2D关键点来自真实标注只评测从2D升到3D的部分Protocol 2输入用的2D关键点来自检测器比如CPM或者Mask R-CNN先检测出2D关键点再交给3D模型更贴近真实应用但整体误差也会更大。论文里常见的训练测试划分是用S1、S5、S6、S7、S8训练S9、S11测试。你看到“Human3.6M under Protocol 2”这类表述指的就是这套设置。2. 数据获取的三条路官方申请、开源脚本、NPZ预处理版各有各的门道数据集这么经典拿到手却没那么容易。我实际走过三条路分别说下体验和适用场景。2.1 官网申请流程与注意事项最正统的途径是去Human3.6M官网提交申请。流程大概是打开官网找到数据申请入口。填写一张表单内容包括姓名、所属单位、邮箱、研究用途。提交后等待人工审核快的话一两天慢的话可能要一周。审核通过后会收到一封激活邮件里面包含下载链接和简单的使用说明。进入下载页面按subject、action组织好的文件夹就在那可以用浏览器直接点也可以用支持断点续传的工具批量拉取。有几个坑一定要提前知道。第一申请邮箱尽量用机构邮箱个人邮箱被拒的概率很大第二下载链接通常有时效性我遇到过48小时内必须下载完的情况文件还没下完链接就先失效了最后只好重新申请第三完整数据集非常大视频部分占大头动辄几十GB到上百GB下载前千万先检查磁盘空间和网络稳定性。2.2 开源项目里附带的下载脚本第二种途径是直接找开源项目里已经写好的下载脚本。GitHub上做3D姿态估计的项目不少VideoPose3D、ST-GCN这类经典仓库里都带了数据处理相关的脚本有些项目甚至会直接在release里挂好预处理后的数据文件。走这条路的好处是省心不用自己写申请理由也不用去跟原始目录结构较劲。坏处是版本比较杂有的脚本是针对老版文件命名的有的预处理环节已经做了自己项目的自定义修改用之前得把处理流程看清楚。2.3 NPZ预处理版本才是最省心的选择如果只是想快速跑通一个baseline或者验证一个想法我强烈建议直接找NPZ预处理版本。最典型的是Martinez等人在ICCV 2017工作里发布的data_3d_h36a.npz这个文件把官方MAT和XML里的核心信息抽出来统一整理成一个numpy压缩包2D关键点、3D关键点、相机参数、训练测试划分、动作名称全都排好np.load一下就能用。很多后来的开源项目都基于这个文件二次fork。但用预处理版也有前提你得搞清楚它的关节顺序是什么、坐标单位是什么、2D坐标到底是GT投影还是检测器输出。我见过有人拿到的数据姿态画出来是倒的就是因为关节索引没对齐。三条路径对比下来大致是这样获取途径适合场景主要风险官网申请做数据pipeline、多视角任务、视频输入审核周期长、下载链接会过期、总量大开源项目脚本快速复现某个论文版本混杂、可能被二次裁剪NPZ预处理版快速实验、对比SOTA缺少原始视频、动作序列可能被精简3. 从文件到Python数组MAT/XML/NPZ格式与加载代码数据下载完真正的考验才开始。不同途径拿到的文件格式差别很大你得先搞清楚里面装的是什么。3.1 官网完整包的目录结构以官网下载并解压后的常见结构为例大致是这样human3.6m/ ├── S1/ │ ├── Directions_1/ │ │ ├── video.mp4 │ │ └── ... │ ├── Discussion_1/ │ └── ... ├── S5/ ├── metadata.xml └── ...每个subject下面按“动作名_重复序号”建文件夹里面放对应动作的视频和动作捕捉原始数据。如果是做视频输入的模型这套目录就是你的数据源。3.2 MAT文件命名新老版本差别很大动作捕捉数据通常会整理成MAT文件保存但文件命名有两种常见风格老版本长这样S_01_act_01_sub_01_ca_01.mat新版本长这样subject_01_act_01_rr_01_ca_01.mat含义都是subject编号、动作编号、重复序号、相机编号。很多网上流传的解析脚本只认老版本命名换到新下载的文件上直接报错。如果你下载的是新命名务必先看脚本里怎么拼文件名或者统一用glob匹配。3.3 用scipy.io.loadmat读原始MATMAT文件用scipy.io.loadmat读取。但H36M的MAT文件不是简单一个矩阵通常是多层struct嵌套字段名也因为来源不同而千差万别。我的习惯是先打印keys再逐层往下看绝不猜字段名import scipy.io as sio mat sio.loadmat(subject_01_act_01_rr_01_ca_01.mat, squeeze_meTrue) print(mat.keys()) # 常见字段名有 pose_3d、points3d、pose_xyz 之类 # 如果遇到 1x1 的 struct array先调用 .item() 解包 data mat[pose_3d] # 具体字段名以实际打印为准 print(data.shape)3.4 NPZ预处理版怎么读如果你用的是data_3d_h36a.npz这种预处理文件读起来就痛快多了import numpy as np data np.load(data_3d_h36a.npz, allow_pickleTrue) train data[train].item() test data[test].item() print(train.keys()) # 受试者列表 print(train[S1].keys()) # 动作序列列表 seq train[S1][Walking 1] print(seq.keys()) # 输出里会有 positions_3d、positions_2d、cameras 等 print(seq[positions_3d].shape) # (帧数, 17, 3) print(seq[positions_2d].shape) # (帧数, 17, 2)第一次读的时候容易漏掉allow_pickleTrue不写的话numpy会直接报错。这个参数就是为了解包里面的Python dict属于这个数据集的标准操作。3.5 动作名字符串里的隐形地雷NPZ里动作名的键通常是“动作名空格重复序号”的形式比如Walking 1和Walking 2中间是有空格的。很多人写成Walking_1一查就报KeyError。先print(train[S1].keys())看清楚原始字符串再写索引。另外一个容易忽略的点是帧率对齐。动作捕捉本身是100Hz视频是50Hz所以官方原始数据里每秒有100个骨架帧但视频每秒只有50帧。直接用原始MAT做训练时一定要明确自己到底取哪个基准NPZ预处理版在制作时已经把2D和3D统一对齐成了50Hz这也是我推荐你从NPZ入门的重要原因。4. 坐标投影与可视化验证确认数据真的读对了数据读进来了不代表它是对的。H36M的坐标系、单位、相机参数这堆东西初学者稍不注意就全乱了。4.1 单位毫米还是米先记住结论H36M的3D坐标单位是毫米。有些库训练时习惯把坐标除以1000转成米有些直接拿毫米算MPJPE这都行但你别混着用。我见过有人直接从某个开源项目里拉数据后来又换了另一个预处理版本两个版本单位不一致训练半天loss下不去查了两天才发现是这问题。4.2 相机参数长什么样在NPZ里每个动作序列的cameras字段是一个长度为4的数组对应4个摄像机视角。每个相机的dict包含f焦距2维向量对应(fx, fy)c主点坐标2维向量对应(cx, cy)R3x3旋转矩阵t3x1平移向量dist畸变系数4.3 3D到2D的投影公式世界坐标系下的3D点先经旋转和平移变换到相机坐标系再做透视投影公式如下x_cam R X_world t x_pixel f[0] * x_cam[0] / x_cam[2] c[0] y_pixel f[1] * x_cam[1] / x_cam[2] c[1]写成Python函数import numpy as np def project_3d_to_2d(points_3d, camera): R camera[R] t camera[t] f camera[f] c camera[c] points_cam (R points_3d.T).T t.reshape(1, 3) points_2d np.zeros((points_cam.shape[0], 2)) points_2d[:, 0] f[0] * points_cam[:, 0] / points_cam[:, 2] c[0] points_2d[:, 1] f[1] * points_cam[:, 1] / points_cam[:, 2] c[1] return points_2d这里特别提醒不同解析包对R和t的定义可能反着写有的是R X_world t有的是R (X_world - t)。你自己推断公式的时候最有效的验证方法就是拿已知的3D点和2D标注做对比如果投影结果和官方给的2D坐标位置对不上第一怀疑R和t的符号形式第二怀疑单位。4.4 把骨架画出来一眼看出对错判断数据是否正确的黄金标准是可视化。画3D骨架其实不复杂import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D edges [ (0, 1), (1, 2), (2, 3), (0, 4), (4, 5), (5, 6), (0, 7), (7, 8), (8, 9), (8, 10), (10, 11), (11, 12), (8, 13), (13, 14), (14, 15), ] def draw_skeleton(ax, pts3d, edges, colorb): ax.scatter(pts3d[:, 0], pts3d[:, 1], pts3d[:, 2], s20, ccolor) for a, b in edges: ax.plot(pts3d[[a, b], 0], pts3d[[a, b], 1], pts3d[[a, b], 2], ccolor, lw2) seq train[S1][Walking 1] points_3d seq[positions_3d][0] fig plt.figure(figsize(8, 8)) ax fig.add_subplot(111, projection3d) draw_skeleton(ax, points_3d, edges) ax.set_box_aspect((1, 1, 1)) plt.show()画出来的姿态如果站立方向合理、四肢位置符合人体结构说明数据基本没问题。我每次换一个新数据集第一件事永远是画骨架不画到正常绝不往下走。这一步看着简单实际能省下大量的debug时间。5. 我踩过的坑和你可能也会遇到的坑最后把这些年实际踩过的坑集中写出来基本都是血泪教训。现象原因对策申请邮件一直不回复用了个人邮箱换机构邮箱重新提交下载到一半链接失效下载链接有时效失效后重新走申请流程用支持断点续传的工具loadmat后print出来全是1x1 structMAT内部存在多层嵌套逐层.item()展开先看清楚结构np.load报Object arrays错误没开allow_pickle加allow_pickleTrue动作名查不到字符串里多了空格或下划线先打印keys再复制原始字符串训练时MPJPE数值离谱单位、关节顺序或坐标定义不统一先画骨架再做投影对比Protocol 2实验的2D输入对不上把GT 2D当成了检测器2D确认输入来自检测器输出不是GT投影还有一个细节值得单独拎出来说。H36M数据里同一个动作序列在不同相机视角下视频帧和动作捕捉帧的对应关系是固定的但你如果从原始MAT直接解析必须自己处理“100Hz动捕帧到50Hz视频帧”的抽取。NPZ版本已经帮你做了这层对齐所以很多人推荐新手先用NPZ。我自己在踩过一次“2D视频帧和3D骨架错位”的坑之后就养成了一个习惯无论是自己做pipeline还是用开源代码第一件事永远是随机抽一帧把2D关键点画到原始视频画面上确认3D骨架投影后和2D标注完全重合再放心进入训练环节。如果让我重新入坑一次我的顺序会是这样先下载NPZ预处理版把整个读取、可视化、训练流程跑通等真要做视频输入或者多视角任务再回官方源申请完整数据。数据集获取只是万里长征第一步但这一步走稳了后面能省掉大量查错时间。希望这份H36M获取与解析的实战记录能帮你在入门3D人体姿态估计时少走些弯路。本文还有配套的精品资源点击获取