其实仔细看一些代码也是非常有收获的。
DeepPhase 那里基本上跟踪到了输入,输出,和测试时的后处理过程
HumanML3D
目前的疑惑点在系数的全局旋转,是在是搞不清楚。问了问题果然是区别对待的就是为了face Z+ 。存储的global 这个应该是个逆。 然后后面的速度,应该也是局部的速度
raw_pose_processing.py
amass_to_pose: 这个函数主要就是把系数转成了3D关键点,并且对于关键点做一个绕着x轴顺时针90度的旋转。
生成文件带有M的,是做了动作的镜像。
motion_representation.py
uniform_skeleton: 这个函数主要就是对齐骨骼,tgt 这个是随便从数据集里面找到一个然后把所有的初始位置都对齐到这里。
# 对齐缩放,也就是平移
scale_rt = tgt_leg_len / src_leg_len
# print(scale_rt)
src_root_pos = positions[:, 0]
tgt_root_pos = src_root_pos * scale_rt
# 之后就是求系数,重新求出 joints
skeleton.py 这个里面是重点
get_offsets_joints: 这个就其实定义了骨架的结构,即偏离父节点的长度和方向(一般都是横平竖直的),前向的时候就是用这个旋转。 (骨骼就是按照横平竖直那样子标准坐标系定义的)
inverse_kinematics_np:
一、这里面先计算人体的朝向,
1)先通过肩膀和胯下,计算向量,这两个向量是直接相加,作为身体’水平方向’
2)竖直方向用 [0,1,0], 叉积算出朝前的方向 forward
【疑问】对于躺下的动作,应该直接就会有问题
二、然后计算出 [0,0,1] 到 forward 的旋转,作为root 旋转
三、接下来该算每一个关节的旋转。
t2m_raw_offsets: 这个其实记录了,后一(子)节点相对于当前节点的标准旋转
当去除掉全局+父旋转时,就是local 旋转。
TIPS: 解释一下这里IK的本质,其实就是当给定标准pose后,稠密点IK的计算方式。因此IK也分多种情况:1)给定稠密点,求出相对标准姿态的骨骼系数 2)给定叶节点,求出相邻跟骨骼的合适位置
quat_params 里面存储的就是各个骨骼旋转的系数。
接下来继续 motion_representation.py
【1】选择一个样本,获得骨骼的长度,进行IK。最终对齐(tgt)骨骼系数,然后得到新的关键点坐标
【2】接着就认为整个序列的最低点在地面上,然后放置在地面上
【3】按照第一帧的XZ坐标,进行对齐
【4】接着算出第一帧旋转的值,然后把人给转正
【5】根据脚的移动速度算出是否接触地面(经验值)
【6】然后计算,速度,和角速度
【7】计算joint相对位置(对齐到x,z),并且转正。然后计算 height,和转正之后骨骼点的位置
【8】一些额外的特征,然后joint velocity 还是有个root 旋转,其实应该就是顺便记录下全局位置
【9】后面的代码展示了回复的步骤
这里面再分析一下速度的计算
'''XZ at origin'''
root_pos_init = positions[0] # pos 只做到步骤[2],这里选择了序列的第一帧
root_pose_init_xz = root_pos_init[0] * np.array([1, 0, 1]) # 这里是记录下第一帧的hip位置
positions = positions - root_pose_init_xz # 以第一帧hip为原点,对齐所有的点
# forward_init 是第一帧朝前的向量
target = np.array([[0, 0, 1]])
root_quat_init = qbetween_np(forward_init, target) # 计算和标准朝向的差距,注意这里本质上一个逆
root_quat_init = np.ones(positions.shape[:-1] + (4,)) * root_quat_init # 扩展一下
positions = qrot_np(root_quat_init, positions) # 其实就是把第一帧给转正了,其他的修正一下
# root_quat = qbetween_np(forward, target) # 最开始是个逆? 转正的旋转
r_rot = quat_params[:, 0].copy() # 因此这个本质上是个逆? 这个非常重要
'''Root Linear Velocity'''
velocity = (positions[1:, 0] - positions[:-1, 0]).copy()
velocity = qrot_np(r_rot[1:], velocity) # 这一步具体意义不明,但结合上面的意义就是转正
# 强行理解就是,让(x,y)位置还能保留角度信息
'''Root Angular Velocity'''
r_velocity = qmul_np(r_rot[1:], qinv_np(r_rot[:-1])) # 就是获得相对旋转
# position:局部坐标 + 转正
ric_data = positions[:, 1:].reshape(len(positions), -1)
local_vel # 其实也是带有旋转的
# root_rot_velocity (B, seq_len, 1)
# root_linear_velocity (B, seq_len, 2)
# root_y (B, seq_len, 1)
# ric_data (B, seq_len, (joint_num - 1)*3)
# rot_data (B, seq_len, (joint_num - 1)*6)
# local_velocity (B, seq_len, joint_num*3)
# foot contact (B, seq_len, 4)
接下来就是如何从 data 数据中恢复骨骼
recover_root_rot_pos:这个就是恢复 root 的位置(r_pos)和y轴旋转。
recover_from_rot:利用 r_pos 和 系数 进行 forward 获得最终的 关键点.
recover_from_ric:之前的 ric 已经转正了,现在需要
Motion Latent Diffusion
先说一下利用blender渲染部分:
主要文件在 mld/render/blender/render.py(joints.py) 中
大概思路就是每一帧都会重新画圆柱和球,并且保存到图片上。 传入的参数 mat 不是矩阵,而是材质
代码的管理主要是通过 OmegaConf 这个库来进行的。优势就是可以随意增加key,v,而且可以$引用(需要load之后resolve)
loss
models/losses/utils.py 这里面应该才是最终用到的loss
感觉核心是看 models/architechtures/modeltype/mld.py
网路结构
文本的:

文章详细探讨了DeepPhase项目中关于人体和四足动物运动捕捉数据的处理,包括骨骼旋转、速度计算、逆动力学(IK)算法以及训练特征。重点分析了如何从局部速度计算到全局运动,并介绍了Unity中数据提取和Blender渲染的部分。此外,还涉及了GNN网络的数据制作过程和IK算法的核心实现。
最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



