|
|
''' |
|
|
Copyright 2015 Matthew Loper, Naureen Mahmood 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 SMPL Model license here http://smpl.is.tue.mpg.de/license |
|
|
|
|
|
More information about SMPL is available here http://smpl.is.tue.mpg. |
|
|
For comments or questions, please email us at: smpl@tuebingen.mpg.de |
|
|
|
|
|
|
|
|
About this file: |
|
|
================ |
|
|
This file defines the serialization functions of the SMPL model. |
|
|
|
|
|
Modules included: |
|
|
- save_model: |
|
|
saves the SMPL model to a given file location as a .pkl file |
|
|
- load_model: |
|
|
loads the SMPL model from a given file location (i.e. a .pkl file location), |
|
|
or a dictionary object. |
|
|
|
|
|
''' |
|
|
|
|
|
__all__ = ['load_model', 'save_model'] |
|
|
|
|
|
import numpy as np |
|
|
import pickle |
|
|
import chumpy as ch |
|
|
from chumpy.ch import MatVecMult |
|
|
from posemapper import posemap |
|
|
from verts import verts_core |
|
|
|
|
|
def save_model(model, fname): |
|
|
m0 = model |
|
|
trainer_dict = {'v_template': np.asarray(m0.v_template),'J': np.asarray(m0.J),'weights': np.asarray(m0.weights),'kintree_table': m0.kintree_table,'f': m0.f, 'bs_type': m0.bs_type, 'posedirs': np.asarray(m0.posedirs)} |
|
|
if hasattr(model, 'J_regressor'): |
|
|
trainer_dict['J_regressor'] = m0.J_regressor |
|
|
if hasattr(model, 'J_regressor_prior'): |
|
|
trainer_dict['J_regressor_prior'] = m0.J_regressor_prior |
|
|
if hasattr(model, 'weights_prior'): |
|
|
trainer_dict['weights_prior'] = m0.weights_prior |
|
|
if hasattr(model, 'shapedirs'): |
|
|
trainer_dict['shapedirs'] = m0.shapedirs |
|
|
if hasattr(model, 'vert_sym_idxs'): |
|
|
trainer_dict['vert_sym_idxs'] = m0.vert_sym_idxs |
|
|
if hasattr(model, 'bs_style'): |
|
|
trainer_dict['bs_style'] = model.bs_style |
|
|
else: |
|
|
trainer_dict['bs_style'] = 'lbs' |
|
|
pickle.dump(trainer_dict, open(fname, 'w'), -1) |
|
|
|
|
|
|
|
|
def backwards_compatibility_replacements(dd): |
|
|
|
|
|
|
|
|
if 'default_v' in dd: |
|
|
dd['v_template'] = dd['default_v'] |
|
|
del dd['default_v'] |
|
|
if 'template_v' in dd: |
|
|
dd['v_template'] = dd['template_v'] |
|
|
del dd['template_v'] |
|
|
if 'joint_regressor' in dd: |
|
|
dd['J_regressor'] = dd['joint_regressor'] |
|
|
del dd['joint_regressor'] |
|
|
if 'blendshapes' in dd: |
|
|
dd['posedirs'] = dd['blendshapes'] |
|
|
del dd['blendshapes'] |
|
|
if 'J' not in dd: |
|
|
dd['J'] = dd['joints'] |
|
|
del dd['joints'] |
|
|
|
|
|
|
|
|
if 'bs_style' not in dd: |
|
|
dd['bs_style'] = 'lbs' |
|
|
|
|
|
|
|
|
|
|
|
def ready_arguments(fname_or_dict): |
|
|
|
|
|
if not isinstance(fname_or_dict, dict): |
|
|
dd = pickle.load(open(fname_or_dict, 'rb'), encoding='latin1') |
|
|
else: |
|
|
dd = fname_or_dict |
|
|
|
|
|
backwards_compatibility_replacements(dd) |
|
|
|
|
|
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]) |
|
|
|
|
|
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 |
|
|
dd['v_posed'] = v_shaped + dd['posedirs'].dot(posemap(dd['bs_type'])(dd['pose'])) |
|
|
else: |
|
|
dd['v_posed'] = dd['v_template'] + dd['posedirs'].dot(posemap(dd['bs_type'])(dd['pose'])) |
|
|
|
|
|
return dd |
|
|
|
|
|
|
|
|
|
|
|
def load_model(fname_or_dict): |
|
|
dd = ready_arguments(fname_or_dict) |
|
|
|
|
|
args = { |
|
|
'pose': dd['pose'], |
|
|
'v': dd['v_posed'], |
|
|
'J': dd['J'], |
|
|
'weights': dd['weights'], |
|
|
'kintree_table': dd['kintree_table'], |
|
|
'xp': ch, |
|
|
'want_Jtr': True, |
|
|
'bs_style': dd['bs_style'] |
|
|
} |
|
|
|
|
|
result, Jtr = verts_core(**args) |
|
|
result = result + dd['trans'].reshape((1,3)) |
|
|
result.J_transformed = Jtr + dd['trans'].reshape((1,3)) |
|
|
|
|
|
for k, v in dd.items(): |
|
|
setattr(result, k, v) |
|
|
|
|
|
return result |
|
|
|
|
|
|