|
|
|
import numpy as np
|
|
import torch
|
|
|
|
import contextlib
|
|
|
|
from smplx import SMPLLayer as _SMPLLayer
|
|
from smplx.lbs import vertices2joints
|
|
|
|
|
|
|
|
|
|
action2motion_joints = [8, 1, 2, 3, 4, 5, 6, 7, 0, 9, 10, 11, 12, 13, 14, 21, 24, 38]
|
|
|
|
from utils.config import SMPL_MODEL_PATH, JOINT_REGRESSOR_TRAIN_EXTRA
|
|
|
|
JOINTSTYPE_ROOT = {"a2m": 0,
|
|
"smpl": 0,
|
|
"a2mpl": 0,
|
|
"vibe": 8}
|
|
|
|
JOINT_MAP = {
|
|
'OP Nose': 24, 'OP Neck': 12, 'OP RShoulder': 17,
|
|
'OP RElbow': 19, 'OP RWrist': 21, 'OP LShoulder': 16,
|
|
'OP LElbow': 18, 'OP LWrist': 20, 'OP MidHip': 0,
|
|
'OP RHip': 2, 'OP RKnee': 5, 'OP RAnkle': 8,
|
|
'OP LHip': 1, 'OP LKnee': 4, 'OP LAnkle': 7,
|
|
'OP REye': 25, 'OP LEye': 26, 'OP REar': 27,
|
|
'OP LEar': 28, 'OP LBigToe': 29, 'OP LSmallToe': 30,
|
|
'OP LHeel': 31, 'OP RBigToe': 32, 'OP RSmallToe': 33, 'OP RHeel': 34,
|
|
'Right Ankle': 8, 'Right Knee': 5, 'Right Hip': 45,
|
|
'Left Hip': 46, 'Left Knee': 4, 'Left Ankle': 7,
|
|
'Right Wrist': 21, 'Right Elbow': 19, 'Right Shoulder': 17,
|
|
'Left Shoulder': 16, 'Left Elbow': 18, 'Left Wrist': 20,
|
|
'Neck (LSP)': 47, 'Top of Head (LSP)': 48,
|
|
'Pelvis (MPII)': 49, 'Thorax (MPII)': 50,
|
|
'Spine (H36M)': 51, 'Jaw (H36M)': 52,
|
|
'Head (H36M)': 53, 'Nose': 24, 'Left Eye': 26,
|
|
'Right Eye': 25, 'Left Ear': 28, 'Right Ear': 27
|
|
}
|
|
|
|
JOINT_NAMES = [
|
|
'OP Nose', 'OP Neck', 'OP RShoulder',
|
|
'OP RElbow', 'OP RWrist', 'OP LShoulder',
|
|
'OP LElbow', 'OP LWrist', 'OP MidHip',
|
|
'OP RHip', 'OP RKnee', 'OP RAnkle',
|
|
'OP LHip', 'OP LKnee', 'OP LAnkle',
|
|
'OP REye', 'OP LEye', 'OP REar',
|
|
'OP LEar', 'OP LBigToe', 'OP LSmallToe',
|
|
'OP LHeel', 'OP RBigToe', 'OP RSmallToe', 'OP RHeel',
|
|
'Right Ankle', 'Right Knee', 'Right Hip',
|
|
'Left Hip', 'Left Knee', 'Left Ankle',
|
|
'Right Wrist', 'Right Elbow', 'Right Shoulder',
|
|
'Left Shoulder', 'Left Elbow', 'Left Wrist',
|
|
'Neck (LSP)', 'Top of Head (LSP)',
|
|
'Pelvis (MPII)', 'Thorax (MPII)',
|
|
'Spine (H36M)', 'Jaw (H36M)',
|
|
'Head (H36M)', 'Nose', 'Left Eye',
|
|
'Right Eye', 'Left Ear', 'Right Ear'
|
|
]
|
|
|
|
|
|
|
|
class SMPL(_SMPLLayer):
|
|
""" Extension of the official SMPL implementation to support more joints """
|
|
|
|
def __init__(self, model_path=SMPL_MODEL_PATH, **kwargs):
|
|
kwargs["model_path"] = model_path
|
|
|
|
|
|
with contextlib.redirect_stdout(None):
|
|
super(SMPL, self).__init__(**kwargs)
|
|
|
|
J_regressor_extra = np.load(JOINT_REGRESSOR_TRAIN_EXTRA)
|
|
self.register_buffer('J_regressor_extra', torch.tensor(J_regressor_extra, dtype=torch.float32))
|
|
vibe_indexes = np.array([JOINT_MAP[i] for i in JOINT_NAMES])
|
|
a2m_indexes = vibe_indexes[action2motion_joints]
|
|
smpl_indexes = np.arange(24)
|
|
a2mpl_indexes = np.unique(np.r_[smpl_indexes, a2m_indexes])
|
|
|
|
self.maps = {"vibe": vibe_indexes,
|
|
"a2m": a2m_indexes,
|
|
"smpl": smpl_indexes,
|
|
"a2mpl": a2mpl_indexes}
|
|
|
|
def forward(self, *args, **kwargs):
|
|
smpl_output = super(SMPL, self).forward(*args, **kwargs)
|
|
|
|
extra_joints = vertices2joints(self.J_regressor_extra, smpl_output.vertices)
|
|
all_joints = torch.cat([smpl_output.joints, extra_joints], dim=1)
|
|
|
|
output = {"vertices": smpl_output.vertices}
|
|
|
|
for joinstype, indexes in self.maps.items():
|
|
output[joinstype] = all_joints[:, indexes]
|
|
|
|
return output |