|
|
''' |
|
|
Copyright 2017 Javier Romero, Dimitrios Tzionas, Michael J Black and the Max Planck Gesellschaft. All rights reserved. |
|
|
This software is provided for research purposes only. |
|
|
By using this software you agree to the terms of the MANO/SMPL+H Model license here http://mano.is.tue.mpg.de/license |
|
|
|
|
|
More information about MANO/SMPL+H is available at http://mano.is.tue.mpg.de. |
|
|
For comments or questions, please email us at: mano@tue.mpg.de |
|
|
|
|
|
|
|
|
About this file: |
|
|
================ |
|
|
This file defines a wrapper for the loading functions of the MANO model. |
|
|
|
|
|
Modules included: |
|
|
- load_model: |
|
|
loads the MANO model from a given file location (i.e. a .pkl file location), |
|
|
or a dictionary object. |
|
|
|
|
|
''' |
|
|
import os |
|
|
import cv2 |
|
|
import torch |
|
|
import numpy as np |
|
|
import pickle |
|
|
import chumpy as ch |
|
|
from chumpy.ch import MatVecMult |
|
|
|
|
|
|
|
|
class Rodrigues(ch.Ch): |
|
|
dterms = 'rt' |
|
|
|
|
|
def compute_r(self): |
|
|
return cv2.Rodrigues(self.rt.r)[0] |
|
|
|
|
|
def compute_dr_wrt(self, wrt): |
|
|
if wrt is self.rt: |
|
|
return cv2.Rodrigues(self.rt.r)[1].T |
|
|
|
|
|
|
|
|
def lrotmin(p): |
|
|
if isinstance(p, np.ndarray): |
|
|
p = p.ravel()[3:] |
|
|
return np.concatenate( |
|
|
[(cv2.Rodrigues(np.array(pp))[0] - np.eye(3)).ravel() |
|
|
for pp in p.reshape((-1, 3))]).ravel() |
|
|
if p.ndim != 2 or p.shape[1] != 3: |
|
|
p = p.reshape((-1, 3)) |
|
|
p = p[1:] |
|
|
return ch.concatenate([(Rodrigues(pp) - ch.eye(3)).ravel() |
|
|
for pp in p]).ravel() |
|
|
|
|
|
|
|
|
def posemap(s): |
|
|
if s == 'lrotmin': |
|
|
return lrotmin |
|
|
else: |
|
|
raise Exception('Unknown posemapping: %s' % (str(s), )) |
|
|
|
|
|
|
|
|
def ready_arguments(fname_or_dict, posekey4vposed='pose'): |
|
|
if not isinstance(fname_or_dict, dict): |
|
|
dd = pickle.load(open(fname_or_dict, 'rb'), encoding='latin1') |
|
|
else: |
|
|
dd = fname_or_dict |
|
|
|
|
|
want_shapemodel = 'shapedirs' in dd |
|
|
nposeparms = dd['kintree_table'].shape[1] * 3 |
|
|
|
|
|
if 'trans' not in dd: |
|
|
dd['trans'] = np.zeros(3) |
|
|
if 'pose' not in dd: |
|
|
dd['pose'] = np.zeros(nposeparms) |
|
|
if 'shapedirs' in dd and 'betas' not in dd: |
|
|
dd['betas'] = np.zeros(dd['shapedirs'].shape[-1]) |
|
|
|
|
|
for s in [ |
|
|
'v_template', 'weights', 'posedirs', 'pose', 'trans', 'shapedirs', |
|
|
'betas', 'J' |
|
|
]: |
|
|
if (s in dd) and not hasattr(dd[s], 'dterms'): |
|
|
dd[s] = ch.array(dd[s]) |
|
|
|
|
|
assert (posekey4vposed in dd) |
|
|
if want_shapemodel: |
|
|
dd['v_shaped'] = dd['shapedirs'].dot(dd['betas']) + dd['v_template'] |
|
|
v_shaped = dd['v_shaped'] |
|
|
J_tmpx = MatVecMult(dd['J_regressor'], v_shaped[:, 0]) |
|
|
J_tmpy = MatVecMult(dd['J_regressor'], v_shaped[:, 1]) |
|
|
J_tmpz = MatVecMult(dd['J_regressor'], v_shaped[:, 2]) |
|
|
dd['J'] = ch.vstack((J_tmpx, J_tmpy, J_tmpz)).T |
|
|
pose_map_res = posemap(dd['bs_type'])(dd[posekey4vposed]) |
|
|
dd['v_posed'] = v_shaped + dd['posedirs'].dot(pose_map_res) |
|
|
else: |
|
|
pose_map_res = posemap(dd['bs_type'])(dd[posekey4vposed]) |
|
|
dd_add = dd['posedirs'].dot(pose_map_res) |
|
|
dd['v_posed'] = dd['v_template'] + dd_add |
|
|
|
|
|
return dd |
|
|
|
|
|
|
|
|
|
|
|
def get_mano_pca_basis(ncomps=45, use_pca=True, side='right', mano_root='data/base_data/human_models/mano'): |
|
|
if use_pca: |
|
|
ncomps = ncomps |
|
|
else: |
|
|
ncomps = 45 |
|
|
|
|
|
if side == 'right': |
|
|
mano_path = os.path.join(mano_root, 'MANO_RIGHT.pkl') |
|
|
elif side == 'left': |
|
|
mano_path = os.path.join(mano_root, 'MANO_LEFT.pkl') |
|
|
smpl_data = ready_arguments(mano_path) |
|
|
hands_components = smpl_data['hands_components'] |
|
|
selected_components = hands_components[:ncomps] |
|
|
th_selected_comps = selected_components |
|
|
|
|
|
return torch.tensor(th_selected_comps, dtype=torch.float32) |
|
|
|
|
|
|
|
|
|
|
|
def change_flat_hand_mean(hand_pose, remove=True, side='right', mano_root='data/base_data/human_models/mano'): |
|
|
if side == 'right': |
|
|
mano_path = os.path.join(mano_root, 'MANO_RIGHT.pkl') |
|
|
elif side == 'left': |
|
|
mano_path = os.path.join(mano_root, 'MANO_LEFT.pkl') |
|
|
smpl_data = ready_arguments(mano_path) |
|
|
|
|
|
|
|
|
hands_mean = smpl_data['hands_mean'] |
|
|
hands_mean = hands_mean.copy() |
|
|
|
|
|
if remove: |
|
|
hand_pose[3:] = hand_pose[3:] - hands_mean |
|
|
else: |
|
|
hand_pose[3:] = hand_pose[3:] + hands_mean |
|
|
return hand_pose |