Spaces:
Running
on
L40S
Running
on
L40S
import numpy as np | |
from detrsmpl.utils.transforms import aa_to_rotmat, rotmat_to_aa | |
def transform_to_camera_frame(global_orient, transl, pelvis, extrinsic): | |
"""Transform body model parameters to camera frame. | |
Args: | |
global_orient (numpy.ndarray): shape (3, ). Only global_orient and | |
transl needs to be updated in the rigid transformation | |
transl (numpy.ndarray): shape (3, ). | |
pelvis (numpy.ndarray): shape (3, ). 3D joint location of pelvis | |
This is necessary to eliminate the offset from SMPL | |
canonical space origin to pelvis, because the global orient | |
is conducted around the pelvis, not the canonical space origin | |
extrinsic (numpy.ndarray): shape (4, 4). Transformation matrix | |
from world frame to camera frame | |
Returns: | |
(new_gloabl_orient, new_transl) | |
new_gloabl_orient: transformed global orient | |
new_transl: transformed transl | |
""" | |
# take out the small offset from smpl origin to pelvis | |
transl_offset = pelvis - transl | |
T_p2w = np.eye(4) | |
T_p2w[:3, 3] = transl_offset | |
# camera extrinsic: transformation from world frame to camera frame | |
T_w2c = extrinsic | |
# smpl transformation: from vertex frame to world frame | |
T_v2p = np.eye(4) | |
global_orient_mat = aa_to_rotmat(global_orient) | |
T_v2p[:3, :3] = global_orient_mat | |
T_v2p[:3, 3] = transl | |
# compute combined transformation from vertex to world | |
T_v2w = T_p2w @ T_v2p | |
# compute transformation from vertex to camera | |
T_v2c = T_w2c @ T_v2w | |
# decompose vertex to camera transformation | |
# np: new pelvis frame | |
# T_v2c = T_np2c x T_v2np | |
T_np2c = T_p2w | |
T_v2np = np.linalg.inv(T_np2c) @ T_v2c | |
# decompose into new global orient and new transl | |
new_global_orient_mat = T_v2np[:3, :3] | |
new_global_orient = rotmat_to_aa(new_global_orient_mat) | |
new_transl = T_v2np[:3, 3] | |
return new_global_orient, new_transl | |
def batch_transform_to_camera_frame(global_orient, transl, pelvis, extrinsic): | |
"""Transform body model parameters to camera frame by batch. | |
Args: | |
global_orient (np.ndarray): shape (N, 3). Only global_orient and | |
transl needs to be updated in the rigid transformation | |
transl (np.ndarray): shape (N, 3). | |
pelvis (np.ndarray): shape (N, 3). 3D joint location of pelvis | |
This is necessary to eliminate the offset from SMPL | |
canonical space origin to pelvis, because the global orient | |
is conducted around the pelvis, not the canonical space origin | |
extrinsic (np.ndarray): shape (4, 4). Transformation matrix | |
from world frame to camera frame | |
Returns: | |
(new_gloabl_orient, new_transl) | |
new_gloabl_orient: transformed global orient | |
new_transl: transformed transl | |
""" | |
N = len(global_orient) | |
assert global_orient.shape == (N, 3) | |
assert transl.shape == (N, 3) | |
assert pelvis.shape == (N, 3) | |
# take out the small offset from smpl origin to pelvis | |
transl_offset = pelvis - transl | |
T_p2w = np.eye(4).reshape(1, 4, 4).repeat(N, axis=0) | |
T_p2w[:, :3, 3] = transl_offset | |
# camera extrinsic: transformation from world frame to camera frame | |
T_w2c = extrinsic | |
# smpl transformation: from vertex frame to world frame | |
T_v2p = np.eye(4).reshape(1, 4, 4).repeat(N, axis=0) | |
global_orient_mat = aa_to_rotmat(global_orient) | |
T_v2p[:, :3, :3] = global_orient_mat | |
T_v2p[:, :3, 3] = transl | |
# compute combined transformation from vertex to world | |
T_v2w = T_p2w @ T_v2p | |
# compute transformation from vertex to camera | |
T_v2c = T_w2c @ T_v2w | |
# decompose vertex to camera transformation | |
# np: new pelvis frame | |
# T_v2c = T_np2c x T_v2np | |
T_np2c = T_p2w | |
T_v2np = np.linalg.inv(T_np2c) @ T_v2c | |
# decompose into new global orient and new transl | |
new_global_orient_mat = T_v2np[:, :3, :3] | |
new_global_orient = rotmat_to_aa(new_global_orient_mat) | |
new_transl = T_v2np[:, :3, 3] | |
assert new_global_orient.shape == (N, 3) | |
assert new_transl.shape == (N, 3) | |
return new_global_orient, new_transl | |