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 jo
(global_orient, transl, pelvis, extrinsic)
| 57 | |
| 58 | |
| 59 | def batch_transform_to_camera_frame(global_orient, transl, pelvis, extrinsic): |
| 60 | """Transform body model parameters to camera frame by batch. |
| 61 | |
| 62 | Args: |
| 63 | global_orient (np.ndarray): shape (N, 3). Only global_orient and |
| 64 | transl needs to be updated in the rigid transformation |
| 65 | transl (np.ndarray): shape (N, 3). |
| 66 | pelvis (np.ndarray): shape (N, 3). 3D joint location of pelvis |
| 67 | This is necessary to eliminate the offset from SMPL |
| 68 | canonical space origin to pelvis, because the global orient |
| 69 | is conducted around the pelvis, not the canonical space origin |
| 70 | extrinsic (np.ndarray): shape (4, 4). Transformation matrix |
| 71 | from world frame to camera frame |
| 72 | Returns: |
| 73 | (new_gloabl_orient, new_transl) |
| 74 | new_gloabl_orient: transformed global orient |
| 75 | new_transl: transformed transl |
| 76 | """ |
| 77 | N = len(global_orient) |
| 78 | assert global_orient.shape == (N, 3) |
| 79 | assert transl.shape == (N, 3) |
| 80 | assert pelvis.shape == (N, 3) |
| 81 | |
| 82 | # take out the small offset from smpl origin to pelvis |
| 83 | transl_offset = pelvis - transl |
| 84 | T_p2w = np.eye(4).reshape(1, 4, 4).repeat(N, axis=0) |
| 85 | T_p2w[:, :3, 3] = transl_offset |
| 86 | |
| 87 | # camera extrinsic: transformation from world frame to camera frame |
| 88 | T_w2c = extrinsic |
| 89 | |
| 90 | # smpl transformation: from vertex frame to world frame |
| 91 | T_v2p = np.eye(4).reshape(1, 4, 4).repeat(N, axis=0) |
| 92 | global_orient_mat = aa_to_rotmat(global_orient) |
| 93 | T_v2p[:, :3, :3] = global_orient_mat |
| 94 | T_v2p[:, :3, 3] = transl |
| 95 | |
| 96 | # compute combined transformation from vertex to world |
| 97 | T_v2w = T_p2w @ T_v2p |
| 98 | |
| 99 | # compute transformation from vertex to camera |
| 100 | T_v2c = T_w2c @ T_v2w |
| 101 | |
| 102 | # decompose vertex to camera transformation |
| 103 | # np: new pelvis frame |
| 104 | # T_v2c = T_np2c x T_v2np |
| 105 | T_np2c = T_p2w |
| 106 | T_v2np = np.linalg.inv(T_np2c) @ T_v2c |
| 107 | |
| 108 | # decompose into new global orient and new transl |
| 109 | new_global_orient_mat = T_v2np[:, :3, :3] |
| 110 | new_global_orient = rotmat_to_aa(new_global_orient_mat) |
| 111 | new_transl = T_v2np[:, :3, 3] |
| 112 | |
| 113 | assert new_global_orient.shape == (N, 3) |
| 114 | assert new_transl.shape == (N, 3) |
| 115 | |
| 116 | return new_global_orient, new_transl |
no test coverage detected