Spaces:
Sleeping
Sleeping
| """Structural contracts the external scene must satisfy. | |
| These ``runtime_checkable`` Protocols are written so that inria | |
| gaussian-splatting's own ``Scene`` / ``GaussianModel`` / ``Camera`` classes | |
| satisfy them **with no changes** (graphdeco-inria/gaussian-splatting and the | |
| 3DGS-LM fork in ``baselines/3DGS-LM``). Non-inria codebases can either expose | |
| the same attribute names or use the low-level ``OptGS.initialize_from_ply`` / | |
| ``initialize_from_tensors`` entrypoints. | |
| """ | |
| from __future__ import annotations | |
| from typing import Any, Protocol, Sequence, runtime_checkable | |
| class OptGSError(RuntimeError): | |
| """Raised for all OptGS API misuse / unsupported-checkpoint conditions.""" | |
| class GaussiansLike(Protocol): | |
| """An inria ``GaussianModel`` (raw, pre-activation parameter storage).""" | |
| active_sh_degree: int | |
| max_sh_degree: int | |
| _xyz: Any | |
| _features_dc: Any | |
| _features_rest: Any | |
| _scaling: Any | |
| _rotation: Any | |
| _opacity: Any | |
| def save_ply(self, path: str) -> None: ... | |
| def load_ply(self, path: str) -> None: ... | |
| class CameraLike(Protocol): | |
| """An inria ``Camera`` (world->camera ``R,T`` + FoV, COLMAP convention).""" | |
| R: Any | |
| T: Any | |
| FoVx: float | |
| FoVy: float | |
| image_width: int | |
| image_height: int | |
| original_image: Any # [3, H, W] in [0, 1] | |
| class SceneLike(Protocol): | |
| """An inria ``Scene`` holding a ``GaussianModel`` and posed cameras.""" | |
| cameras_extent: float | |
| gaussians: GaussiansLike | |
| def getTrainCameras(self, scale: float = 1.0) -> Sequence[CameraLike]: ... | |
| # Explicit attribute lists drive precise error messages (clearer than a bare | |
| # isinstance failure, which does not say *which* member is missing). | |
| _SCENE_ATTRS = ("cameras_extent", "gaussians") | |
| _SCENE_METHODS = ("getTrainCameras",) | |
| _GAUSSIAN_ATTRS = ( | |
| "active_sh_degree", "max_sh_degree", | |
| "_xyz", "_features_dc", "_features_rest", "_scaling", "_rotation", "_opacity", | |
| ) | |
| _GAUSSIAN_METHODS = ("save_ply", "load_ply") | |
| _CAMERA_ATTRS = ( | |
| "R", "T", "FoVx", "FoVy", "image_width", "image_height", "original_image", | |
| ) | |
| def _missing(obj: object, attrs: tuple[str, ...], methods: tuple[str, ...] = ()) -> list[str]: | |
| miss = [a for a in attrs if not hasattr(obj, a)] | |
| miss += [f"{m}()" for m in methods if not callable(getattr(obj, m, None))] | |
| return miss | |
| def assert_scene_protocol(scene: object) -> None: | |
| """Validate ``scene`` against :class:`SceneLike`; raise a precise error. | |
| Checked structurally (duck-typed) so inria's classes pass unchanged. | |
| """ | |
| miss = _missing(scene, _SCENE_ATTRS, _SCENE_METHODS) | |
| if miss: | |
| raise OptGSError( | |
| f"scene is missing required attribute(s)/method(s): {', '.join(miss)}. " | |
| f"Expected an inria-style Scene (cameras_extent, gaussians, " | |
| f"getTrainCameras()). Use OptGS.initialize_from_ply/" | |
| f"initialize_from_tensors for non-inria codebases." | |
| ) | |
| gm = scene.gaussians | |
| gmiss = _missing(gm, _GAUSSIAN_ATTRS, _GAUSSIAN_METHODS) | |
| if gmiss: | |
| raise OptGSError( | |
| f"scene.gaussians is missing: {', '.join(gmiss)}. Expected an inria " | |
| f"GaussianModel (raw _xyz/_features_dc/_features_rest/_scaling/" | |
| f"_rotation/_opacity + save_ply/load_ply)." | |
| ) | |
| cams = scene.getTrainCameras() | |
| if cams is None or len(cams) == 0: | |
| raise OptGSError("scene.getTrainCameras() returned no cameras.") | |
| cmiss = _missing(cams[0], _CAMERA_ATTRS) | |
| if cmiss: | |
| raise OptGSError( | |
| f"train camera is missing: {', '.join(cmiss)}. Expected an inria " | |
| f"Camera (R, T, FoVx, FoVy, image_width, image_height, " | |
| f"original_image)." | |
| ) | |