(
path: Path,
device: torch.device = torch.device("cpu"),
reorder: bool = True,
)
| 112 | |
| 113 | |
| 114 | def read_colmap_model( |
| 115 | path: Path, |
| 116 | device: torch.device = torch.device("cpu"), |
| 117 | reorder: bool = True, |
| 118 | ) -> tuple[ |
| 119 | Float[Tensor, "frame 4 4"], # extrinsics |
| 120 | Float[Tensor, "frame 3 3"], # intrinsics |
| 121 | list[str], # image names |
| 122 | ]: |
| 123 | model = read_model(path) |
| 124 | if model is None: |
| 125 | raise FileNotFoundError() |
| 126 | cameras, images, _ = model |
| 127 | |
| 128 | all_extrinsics = [] |
| 129 | all_intrinsics = [] |
| 130 | all_image_names = [] |
| 131 | |
| 132 | for image in images.values(): |
| 133 | camera: Camera = cameras[image.camera_id] |
| 134 | |
| 135 | # Read the camera intrinsics. |
| 136 | intrinsics = torch.eye(3, dtype=torch.float32, device=device) |
| 137 | if camera.model == "SIMPLE_PINHOLE": |
| 138 | fx, cx, cy = camera.params |
| 139 | fy = fx |
| 140 | elif camera.model == "PINHOLE": |
| 141 | fx, fy, cx, cy = camera.params |
| 142 | intrinsics[0, 0] = fx |
| 143 | intrinsics[1, 1] = fy |
| 144 | intrinsics[0, 2] = cx |
| 145 | intrinsics[1, 2] = cy |
| 146 | intrinsics[0] /= camera.width |
| 147 | intrinsics[1] /= camera.height |
| 148 | all_intrinsics.append(intrinsics) |
| 149 | |
| 150 | # Read the camera extrinsics. |
| 151 | qw, qx, qy, qz = image.qvec |
| 152 | w2c = torch.eye(4, dtype=torch.float32, device=device) |
| 153 | rotation = R.from_quat([qx, qy, qz, qw]).as_matrix() |
| 154 | w2c[:3, :3] = torch.tensor(rotation, dtype=torch.float32, device=device) |
| 155 | w2c[:3, 3] = torch.tensor(image.tvec, dtype=torch.float32, device=device) |
| 156 | extrinsics = w2c.inverse() |
| 157 | all_extrinsics.append(extrinsics) |
| 158 | |
| 159 | # Read the image name. |
| 160 | all_image_names.append(image.name) |
| 161 | |
| 162 | # Since COLMAP shuffles the images, we generally want to re-order them according |
| 163 | # to their file names so that they form a video again. |
| 164 | if reorder: |
| 165 | ordered = sorted([(name, index) for index, name in enumerate(all_image_names)]) |
| 166 | indices = torch.tensor([index for _, index in ordered]) |
| 167 | all_extrinsics = [all_extrinsics[index] for index in indices] |
| 168 | all_intrinsics = [all_intrinsics[index] for index in indices] |
| 169 | all_image_names = [all_image_names[index] for index in indices] |
| 170 | |
| 171 | return torch.stack(all_extrinsics), torch.stack(all_intrinsics), all_image_names |
no outgoing calls
no test coverage detected