import numpy as np import torch from smplx import SMPL as _SMPL from smplx import SMPLX as _SMPLX from smplx.body_models import SMPLOutput, SMPLXOutput from smplx.lbs import vertices2joints from .constants import JOINT_MAP, JOINT_NAMES # Hand joints SMPLX_HAND_TO_PANOPTIC = [ 0, 13, 14, 15, 16, 1, 2, 3, 17, 4, 5, 6, 18, 10, 11, 12, 19, 7, 8, 9, 20, ] # Wrist Thumb to Pinky class SMPL(_SMPL): """Extension of the official SMPL implementation to support more joints""" JOINTS = ( "Hips", "Left Upper Leg", "Right Upper Leg", "Spine", "Left Leg", "Right Leg", "Spine1", "Left Foot", "Right Foot", "Thorax", "Left Toe", "Right Toe", "Neck", "Left Shoulder", "Right Shoulder", "Head", "Left ForeArm", "Right ForeArm", "Left Arm", "Right Arm", "Left Hand", "Right Hand", "Left Finger", "Right Finger", ) SKELETON = ( (0, 1), (0, 2), (0, 3), (1, 4), (2, 5), (3, 6), (4, 7), (5, 8), (6, 9), (7, 10), (8, 11), (9, 12), (12, 13), (12, 14), (12, 15), (13, 16), (14, 17), (16, 18), (17, 19), (18, 20), (19, 21), (20, 22), (21, 23), ) def __init__(self, *args, **kwargs): super(SMPL, self).__init__(*args, **kwargs) joints = [JOINT_MAP[i] for i in JOINT_NAMES] joint_regressor_extra = kwargs["joint_regressor_extra_path"] J_regressor_extra = np.load(joint_regressor_extra) self.register_buffer( "J_regressor_extra", torch.tensor(J_regressor_extra, dtype=torch.float32) ) self.joint_map = torch.tensor(joints, dtype=torch.long) def forward(self, *args, **kwargs): kwargs["get_skin"] = True smpl_output = super(SMPL, self).forward(*args, **kwargs) extra_joints = vertices2joints( self.J_regressor_extra, smpl_output.vertices ) # Additional 9 joints #Check doc/J_regressor_extra.png joints = torch.cat( [smpl_output.joints, extra_joints], dim=1 ) # [N, 24 + 21, 3] + [N, 9, 3] joints = joints[:, self.joint_map, :] output = SMPLOutput( vertices=smpl_output.vertices, global_orient=smpl_output.global_orient, body_pose=smpl_output.body_pose, joints=joints, betas=smpl_output.betas, full_pose=smpl_output.full_pose, ) return output class SMPLX(_SMPLX): """Extension of the official SMPL implementation to support more joints""" JOINTS = ( "Hips", "Left Upper Leg", "Right Upper Leg", "Spine", "Left Leg", "Right Leg", "Spine1", "Left Foot", "Right Foot", "Thorax", "Left Toe", "Right Toe", "Neck", "Left Shoulder", "Right Shoulder", "Head", "Left ForeArm", "Right ForeArm", "Left Arm", "Right Arm", "Left Hand", "Right Hand", ) SKELETON = ( (0, 1), (0, 2), (0, 3), (1, 4), (2, 5), (3, 6), (4, 7), (5, 8), (6, 9), (7, 10), (8, 11), (9, 12), (12, 13), (12, 14), (12, 15), (13, 16), (14, 17), (16, 18), (17, 19), (18, 20), (19, 21), ) def __init__(self, *args, **kwargs): kwargs["ext"] = "pkl" # We have pkl file super(SMPLX, self).__init__(*args, **kwargs) joints = [JOINT_MAP[i] for i in JOINT_NAMES] self.joint_map = torch.tensor(joints, dtype=torch.long) def forward(self, *args, **kwargs): kwargs["get_skin"] = True # if pose parameter is for SMPL with 21 joints (ignoring root) try: if kwargs["body_pose"].shape[1] == 69: kwargs["body_pose"] = kwargs["body_pose"][ :, : -2 * 3 ] # Ignore the last two joints (which are on the palm. Not used) if kwargs["body_pose"].shape[1] == 23: kwargs["body_pose"] = kwargs["body_pose"][ :, :-2 ] # Ignore the last two joints (which are on the palm. Not used) except: pass smpl_output = super(SMPLX, self).forward(*args, **kwargs) # SMPL-X Joint order: https://docs.google.com/spreadsheets/d/1_1dLdaX-sbMkCKr_JzJW_RZCpwBwd7rcKkWT_VgAQ_0/edit#gid=0 smplx_to_smpl = ( list(range(0, 22)) + [28, 43] + list(range(55, 76)) ) # 28 left middle finger , 43: right middle finger 1 smpl_joints = smpl_output.joints[ :, smplx_to_smpl, : ] # Convert SMPL-X to SMPL 127 ->45 joints = smpl_joints joints = joints[:, self.joint_map, :] smplx_lhand = ( [20] + list(range(25, 40)) + list(range(66, 71)) ) # 20 for left wrist. 20 finger joints lhand_joints = smpl_output.joints[:, smplx_lhand, :] # (N,21,3) lhand_joints = lhand_joints[ :, SMPLX_HAND_TO_PANOPTIC, : ] # Convert SMPL-X hand order to paonptic hand order smplx_rhand = ( [21] + list(range(40, 55)) + list(range(71, 76)) ) # 21 for right wrist. 20 finger joints rhand_joints = smpl_output.joints[:, smplx_rhand, :] # (N,21,3) rhand_joints = rhand_joints[ :, SMPLX_HAND_TO_PANOPTIC, : ] # Convert SMPL-X hand order to paonptic hand order output = SMPLXOutput( vertices=smpl_output.vertices, global_orient=smpl_output.global_orient, body_pose=smpl_output.body_pose, joints=joints, right_hand_pose=rhand_joints, # N,21,3 left_hand_pose=lhand_joints, # N,21,3 betas=smpl_output.betas, full_pose=smpl_output.full_pose, A=smpl_output.A, ) return output """ 0 pelvis', 1 left_hip', 2 right_hip', 3 spine1', 4 left_knee', 5 right_knee', 6 spine2', 7 left_ankle', 8 right_ankle', 9 spine3', 10 left_foot', 11 right_foot', 12 neck', 13 left_collar', 14 right_collar', 15 head', 16 left_shoulder', 17 right_shoulder', 18 left_elbow', 19 right_elbow', 20 left_wrist', 21 right_wrist', 22 jaw', 23 left_eye_smplhf', 24 right_eye_smplhf', 25 left_index1', 26 left_index2', 27 left_index3', 28 left_middle1', 29 left_middle2', 30 left_middle3', 31 left_pinky1', 32 left_pinky2', 33 left_pinky3', 34 left_ring1', 35 left_ring2', 36 left_ring3', 37 left_thumb1', 38 left_thumb2', 39 left_thumb3', 40 right_index1', 41 right_index2', 42 right_index3', 43 right_middle1', 44 right_middle2', 45 right_middle3', 46 right_pinky1', 47 right_pinky2', 48 right_pinky3', 49 right_ring1', 50 right_ring2', 51 right_ring3', 52 right_thumb1', 53 right_thumb2', 54 right_thumb3', 55 nose', 56 right_eye', 57 left_eye', 58 right_ear', 59 left_ear', 60 left_big_toe', 61 left_small_toe', 62 left_heel', 63 right_big_toe', 64 right_small_toe', 65 right_heel', 66 left_thumb', 67 left_index', 68 left_middle', 69 left_ring', 70 left_pinky', 71 right_thumb', 72 right_index', 73 right_middle', 74 right_ring', 75 right_pinky', 76 right_eye_brow1', 77 right_eye_brow2', 78 right_eye_brow3', 79 right_eye_brow4', 80 right_eye_brow5', 81 left_eye_brow5', 82 left_eye_brow4', 83 left_eye_brow3', 84 left_eye_brow2', 85 left_eye_brow1', 86 nose1', 87 nose2', 88 nose3', 89 nose4', 90 right_nose_2', 91 right_nose_1', 92 nose_middle', 93 left_nose_1', 94 left_nose_2', 95 right_eye1', 96 right_eye2', 97 right_eye3', 98 right_eye4', 99 right_eye5', 100 right_eye6', 101 left_eye4', 102 left_eye3', 103 left_eye2', 104 left_eye1', 105 left_eye6', 106 left_eye5', 107 right_mouth_1', 108 right_mouth_2', 109 right_mouth_3', 110 mouth_top', 111 left_mouth_3', 112 left_mouth_2', 113 left_mouth_1', 114 left_mouth_5', # 59 in OpenPose output 115 left_mouth_4', # 58 in OpenPose output 116 mouth_bottom', 117 right_mouth_4', 118 right_mouth_5', 119 right_lip_1', 120 right_lip_2', 121 lip_top', 122 left_lip_2', 123 left_lip_1', 124 left_lip_3', 125 lip_bottom', 126 right_lip_3', 127 right_contour_1', 128 right_contour_2', 129 right_contour_3', 130 right_contour_4', 131 right_contour_5', 132 right_contour_6', 133 right_contour_7', 134 right_contour_8', 135 contour_middle', 136 left_contour_8', 137 left_contour_7', 138 left_contour_6', 139 left_contour_5', 140 left_contour_4', 141 left_contour_3', 142 left_contour_2', 143 left_contour_1' """ # SMPL Joints: """ 0 pelvis', 1 left_hip', 2 right_hip', 3 spine1', 4 left_knee', 5 right_knee', 6 spine2', 7 left_ankle', 8 right_ankle', 9 spine3', 10 left_foot', 11 right_foot', 12 neck', 13 left_collar', 14 right_collar', 15 head', 16 left_shoulder', 17 right_shoulder', 18 left_elbow', 19 right_elbow', 20 left_wrist', 21 right_wrist', 22 23 24 nose', 25 right_eye', 26 left_eye', 27 right_ear', 28 left_ear', 29 left_big_toe', 30 left_small_toe', 31 left_heel', 32 right_big_toe', 33 right_small_toe', 34 right_heel', 35 left_thumb', 36 left_index', 37 left_middle', 38 left_ring', 39 left_pinky', 40 right_thumb', 41 right_index', 42 right_middle', 43 right_ring', 44 right_pinky', """