Source code for drtk.transform
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
from typing import List, Optional, Tuple, Union
import torch as th
from drtk.utils import project_points
[docs]
def transform(
v: th.Tensor,
campos: Optional[th.Tensor] = None,
camrot: Optional[th.Tensor] = None,
focal: Optional[th.Tensor] = None,
princpt: Optional[th.Tensor] = None,
K: Optional[th.Tensor] = None,
Rt: Optional[th.Tensor] = None,
distortion_mode: Optional[Union[List[str], str]] = None,
distortion_coeff: Optional[th.Tensor] = None,
fov: Optional[th.Tensor] = None,
) -> th.Tensor:
"""
Projects 3D vertex positions onto the image plane of the camera.
Args:
v (th.Tensor): vertex positions. N x V x 3
campos (Tensor): Camera position. N x 3
camrot (Tensor): Camera rotation matrix. N x 3 x 3
focal (Tensor): Focal length. The upper left 2x2 block of the intrinsic matrix
[[f_x, s], [0, f_y]]. N x 2 x 2
princpt (Tensor): Camera principal point [cx, cy]. N x 2
K (Tensor): Camera intrinsic calibration matrix, N x 3 x 3
Rt (Tensor): Camera extrinsic matrix. N x 3 x 4 or N x 4 x 4
distortion_mode (List[str]): Names of the distortion modes.
distortion_coeff (Tensor): Distortion coefficients. N x 4
fov (Tensor): Valid field of view of the distortion model. N x 1
Returns:
Vertex positions projected onto the image plane of the camera. The last dimension has
still size 3. The first two components are the x and y coordinates on the image plane,
and the z is z component of the vertex positions in the camera frame. The latter is used
for depth values that are written to the z-buffer. N x V x 3
.. warning::
You must specify either ``K`` (intrinsic matrix) or both ``focal`` and ``princpt``
(focal length and principal point).
Additionally, you must provide either ``Rt`` (extrinsic matrix) or both ``campos``
(camera position) and ``camrot`` (camera rotation).
.. note::
If we split ``Rt`` of shape N x 3 x 4 into ``R`` of shape N x 3 x 3 and ``t`` of
shape N x 3 x 1, then: ``camrot`` is ``R``, and ``campos`` is ``-R.T @ t``.
"""
v_pix, _ = transform_with_v_cam(
v, campos, camrot, focal, princpt, K, Rt, distortion_mode, distortion_coeff, fov
)
return v_pix
[docs]
def transform_with_v_cam(
v: th.Tensor,
campos: Optional[th.Tensor] = None,
camrot: Optional[th.Tensor] = None,
focal: Optional[th.Tensor] = None,
princpt: Optional[th.Tensor] = None,
K: Optional[th.Tensor] = None,
Rt: Optional[th.Tensor] = None,
distortion_mode: Optional[Union[List[str], str]] = None,
distortion_coeff: Optional[th.Tensor] = None,
fov: Optional[th.Tensor] = None,
) -> Tuple[th.Tensor, th.Tensor]:
"""
Same as transform, but also returns the camera-space coordinates.
In most cases it is not needed, but renderlayer depends on it
"""
if not ((camrot is not None and campos is not None) ^ (Rt is not None)):
raise ValueError("You must provide exactly one of Rt or (campos, camrot).")
if not ((focal is not None and princpt is not None) ^ (K is not None)):
raise ValueError("You must provide exactly one of K or (focal, princpt).")
if campos is None:
assert Rt is not None
camrot = Rt[:, :3, :3]
campos = -(camrot.transpose(-2, -1) @ Rt[:, :3, 3:4])[..., 0]
if focal is None:
assert K is not None
focal = K[:, :2, :2]
princpt = K[:, :2, 2]
assert camrot is not None
assert princpt is not None
# Compute camera-space 3D coordinates and 2D pixel-space projections.
v_pix, v_cam = project_points(
v, campos, camrot, focal, princpt, distortion_mode, distortion_coeff, fov
)
return v_pix, v_cam