in contactopt/util.py [0:0]
def fit_pca_to_axang(mano_pose, mano_beta):
"""
This project uses the MANO model parameterized with 15 PCA components. However, many other approaches use
different parameterizations (15 joints, parameterized with 45 axis-angle parameters). This function
allows converting between the formats. It first runs the MANO model forwards to get the hand vertices of
the initial format. Then an optimization is performed to adjust the 15 PCA parameters of a second MANO model
to match the initial vertices. Perhaps there are better ways to do this, but this ensures highest accuracy.
:param mano_pose: numpy (45) axis angle coordinates
:param mano_beta: numpy (10) beta parameters
:return: numpy (15) PCA parameters of fitted hand
"""
mano_pose = np.array(mano_pose)
full_axang = torch.Tensor(mano_pose).unsqueeze(0)
mano_model = ManoLayer(mano_root='mano/models', use_pca=True, ncomps=45, side='right', flat_hand_mean=False)
beta_in = torch.Tensor(mano_beta).unsqueeze(0)
mano_model_orig = ManoLayer(mano_root='mano/models', joint_rot_mode="axisang", use_pca=False, center_idx=None, flat_hand_mean=True)
_, target_joints = forward_mano(mano_model_orig, full_axang, beta_in, [])
full_axang[:, 3:] -= mano_model.th_hands_mean
pca_mat = mano_model.th_selected_comps.T
pca_shape = full_axang[:, 3:].mm(pca_mat) # Since the HO gt is in full 45 dim axang coords, convert back to PCA shape
new_pca_shape = np.zeros(18)
new_pca_shape[:3] = mano_pose[:3] # set axang
new_pca_shape[3:] = pca_shape[0, :15] # set pca pose
# Do optimization
pca_in = torch.Tensor(new_pca_shape).unsqueeze(0)
pca_in.requires_grad = True
mano_model = ManoLayer(mano_root='mano/models', use_pca=True, ncomps=15, side='right', flat_hand_mean=False)
optimizer = torch.optim.Adam([pca_in], lr=0.03, amsgrad=True) # AMSgrad helps
loss_criterion = torch.nn.L1Loss()
for it in range(200):
optimizer.zero_grad()
hand_verts, hand_joints = forward_mano(mano_model, pca_in, beta_in, []) # 2.2ms
# vis_pointcloud(hand_joints, target_joints)
loss = loss_criterion(hand_joints, target_joints)
# print('Opt loss', loss.detach())
loss.backward()
optimizer.step()
return pca_in.detach().squeeze(0).numpy()