From f3f42692aa17c937a0578a47aabd1dfa86b8da1f Mon Sep 17 00:00:00 2001 From: wyyyz1937365497 Date: Thu, 5 Mar 2026 19:30:54 +0800 Subject: [PATCH 1/3] =?UTF-8?q?```=20feat(plugins):=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=8F=AF=E8=B0=83=E7=94=A8=E5=85=A5=E5=8F=A3=E7=82=B9=E4=BB=A5?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E5=BE=AA=E7=8E=AF=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在插件注册表中添加对函数入口点的支持,通过检测并调用可调用对象来避免循环导入问题。 这使得入口点可以作为函数定义,而不是直接的类实例,从而提高模块间的解耦性。 ``` --- nerfstudio/plugins/registry.py | 5 +++++ nerfstudio/plugins/registry_dataparser.py | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/nerfstudio/plugins/registry.py b/nerfstudio/plugins/registry.py index f50550f74b..380fab25f5 100644 --- a/nerfstudio/plugins/registry.py +++ b/nerfstudio/plugins/registry.py @@ -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" diff --git a/nerfstudio/plugins/registry_dataparser.py b/nerfstudio/plugins/registry_dataparser.py index 6b1e34a0f3..1d7011356a 100644 --- a/nerfstudio/plugins/registry_dataparser.py +++ b/nerfstudio/plugins/registry_dataparser.py @@ -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" From 8709e2d857b03bd10d443464db37c72abfe48662 Mon Sep 17 00:00:00 2001 From: wyyyz1937365497 Date: Sat, 1 Aug 2026 13:45:48 +0800 Subject: [PATCH 2/3] fix(process_data): use faiss vocab tree for COLMAP >= 3.12.0 COLMAP switched from FLANN to faiss for vocabulary tree indexing in 3.12.0 (June 2025). The FLANN-based tree that nerfstudio auto-downloads is incompatible with faiss-based COLMAP, causing `vocab_tree_matcher` (the default matching method) to crash: Check failed: file_version == 1 (32762 vs. 1) Failed to read faiss index. `get_vocab_tree()` now selects the correct tree format based on the detected COLMAP version, downloading the faiss-based tree from the official COLMAP 3.11.1 release for COLMAP >= 3.12.0 and keeping the legacy FLANN tree for older versions. Each format is cached under a distinct filename so that upgrading COLMAP never silently serves a stale tree of the wrong format. Fixes #3664 --- nerfstudio/process_data/colmap_utils.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/nerfstudio/process_data/colmap_utils.py b/nerfstudio/process_data/colmap_utils.py index 1d9405c81a..1ae13639eb 100644 --- a/nerfstudio/process_data/colmap_utils.py +++ b/nerfstudio/process_data/colmap_utils.py @@ -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") @@ -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): From 98e6b30e2986ea77844ccabf8c59d42cfe1099cb Mon Sep 17 00:00:00 2001 From: wyyyz1937365497 Date: Sat, 1 Aug 2026 14:11:45 +0800 Subject: [PATCH 3/3] fix(process_data): handle numpy array in write_points3D_binary error field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `read_points3D_binary` stores `error` as a numpy array, but `write_points3D_binary` passed it directly to `struct.pack("