Spaces:
Runtime error
Runtime error
| import copy | |
| import os | |
| from typing import Iterable, Optional, Union | |
| import numpy as np | |
| import torch | |
| from pytorch3d.renderer.cameras import CamerasBase | |
| from detrsmpl.core.cameras import build_cameras | |
| from detrsmpl.core.conventions.cameras.convert_convention import ( | |
| convert_camera_matrix, | |
| convert_world_view, | |
| ) | |
| from detrsmpl.core.conventions.cameras.convert_projection import \ | |
| convert_perspective_to_weakperspective # prevent yapf isort conflict | |
| from detrsmpl.models.body_models.builder import build_body_model | |
| from detrsmpl.utils.transforms import aa_to_rotmat, rotmat_to_aa | |
| def convert_smpl_from_opencv_calibration( | |
| R: Union[np.ndarray, torch.Tensor], | |
| T: Union[np.ndarray, torch.Tensor], | |
| K: Optional[Union[np.ndarray, torch.Tensor]] = None, | |
| resolution: Optional[Union[Iterable[int], int]] = None, | |
| verts: Optional[Union[np.ndarray, torch.Tensor]] = None, | |
| poses: Optional[Union[np.ndarray, torch.Tensor]] = None, | |
| transl: Optional[Union[np.ndarray, torch.Tensor]] = None, | |
| model_path: Optional[str] = None, | |
| betas: Optional[Union[np.ndarray, torch.Tensor]] = None, | |
| model_type: Optional[str] = 'smpl', | |
| gender: Optional[str] = 'neutral'): | |
| """Convert opencv calibration smpl poses&transl parameters to model based | |
| poses&transl or verts. | |
| Args: | |
| R (Union[np.ndarray, torch.Tensor]): (frame, 3, 3) | |
| T (Union[np.ndarray, torch.Tensor]): [(frame, 3) | |
| K (Optional[Union[np.ndarray, torch.Tensor]], optional): | |
| (frame, 3, 3) or (frame, 4, 4). Defaults to None. | |
| resolution (Optional[Union[Iterable[int], int]], optional): | |
| (height, width). Defaults to None. | |
| verts (Optional[Union[np.ndarray, torch.Tensor]], optional): | |
| (frame, num_verts, 3). Defaults to None. | |
| poses (Optional[Union[np.ndarray, torch.Tensor]], optional): | |
| (frame, 72/165). Defaults to None. | |
| transl (Optional[Union[np.ndarray, torch.Tensor]], optional): | |
| (frame, 3). Defaults to None. | |
| model_path (Optional[str], optional): model path. | |
| Defaults to None. | |
| betas (Optional[Union[np.ndarray, torch.Tensor]], optional): | |
| (frame, 10). Defaults to None. | |
| model_type (Optional[str], optional): choose in 'smpl' or 'smplx'. | |
| Defaults to 'smpl'. | |
| gender (Optional[str], optional): choose in 'male', 'female', | |
| 'neutral'. | |
| Defaults to 'neutral'. | |
| Raises: | |
| ValueError: wrong input poses or transl. | |
| Returns: | |
| Tuple[torch.Tensor]: Return converted poses, transl, pred_cam | |
| or verts, pred_cam. | |
| """ | |
| R_, T_ = convert_world_view(R, T) | |
| RT = torch.eye(4, 4)[None] | |
| RT[:, :3, :3] = R_ | |
| RT[:, :3, 3] = T_ | |
| if verts is not None: | |
| poses = None | |
| betas = None | |
| transl = None | |
| else: | |
| assert poses is not None | |
| assert transl is not None | |
| if isinstance(poses, dict): | |
| poses = copy.deepcopy(poses) | |
| for k in poses: | |
| if isinstance(poses[k], np.ndarray): | |
| poses[k] = torch.Tensor(poses[k]) | |
| elif isinstance(poses, np.ndarray): | |
| poses = torch.Tensor(poses) | |
| elif isinstance(poses, torch.Tensor): | |
| poses = poses.clone() | |
| else: | |
| raise ValueError(f'Wrong data type of poses: {type(poses)}.') | |
| if isinstance(transl, np.ndarray): | |
| transl = torch.Tensor(transl) | |
| elif isinstance(transl, torch.Tensor): | |
| transl = transl.clone() | |
| else: | |
| raise ValueError('Should pass valid `transl`.') | |
| transl = transl.view(-1, 3) | |
| if isinstance(betas, np.ndarray): | |
| betas = torch.Tensor(betas) | |
| elif isinstance(betas, torch.Tensor): | |
| betas = betas.clone() | |
| body_model = build_body_model( | |
| dict(type=model_type, | |
| model_path=os.path.join(model_path, model_type), | |
| gender=gender, | |
| model_type=model_type)) | |
| if isinstance(poses, dict): | |
| poses.update({'transl': transl, 'betas': betas}) | |
| else: | |
| if isinstance(poses, np.ndarray): | |
| poses = torch.tensor(poses) | |
| poses = body_model.tensor2dict(full_pose=poses, | |
| transl=transl, | |
| betas=betas) | |
| model_output = body_model(**poses) | |
| verts = model_output['vertices'] | |
| global_orient = poses['global_orient'] | |
| global_orient = rotmat_to_aa(R_ @ aa_to_rotmat(global_orient)) | |
| poses['global_orient'] = global_orient | |
| poses['transl'] = None | |
| verts_rotated = model_output['vertices'] | |
| rotated_pose = body_model.dict2tensor(poses) | |
| verts_converted = verts.clone().view(-1, 3) | |
| verts_converted = RT @ torch.cat( | |
| [verts_converted, | |
| torch.ones(verts_converted.shape[0], 1)], dim=-1).unsqueeze(-1) | |
| verts_converted = verts_converted.squeeze(-1) | |
| verts_converted = verts_converted[:, :3] / verts_converted[:, 3:] | |
| verts_converted = verts_converted.view(verts.shape[0], -1, 3) | |
| num_frame = verts_converted.shape[0] | |
| if poses is not None: | |
| transl = torch.mean(verts_converted - verts_rotated, dim=1) | |
| orig_cam = None | |
| if K is not None: | |
| zmean = torch.mean(verts_converted, dim=1)[:, 2] | |
| K, _, _ = convert_camera_matrix(K, | |
| is_perspective=True, | |
| convention_dst='opencv', | |
| convention_src='opencv', | |
| in_ndc_dst=True, | |
| in_ndc_src=False, | |
| resolution_src=resolution) | |
| K = K.repeat(num_frame, 1, 1) | |
| orig_cam = convert_perspective_to_weakperspective( | |
| K=K, zmean=zmean, in_ndc=True, resolution=resolution) | |
| if poses is not None: | |
| orig_cam[:, 0, 3] += transl[:, 0] | |
| orig_cam[:, 1, 3] += transl[:, 1] | |
| if poses is not None: | |
| return rotated_pose, orig_cam | |
| else: | |
| return verts_converted, orig_cam | |
| def project_points(points3d: Union[np.ndarray, torch.Tensor], | |
| cameras: CamerasBase = None, | |
| resolution: Iterable[int] = None, | |
| K: Union[torch.Tensor, np.ndarray] = None, | |
| R: Union[torch.Tensor, np.ndarray] = None, | |
| T: Union[torch.Tensor, np.ndarray] = None, | |
| convention: str = 'opencv', | |
| in_ndc: bool = False) -> Union[torch.Tensor, np.ndarray]: | |
| """Project 3d points to image. | |
| Args: | |
| points3d (Union[np.ndarray, torch.Tensor]): shape could be (..., 3). | |
| cameras (CamerasBase): pytorch3d cameras or mmhuman3d cameras. | |
| resolution (Iterable[int]): (height, width) for rectangle or width for | |
| square. | |
| K (Union[torch.Tensor, np.ndarray], optional): intrinsic matrix. | |
| Defaults to None. | |
| R (Union[torch.Tensor, np.ndarray], optional): rotation matrix. | |
| Defaults to None. | |
| T (Union[torch.Tensor, np.ndarray], optional): translation matrix. | |
| Defaults to None. | |
| convention (str, optional): camera convention. Defaults to 'opencv'. | |
| in_ndc (bool, optional): whether in NDC. Defaults to False. | |
| Returns: | |
| Union[torch.Tensor, np.ndarray]: transformed points of shape (..., 2). | |
| """ | |
| if cameras is None: | |
| cameras = build_cameras( | |
| dict(type='perspective', | |
| convention=convention, | |
| in_ndc=in_ndc, | |
| resolution=resolution, | |
| K=K, | |
| R=R, | |
| T=T)) | |
| if cameras.get_image_size() is not None: | |
| image_size = cameras.get_image_size() | |
| else: | |
| image_size = resolution | |
| if isinstance(points3d, np.ndarray): | |
| points3d = torch.Tensor(points3d[..., :3]).to(cameras.device) | |
| points2d = cameras.transform_points_screen( | |
| points3d, image_size=image_size).cpu().numpy() | |
| elif isinstance(points3d, torch.Tensor): | |
| points3d = points3d[..., :3].to(cameras.device) | |
| points2d = cameras.transform_points_screen(points3d, | |
| image_size=image_size) | |
| return points2d | |