Source code for pytorch3d.utils.camera_conversions

# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

# pyre-unsafe

from typing import Tuple

import torch

from ..renderer import PerspectiveCameras
from ..renderer.camera_conversions import (
    _cameras_from_opencv_projection,
    _opencv_from_cameras_projection,
    _pulsar_from_cameras_projection,
    _pulsar_from_opencv_projection,
)


[docs] def cameras_from_opencv_projection( R: torch.Tensor, tvec: torch.Tensor, camera_matrix: torch.Tensor, image_size: torch.Tensor, ) -> PerspectiveCameras: """ Converts a batch of OpenCV-conventioned cameras parametrized with the rotation matrices `R`, translation vectors `tvec`, and the camera calibration matrices `camera_matrix` to `PerspectiveCameras` in PyTorch3D convention. More specifically, the conversion is carried out such that a projection of a 3D shape to the OpenCV-conventioned screen of size `image_size` results in the same image as a projection with the corresponding PyTorch3D camera to the NDC screen convention of PyTorch3D. More specifically, the OpenCV convention projects points to the OpenCV screen space as follows:: x_screen_opencv = camera_matrix @ (R @ x_world + tvec) followed by the homogenization of `x_screen_opencv`. Note: The parameters `R, tvec, camera_matrix` correspond to the inputs of `cv2.projectPoints(x_world, rvec, tvec, camera_matrix, [])`, where `rvec` is an axis-angle vector that can be obtained from the rotation matrix `R` expected here by calling the `so3_log_map` function. Correspondingly, `R` can be obtained from `rvec` by calling `so3_exp_map`. Args: R: A batch of rotation matrices of shape `(N, 3, 3)`. tvec: A batch of translation vectors of shape `(N, 3)`. camera_matrix: A batch of camera calibration matrices of shape `(N, 3, 3)`. image_size: A tensor of shape `(N, 2)` containing the sizes of the images (height, width) attached to each camera. Returns: cameras_pytorch3d: A batch of `N` cameras in the PyTorch3D convention. """ return _cameras_from_opencv_projection(R, tvec, camera_matrix, image_size)
[docs] def opencv_from_cameras_projection( cameras: PerspectiveCameras, image_size: torch.Tensor, ) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]: """ Converts a batch of `PerspectiveCameras` into OpenCV-convention rotation matrices `R`, translation vectors `tvec`, and the camera calibration matrices `camera_matrix`. This operation is exactly the inverse of `cameras_from_opencv_projection`. Note: The outputs `R, tvec, camera_matrix` correspond to the inputs of `cv2.projectPoints(x_world, rvec, tvec, camera_matrix, [])`, where `rvec` is an axis-angle vector that can be obtained from the rotation matrix `R` output here by calling the `so3_log_map` function. Correspondingly, `R` can be obtained from `rvec` by calling `so3_exp_map`. Args: cameras: A batch of `N` cameras in the PyTorch3D convention. image_size: A tensor of shape `(N, 2)` containing the sizes of the images (height, width) attached to each camera. return_as_rotmat (bool): If set to True, return the full 3x3 rotation matrices. Otherwise, return an axis-angle vector (default). Returns: R: A batch of rotation matrices of shape `(N, 3, 3)`. tvec: A batch of translation vectors of shape `(N, 3)`. camera_matrix: A batch of camera calibration matrices of shape `(N, 3, 3)`. """ return _opencv_from_cameras_projection(cameras, image_size)
[docs] def pulsar_from_opencv_projection( R: torch.Tensor, tvec: torch.Tensor, camera_matrix: torch.Tensor, image_size: torch.Tensor, znear: float = 0.1, ) -> torch.Tensor: """ Convert OpenCV style camera parameters to Pulsar style camera parameters. Note: * Pulsar does NOT support different focal lengths for x and y. For conversion, we use the average of fx and fy. * The Pulsar renderer MUST use a left-handed coordinate system for this mapping to work. * The resulting image will be vertically flipped - which has to be addressed AFTER rendering by the user. * The parameters `R, tvec, camera_matrix` correspond to the outputs of `cv2.decomposeProjectionMatrix`. Args: R: A batch of rotation matrices of shape `(N, 3, 3)`. tvec: A batch of translation vectors of shape `(N, 3)`. camera_matrix: A batch of camera calibration matrices of shape `(N, 3, 3)`. image_size: A tensor of shape `(N, 2)` containing the sizes of the images (height, width) attached to each camera. znear (float): The near clipping value to use for Pulsar. Returns: cameras_pulsar: A batch of `N` Pulsar camera vectors in the Pulsar convention `(N, 13)` (3 translation, 6 rotation, focal_length, sensor_width, c_x, c_y). """ return _pulsar_from_opencv_projection(R, tvec, camera_matrix, image_size, znear)
[docs] def pulsar_from_cameras_projection( cameras: PerspectiveCameras, image_size: torch.Tensor, ) -> torch.Tensor: """ Convert PyTorch3D `PerspectiveCameras` to Pulsar style camera parameters. Note: * Pulsar does NOT support different focal lengths for x and y. For conversion, we use the average of fx and fy. * The Pulsar renderer MUST use a left-handed coordinate system for this mapping to work. * The resulting image will be vertically flipped - which has to be addressed AFTER rendering by the user. Args: cameras: A batch of `N` cameras in the PyTorch3D convention. image_size: A tensor of shape `(N, 2)` containing the sizes of the images (height, width) attached to each camera. Returns: cameras_pulsar: A batch of `N` Pulsar camera vectors in the Pulsar convention `(N, 13)` (3 translation, 6 rotation, focal_length, sensor_width, c_x, c_y). """ return _pulsar_from_cameras_projection(cameras, image_size)