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)
| 37 | return motion |
| 38 | |
| 39 | def 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 |
no test coverage detected