|
4 | 4 | # This source code is licensed under the BSD-style license found in the
|
5 | 5 | # LICENSE file in the root directory of this source tree.
|
6 | 6 |
|
| 7 | +from typing import Tuple |
| 8 | + |
7 | 9 | import torch
|
8 | 10 |
|
9 | 11 | from ..renderer import PerspectiveCameras
|
10 |
| -from ..transforms import so3_exponential_map |
| 12 | +from ..transforms import so3_exponential_map, so3_log_map |
11 | 13 |
|
12 | 14 |
|
13 | 15 | def cameras_from_opencv_projection(
|
@@ -35,7 +37,7 @@ def cameras_from_opencv_projection(
|
35 | 37 | followed by the homogenization of `x_screen_opencv`.
|
36 | 38 |
|
37 | 39 | Note:
|
38 |
| - The parameters `rvec, tvec, camera_matrix` correspond e.g. to the inputs |
| 40 | + The parameters `rvec, tvec, camera_matrix` correspond, e.g., to the inputs |
39 | 41 | of `cv2.projectPoints`, or to the ouputs of `cv2.calibrateCamera`.
|
40 | 42 |
|
41 | 43 | Args:
|
@@ -74,3 +76,51 @@ def cameras_from_opencv_projection(
|
74 | 76 | focal_length=focal_pytorch3d,
|
75 | 77 | principal_point=p0_pytorch3d,
|
76 | 78 | )
|
| 79 | + |
| 80 | + |
| 81 | +def opencv_from_cameras_projection( |
| 82 | + cameras: PerspectiveCameras, |
| 83 | + image_size: torch.Tensor, |
| 84 | +) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]: |
| 85 | + """ |
| 86 | + Converts a batch of `PerspectiveCameras` into OpenCV-convention |
| 87 | + axis-angle rotation vectors `rvec`, translation vectors `tvec`, and the camera |
| 88 | + calibration matrices `camera_matrix`. This operation is exactly the inverse |
| 89 | + of `cameras_from_opencv_projection`. |
| 90 | +
|
| 91 | + Note: |
| 92 | + The parameters `rvec, tvec, camera_matrix` correspond, e.g., to the inputs |
| 93 | + of `cv2.projectPoints`, or to the ouputs of `cv2.calibrateCamera`. |
| 94 | +
|
| 95 | + Args: |
| 96 | + cameras: A batch of `N` cameras in the PyTorch3D convention. |
| 97 | + image_size: A tensor of shape `(N, 2)` containing the sizes of the images |
| 98 | + (height, width) attached to each camera. |
| 99 | +
|
| 100 | + Returns: |
| 101 | + rvec: A batch of axis-angle rotation vectors of shape `(N, 3)`. |
| 102 | + tvec: A batch of translation vectors of shape `(N, 3)`. |
| 103 | + camera_matrix: A batch of camera calibration matrices of shape `(N, 3, 3)`. |
| 104 | + """ |
| 105 | + R_pytorch3d = cameras.R |
| 106 | + T_pytorch3d = cameras.T |
| 107 | + focal_pytorch3d = cameras.focal_length |
| 108 | + p0_pytorch3d = cameras.principal_point |
| 109 | + T_pytorch3d[:, :2] *= -1 # pyre-ignore |
| 110 | + R_pytorch3d[:, :, :2] *= -1 # pyre-ignore |
| 111 | + tvec = T_pytorch3d.clone() # pyre-ignore |
| 112 | + R = R_pytorch3d.permute(0, 2, 1) # pyre-ignore |
| 113 | + |
| 114 | + # Retype the image_size correctly and flip to width, height. |
| 115 | + image_size_wh = image_size.to(R).flip(dims=(1,)) |
| 116 | + |
| 117 | + principal_point = (-p0_pytorch3d + 1.0) * (0.5 * image_size_wh) # pyre-ignore |
| 118 | + focal_length = focal_pytorch3d * (0.5 * image_size_wh) |
| 119 | + |
| 120 | + camera_matrix = torch.zeros_like(R) |
| 121 | + camera_matrix[:, :2, 2] = principal_point |
| 122 | + camera_matrix[:, 2, 2] = 1.0 |
| 123 | + camera_matrix[:, 0, 0] = focal_length[:, 0] |
| 124 | + camera_matrix[:, 1, 1] = focal_length[:, 1] |
| 125 | + rvec = so3_log_map(R) |
| 126 | + return rvec, tvec, camera_matrix |
0 commit comments