| import numpy as np | |
| import torch | |
| from torch import Tensor | |
| import torch.nn.functional as F | |
| from jaxtyping import Float | |
| def transform_points( | |
| T: Float[Tensor, "... d d"], | |
| pts: Float[Tensor, "... n c"] | |
| ) -> Float[Tensor, "... n 3"]: | |
| """ | |
| Args: | |
| T (torch.Tensor): transformation matrix of shape (d, d) | |
| pts (torch.Tensor): Input points of shape (n, c) | |
| """ | |
| if pts.shape[-1] == (T.shape[-1] - 1): | |
| pts = F.pad(pts, (0, 1), value=1) | |
| pts = torch.einsum("...ji,...ni->...nj", T, pts) | |
| return pts[..., :3] | |
| def transform_points_np( | |
| T: Float[np.ndarray, "... d d"], | |
| pts: Float[np.ndarray, "... n c"] | |
| ) -> Float[np.ndarray, "... n 3"]: | |
| """ | |
| Args: | |
| T (torch.Tensor): transformation matrix of shape (d, d) | |
| pts (torch.Tensor): Input points of shape (n, c) | |
| """ | |
| orig_shape = pts.shape | |
| pts = pts.reshape(-1, 3) | |
| if pts.shape[-1] == (T.shape[-1] - 1): | |
| pts = np.pad(pts, ((0, 0), (0, 1)), constant_values=1) | |
| pts = np.einsum("...ji,...ni->...nj", T, pts) | |
| pts = pts[..., :3] | |
| pts = pts.reshape(orig_shape) | |
| return pts | |
| def invert_intrinsics( | |
| K: Float[Tensor, "3 3"] | |
| ): | |
| fx, fy, cx, cy = K[0, 0], K[1, 1], K[0, 2], K[1, 2] | |
| K_inv = torch.tensor([ | |
| [1/fx, 0, -cx/fx], | |
| [0, 1/fy, -cy/fy], | |
| [0, 0, 1 ] | |
| ], device=K.device) | |
| return K_inv | |
| def se3_from_Rt( | |
| R: Float[Tensor, "3 3"], | |
| t: Float[Tensor, "3"] | |
| ) -> Float[Tensor, "4 4"]: | |
| T = torch.eye(4, dtype=R.dtype) | |
| T[:3, :3] = R | |
| T[:3, 3] = t | |
| return T | |
| def invert_se3( | |
| T: Float[Tensor, "4 4"] | |
| ): | |
| R_ = T[:3, :3].transpose(0, 1) | |
| t = T[:3, 3] | |
| t_ = -torch.einsum("ij,j->i", R_, t) | |
| T_ = torch.eye(4, dtype=T.dtype) | |
| T_[:3, :3] = R_ | |
| T_[:3, 3] = t_ | |
| return T_ | |
| def to_4x4( | |
| m: Float[Tensor, "3 3"] | |
| ): | |
| m_ = torch.eye(4, dtype=m.dtype) | |
| m_[:3, :3] = m | |
| return m_ | |
| def project_points( | |
| K: Float[Tensor, "... d d"], | |
| pts: Float[Tensor, "... n c"] | |
| ): | |
| """ | |
| Non-differentiable | |
| """ | |
| if K.shape[-1] == 3: | |
| K = to_4x4(K) | |
| xyz = transform_points(K, pts) | |
| uv = xyz[..., :2] / xyz[..., 2:] | |
| return uv | |