MHformer 源码学习
(上图转载知乎,侵权删)
1. 数据方面
1.1 下载过来的数据
“data_2d_h36m_cpn_ft_h36m_dbb”压缩包内是 2D关键的数据;“data_3d_h36m”内是3D关节点的数据。
a、3D关节点数据解压查看
读取“data_3d_h36m”压缩包内的 positions_3d.npy 文件;读取数据后,数据的格式是dict类型,第一层含有7个dict的字典,然后中的每一个元素均是含有30个dict的字典,这30个dict的字典中包含元素是一个动作序列维度表示为(动作序列长度,17,3),“S”表示 人物。
-S1
----actions
----------frames
-----------------joints
-----------------------xyz
b、2D关节点数据解压查看
“data_2d_h36m_cpn_ft_h36m_dbb”压缩包内有两个文件,一个是metadata.npy,另一个是positions_2d.npy。
metadata.npy中含有的信息是2D 骨架中左右手边关节的 Index,左边6个,右边6个,没有包括对称中心线。
positions_2d.npy中含有的信息是4台相机的2D骨架数据,和3D数据类似也是层层字典数据嵌套,第一层字典元素表示 ‘S’ 人物,第二次字典嵌套则表示的是该 人物下的 动作类,第三次字典嵌套表示 该人物该动作下的 相机类(哪个相机拍的)。
-S
----actions
----------cameras
---------- ----frames
---------------------joints
----------------------------xyz
1.2 对于数据的处理流程
1.2.1、训练阶段
pytorch的数据需要用data.Dataset的子类,在本项目中,使用的是
①构建自己的Dataset先
②然后将自己构成的Dataset作为实参输入到data.Dataset的子类中从而初始化了一个data.Dataset的子类对象。
①、读取 3D Dataset(Human36mDataset)
a、加载 相机内外参数据
b、加载数据集数据
构建的自己的Dataset 类名叫: Human36mDataset 继承于 MocapDataset(这样的做法应该是为了起到抽象的作用,松耦合的模式)
这处理的过程是在 读取的数据的基础上 加上了4 相机的外参(注意 同一个人下的相同相加下的外参是相同的-代码详,但是不同的相机的同一个人的外参,以及同一个相机的不同人的外参不一样)
c、修改数据为17个关节点(原本的32个)
②、加载2D数据、预处理(prepare_data函数)
目的:1)输出得到 经过了长度对齐于3D数据,并且标准化后的2D数据
2)得到了额外标签position_3D下的处于相机坐标系的3D数据(每个人的动作下有四个)
加载2D数据
a、坐标系转换3D-w2c 并处理真值(除盆骨外均变为相对向量)
训练阶段 我们的目的是 在 相机坐标系下 将2D姿态估计出相机坐标系下的3D姿态来,所以需要将3D的数据转换到 每个人下的 四台相机下(数据量一下翻了4倍)。如下图所示在原本的Dataset上同 “position”,"cameras"下额外加了一个标签“positions_3d”表示这个人四台相机坐标系下的3D关节点。
b、2D 数据与3D数据长度一致化
动作序列长度一致化的前提是:2D动作的序列 大于等于 3D动作的序列
c、2D数据标准化
将2D数据 根据其拍摄的相机内参进行标准化到 [-1,1],这样有利于模型的训练
③、以相机为最小单位制作 序列数据(fetch函数)
输出:out_camera_params, out_poses_3d, out_poses_2d
序列数据就是一个人一个动作下的数据,先从Dataset中取出序列数据,使得可以统一检索,比如检索号是(S_Index,action_Index,camera_Index),则可以找到同一组的信息
a、2D 序列数据
b、序列数据下的相机内参
c、3D序列数据
④、分块生成器-用于DataLoad中的Batch操作(ChunkedGenerator函数)
ChunkedGenerator的主要作用是生成一个 generator的类使得在在DataLoad在调用__getitem__时,可以通过generator产生一个 batch。
a、pairs的形成-ChunkedGenerator中把序列数据处理为单帧
分析:一个pairs的包表示一段序列,单个pair中的元素由五个组成,分别是:((人物、动作类型、相机编号)、这一帧在序列中的Index范围(左闭右开)、augment_vector、reverse_augment_vector)。
通过(人物、动作类型、相机编号) 便可以找到这一个动作序列
b、get_batch的处理
猜想:DataLoad在取数据时随机从 paris中抽出一个其index,通过其index在获得其pair中信息比如(人物、动作类型、相机编号),找到其对应的序列后 然后对该index处于序列中的位置进行 感受野放大(输入、输出都放大)-放大为frames大小,不能放大的index对其进行左padding,右padding。
c、最后
这样 输入的是 一帧2D 图像=>感受野放大为 frames,输出的也是 放大的感受野为frames的3D骨架,且均处于该相机坐标系下。
1.2.2、Demon阶段
–通过 Yolov3框出图像中的人
–将框中人进行2D人体姿态估计,并将数据保存
–读取训练好的模型与2D关节点数据
–输入一帧2D,预处理2D数据
–输出前预处理3D数据,输出一帧3D
–画图
①、2D数据的预处理与输出
1、2D的数据进行感受野放大
2、2D数据标准化到 [-1,1]
3、对称骨架数据 并重新创建一个维度
4、将2D的数据 分两次放入 模型中(第一次是没有对称的,第二次放入是对称了的)
5、3D数据输出处理
输出的也是两个带有感受野的数据,将对称的与没对称进行取均值,然后压缩维度取感受野中的那帧即为 最终的输出,这样就是实现了端到端了,输入是一帧,输出是一帧(虽然输入后进行了预处理padding)
2、模型方面
模型输入:的是2D关节点(归一化为[-1,1]带有画面纵横比的,像素坐标系下)
loss对比的真值是:其相机坐标系下 进行 人体平移后,除盆骨外所有关节点向量以盆骨为起点了(注意没有RT变换的,仅仅是平移),但是在 训练时,取DataLoad时把 盆骨关节点 置为 0.(这样一来获得的3D人体姿态就是全是相对对于盆骨向量的,没法获得其与相机坐标系之间的信息了)
模型的输出则是:盆骨的位置 为0, 而其他关节点向量则是相对于盆骨的
进行 人体平移后,除盆骨外所有关节点向量以盆骨为起点了(注意没有RT变换的,仅仅是平移),但是在 训练时,取DataLoad时把 盆骨关节点 置为 0.(这样一来获得的3D人体姿态就是全是相对对于盆骨向量的,没法获得其与相机坐标系之间的信息了)
模型的输出则是:盆骨的位置 为0, 而其他关节点向量则是相对于盆骨的
待更新…