4
0
mirror of https://github.com/nerfstudio-project/nerfstudio.git synced 2026-11-11 02:24:38 +08:00

Revisiting #1504 and fix colmap world coordinate transform (#2793)

fix colmap world coordinate transform
This commit is contained in:
J.Y 2024-01-19 00:08:19 -05:00 committed by GitHub
parent 46847ab56b
commit 25a00a09ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 18 deletions

View File

@ -64,6 +64,12 @@ class ColmapDataParserConfig(DataParserConfig):
"""The method to use to center the poses."""
auto_scale_poses: bool = True
"""Whether to automatically scale the poses to fit in +/- 1 bounding box."""
assume_colmap_world_coordinate_convention: bool = True
"""Colmap optimized world often have y direction of the first camera pointing towards down direction,
while nerfstudio world set z direction to be up direction for viewer. Therefore, we usually need to apply an extra
transform when orientation_method=none. This parameter has no effects if orientation_method is set other than none.
When this parameter is set to False, no extra transform is applied when reading data from colmap.
"""
eval_mode: Literal["fraction", "filename", "interval", "all"] = "interval"
"""
The method to use for splitting the dataset into train and eval.
@ -154,10 +160,10 @@ class ColmapDataParser(DataParser):
c2w = np.linalg.inv(w2c)
# Convert from COLMAP's camera coordinate system (OpenCV) to ours (OpenGL)
c2w[0:3, 1:3] *= -1
# Why do we want to flip Z with a handedness transform?
# See https://github.com/nerfstudio-project/nerfstudio/issues/1504
c2w = c2w[np.array([1, 0, 2, 3]), :]
c2w[2, :] *= -1
if self.config.assume_colmap_world_coordinate_convention:
# world coordinate transform: map colmap gravity guess (-y) to nerfstudio convention (+z)
c2w = c2w[np.array([0, 2, 1, 3]), :]
c2w[2, :] *= -1
frame = {
"file_path": (self.config.data / self.config.images_path / im_data.name).as_posix(),
@ -181,12 +187,12 @@ class ColmapDataParser(DataParser):
out = {}
out["frames"] = frames
# Why do we want to flip Z with a handedness transform?
# See https://github.com/nerfstudio-project/nerfstudio/issues/1504
applied_transform = np.eye(4)[:3, :]
applied_transform = applied_transform[np.array([1, 0, 2]), :]
applied_transform[2, :] *= -1
out["applied_transform"] = applied_transform.tolist()
if self.config.assume_colmap_world_coordinate_convention:
# world coordinate transform: map colmap gravity guess (-y) to nerfstudio convention (+z)
applied_transform = np.eye(4)[:3, :]
applied_transform = applied_transform[np.array([0, 2, 1]), :]
applied_transform[2, :] *= -1
out["applied_transform"] = applied_transform.tolist()
out["camera_model"] = camera_model
assert len(frames) > 0, "No images found in the colmap model"
return out
@ -304,7 +310,6 @@ class ColmapDataParser(DataParser):
if self.config.auto_scale_poses:
scale_factor /= float(torch.max(torch.abs(poses[:, :3, 3])))
scale_factor *= self.config.scale_factor
poses[:, :3, 3] *= scale_factor
# Choose image_filenames and poses based on split, but after auto orient and scaling the poses.

View File

@ -391,6 +391,7 @@ def colmap_to_json(
camera_mask_path: Optional[Path] = None,
image_id_to_depth_path: Optional[Dict[int, Path]] = None,
image_rename_map: Optional[Dict[str, str]] = None,
keep_original_world_coordinate: bool = False,
) -> int:
"""Converts COLMAP's cameras.bin and images.bin to a JSON file.
@ -401,7 +402,9 @@ def colmap_to_json(
camera_mask_path: Path to the camera mask.
image_id_to_depth_path: When including sfm-based depth, embed these depth file paths in the exported json
image_rename_map: Use these image names instead of the names embedded in the COLMAP db
keep_original_world_coordinate: If True, no extra transform will be applied to world coordinate.
Colmap optimized world often have y direction of the first camera pointing towards down direction,
while nerfstudio world set z direction to be up direction for viewer.
Returns:
The number of registered images.
"""
@ -430,8 +433,9 @@ def colmap_to_json(
c2w = np.linalg.inv(w2c)
# Convert from COLMAP's camera coordinate system (OpenCV) to ours (OpenGL)
c2w[0:3, 1:3] *= -1
c2w = c2w[np.array([1, 0, 2, 3]), :]
c2w[2, :] *= -1
if not keep_original_world_coordinate:
c2w = c2w[np.array([0, 2, 1, 3]), :]
c2w[2, :] *= -1
name = im_data.name
if image_rename_map is not None:
@ -455,10 +459,11 @@ def colmap_to_json(
out = parse_colmap_camera_params(cam_id_to_camera[1])
out["frames"] = frames
applied_transform = np.eye(4)[:3, :]
applied_transform = applied_transform[np.array([1, 0, 2]), :]
applied_transform[2, :] *= -1
out["applied_transform"] = applied_transform.tolist()
if not keep_original_world_coordinate:
applied_transform = np.eye(4)[:3, :]
applied_transform = applied_transform[np.array([0, 2, 1]), :]
applied_transform[2, :] *= -1
out["applied_transform"] = applied_transform.tolist()
with open(output_dir / "transforms.json", "w", encoding="utf-8") as f:
json.dump(out, f, indent=4)