Project rays into a 360 panorama (spherical) image.
(
image_size: tuple[int, int], rays_in_cam: npt.NDArray[np.floating]
)
| 124 | |
| 125 | |
| 126 | def spherical_img_from_cam( |
| 127 | image_size: tuple[int, int], rays_in_cam: npt.NDArray[np.floating] |
| 128 | ) -> npt.NDArray[np.floating]: |
| 129 | """Project rays into a 360 panorama (spherical) image.""" |
| 130 | if image_size[0] != image_size[1] * 2: |
| 131 | raise ValueError("Only 360° panoramas are supported.") |
| 132 | if rays_in_cam.ndim != 2 or rays_in_cam.shape[1] != 3: |
| 133 | raise ValueError(f"{rays_in_cam.shape=} but expected (N,3).") |
| 134 | r = rays_in_cam.T |
| 135 | yaw = np.arctan2(r[0], r[2]) |
| 136 | pitch = -np.arctan2(r[1], np.linalg.norm(r[[0, 2]], axis=0)) |
| 137 | u = (1 + yaw / np.pi) / 2 |
| 138 | v = (1 - pitch * 2 / np.pi) / 2 |
| 139 | return np.stack([u, v], -1) * image_size |
| 140 | |
| 141 | |
| 142 | def get_virtual_rotations( |
no outgoing calls
no test coverage detected