MCPcopy Create free account
hub / github.com/MotrixLab/ViMoGen / motion_rep_to_SMPL

Function motion_rep_to_SMPL

motion_rep/retarget_motion.py:39–97  ·  view source on GitHub ↗

Convert 276-dim global (aligned) motion representation back to SMPL params + joints. The representation layout follows collect_motion_rep_DART: [body_pose(126), joints(66), joints_vel(66), root_rot6d(6), root_rot_vel6d(6), transl(3), transl_vel(3)].

(motion, recover_from_velocity=False, equal_length=False)

Source from the content-addressed store, hash-verified

37 return motion
38
39def motion_rep_to_SMPL(motion, recover_from_velocity=False, equal_length=False):
40 """
41 Convert 276-dim global (aligned) motion representation back to SMPL params + joints.
42 The representation layout follows collect_motion_rep_DART:
43 [body_pose(126), joints(66), joints_vel(66), root_rot6d(6), root_rot_vel6d(6), transl(3), transl_vel(3)].
44 """
45 expected_dim = JOINT_NUM * 12 + 12 # 276 for JOINT_NUM=22
46 if motion.shape[1] != expected_dim:
47 raise ValueError(f"get unexpected motion shape: {motion.shape}, expect {expected_dim} (global DART rep)")
48
49 seq_len = motion.shape[0]
50 body_poses = motion[:, :(JOINT_NUM-1)*6] # (seq_len-1, (joints_num-1)*6)
51 body_poses = rot6d_to_axis_angle(body_poses.reshape(-1, 6)).reshape(seq_len, -1) # (seq_len-1, (joints_num-1)*3)
52 joints = motion[:, (JOINT_NUM*6-6):(JOINT_NUM*9-6)].reshape(seq_len, -1, 3) # (seq_len-1, joints_num, 3)
53 joints_vel = motion[:, (JOINT_NUM*9-6):(JOINT_NUM*12-6)].reshape(seq_len, -1, 3) # (seq_len-1, joints_num, 3)
54 global_orient = motion[:, (JOINT_NUM*12-6):(JOINT_NUM*12)] # (seq_len-1, 6)
55 global_orient = rot6d_to_axis_angle(global_orient) # (seq_len-1, 3)
56 trans = motion[:, (JOINT_NUM*12+6):(JOINT_NUM*12+9)] # (seq_len-1, 3)
57 trans_vel = motion[:, (JOINT_NUM*12+9):(JOINT_NUM*12+12)]
58
59 smpl_data = {
60 'global_orient': global_orient,
61 'body_pose': body_poses,
62 'transl': trans
63 }
64
65 if recover_from_velocity or equal_length:
66 seq_end = seq_len + 1 if equal_length else seq_len
67 # recover the global_orient seq from velocity
68 R_first = rot6d_to_mat3x3(motion[0:1, (JOINT_NUM*12-6):(JOINT_NUM*12)]) # (1, 6)
69 R_vel = rot6d_to_mat3x3(motion[:, (JOINT_NUM*12):(JOINT_NUM*12+6)]) # (seq_len-1, 6)
70 # Recover global orientation by cumulative multiplication of velocities
71 R_rec = [R_first]
72 for i in range(1, seq_end):
73 R_curr = torch.matmul(R_vel[i-1:i], R_rec[i-1]) # (1,3,3) x (1,3,3)
74 R_rec.append(R_curr)
75 R_rec = torch.cat(R_rec, dim=0) # (seq_len, 3, 3)
76
77 # Similarly, recover translations:
78 trans_first_frame = trans[0:1] # (1,3)
79 trans_recovered = [trans_first_frame]
80 for i in range(1, seq_end):
81 trans_recovered.append(trans_recovered[i-1] + trans_vel[i-1:i])
82 trans_recovered = torch.cat(trans_recovered, dim=0) # (seq_len, 3)
83
84 # recover the joints sequence
85 joints_recovered = [joints[0:1]]
86 for i in range(1, seq_end):
87 joints_recovered.append(joints_recovered[i-1] + joints_vel[i-1:i])
88 joints_recovered = torch.cat(joints_recovered, dim=0) # (seq_len, joints_num, 3)
89
90 smpl_data['global_orient'] = mat3x3_to_axis_angle(R_rec) # (seq_len, 3)
91 smpl_data['transl'] = trans_recovered
92 if equal_length:
93 last_frame_body_pose = smpl_data['body_pose'][-1:]
94 smpl_data['body_pose'] = torch.cat([smpl_data['body_pose'], last_frame_body_pose], dim=0)
95 joints = joints_recovered
96

Callers 4

run_smplxFunction · 0.90
motion_visFunction · 0.90
convert_motion_to_jointsFunction · 0.90
process_hmr_motionFunction · 0.85

Calls 3

rot6d_to_axis_angleFunction · 0.85
rot6d_to_mat3x3Function · 0.85
mat3x3_to_axis_angleFunction · 0.85

Tested by

no test coverage detected