Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion nerfstudio/data/utils/colmap_parsing_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ def write_points3D_binary(points3D, path_to_model_file):
write_next_bytes(fid, pt.id, "Q")
write_next_bytes(fid, pt.xyz.tolist(), "ddd")
write_next_bytes(fid, pt.rgb.tolist(), "BBB")
write_next_bytes(fid, pt.error, "d")
write_next_bytes(fid, float(pt.error.item()), "d")
track_length = pt.image_ids.shape[0]
write_next_bytes(fid, track_length, "Q")
for image_id, point2D_id in zip(pt.image_ids, pt.point2D_idxs):
Expand Down
5 changes: 5 additions & 0 deletions nerfstudio/plugins/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ def discover_methods() -> t.Tuple[t.Dict[str, TrainerConfig], t.Dict[str, str]]:
discovered_entry_points = entry_points(group="nerfstudio.method_configs")
for name in discovered_entry_points.names:
spec = discovered_entry_points[name].load()

# Support callable (function) entry points to avoid circular imports
if callable(spec):
spec = spec()

if not isinstance(spec, MethodSpecification):
CONSOLE.print(
f"[bold yellow]Warning: Could not entry point {spec} as it is not an instance of MethodSpecification"
Expand Down
5 changes: 5 additions & 0 deletions nerfstudio/plugins/registry_dataparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ def discover_dataparsers() -> t.Tuple[t.Dict[str, DataParserConfig], t.Dict[str,
discovered_entry_points = entry_points(group="nerfstudio.dataparser_configs")
for name in discovered_entry_points.names:
spec = discovered_entry_points[name].load()

# Support callable (function) entry points to avoid circular imports
if callable(spec):
spec = spec()

if not isinstance(spec, DataParserSpecification):
CONSOLE.print(
f"[bold yellow]Warning: Could not entry point {spec} as it is not an instance of DataParserSpecification"
Expand Down
23 changes: 19 additions & 4 deletions nerfstudio/process_data/colmap_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,31 @@ def get_colmap_version(colmap_cmd: str, default_version: str = "3.8") -> Version
return Version(default_version)


def get_vocab_tree() -> Path:
def get_vocab_tree(colmap_version: Version) -> Path:
"""Return path to vocab tree. Downloads vocab tree if it doesn't exist.

COLMAP switched from FLANN to faiss for vocabulary tree indexing in 3.12.0
(June 2025). FLANN- and faiss-based trees are mutually incompatible, so the
correct tree format is selected based on the detected COLMAP version, and
each format is cached under a distinct filename so that upgrading COLMAP
never silently serves a stale tree of the wrong format.

Args:
colmap_version: The detected COLMAP version, used to choose the tree format.
Returns:
The path to the vocab tree.
"""
vocab_tree_filename = Path(appdirs.user_data_dir("nerfstudio")) / "vocab_tree.fbow"
if colmap_version >= Version("3.12.0"):
vocab_tree_filename = Path(appdirs.user_data_dir("nerfstudio")) / "vocab_tree_faiss_words32K.bin"
vocab_tree_url = (
"https://github.com/colmap/colmap/releases/download/3.11.1/vocab_tree_faiss_flickr100K_words32K.bin"
)
else:
vocab_tree_filename = Path(appdirs.user_data_dir("nerfstudio")) / "vocab_tree.fbow"
vocab_tree_url = "https://demuc.de/colmap/vocab_tree_flickr100K_words32K.bin"

if not vocab_tree_filename.exists():
r = requests.get("https://demuc.de/colmap/vocab_tree_flickr100K_words32K.bin", stream=True)
r = requests.get(vocab_tree_url, stream=True)
vocab_tree_filename.parent.mkdir(parents=True, exist_ok=True)
with open(vocab_tree_filename, "wb") as f:
total_length = r.headers.get("content-length")
Expand Down Expand Up @@ -143,7 +158,7 @@ def run_colmap(
f"--SiftMatching.use_gpu {int(gpu)}",
]
if matching_method == "vocab_tree":
vocab_tree_filename = get_vocab_tree()
vocab_tree_filename = get_vocab_tree(colmap_version)
feature_matcher_cmd.append(f'--VocabTreeMatching.vocab_tree_path "{vocab_tree_filename}"')
feature_matcher_cmd = " ".join(feature_matcher_cmd)
with status(msg="[bold yellow]Running COLMAP feature matcher...", spinner="runner", verbose=verbose):
Expand Down
Loading