Update Gaussian splatting camera API and world-space parity#518
Update Gaussian splatting camera API and world-space parity#518fwilliams wants to merge 12 commits intoopenvdb:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates FVDB’s Gaussian splatting camera API to cleanly separate camera semantics (CameraModel) from projection implementation choice (ProjectionMethod), and extends world-space rendering to include depth-only and RGBD variants to match the existing world-space RGB path.
Changes:
- Replaced the old projection/distortion API split with
camera_model,projection_method, anddistortion_coeffsacross C++, pybind, Python wrappers, and typing stubs. - Added world-space parity APIs:
render_depths_from_world(...)andrender_images_and_depths_from_world(...). - Expanded/updated CUDA/C++ and Python test coverage for camera-model dispatch, metadata, and world-space depth/RGBD parity.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/test_rasterize_from_world.py | Updates test helper + adds world-space depth/RGBD parity and gradient tests across camera models. |
| tests/unit/test_gaussian_splat_3d.py | Adds new camera API test suite covering dispatch/validation/parity and metadata fields. |
| src/tests/GaussianSplat3dCameraApiTest.cpp | New C++ gtest coverage for camera API dispatch, validation, and world-space parity. |
| src/tests/GaussianCamerasTest.cu | Adds distorted-perspective projection parity test and helpers for OpenCV distortion coefficients. |
| src/tests/CMakeLists.txt | Registers the new GaussianSplat3dCameraApiTest. |
| src/python/GaussianSplatBinding.cpp | Exposes CameraModel + ProjectionMethod and updates GaussianSplat3d bindings + new world-space depth/RGBD entry points. |
| src/fvdb/detail/ops/gsplat/GaussianCameras.cuh | Introduces ProjectionMethod enum. |
| src/fvdb/GaussianSplat3d.h | Updates public C++ API signatures + projected-state metadata, and adds world-space depth/RGBD entry points. |
| src/fvdb/GaussianSplat3d.cpp | Implements shared camera arg validation + dispatch and adds world-space depth/RGBD implementations. |
| fvdb/gaussian_splatting.py | Updates Python wrapper APIs, conversions, metadata accessors, and adds world-space depth/RGBD wrapper methods. |
| fvdb/enums.py | Renames DistortionModel → CameraModel and adds ProjectionMethod. |
| fvdb/_fvdb_cpp.pyi | Updates stubs for new camera/projection API surface and adds world-space depth/RGBD bindings. |
| fvdb/init.pyi | Re-exports CameraModel and ProjectionMethod in typing. |
| fvdb/init.py | Re-exports CameraModel and ProjectionMethod at runtime. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
src/tests/scripts/write_rasterize_forward_test_data.py:72
project_gaussians_for_images(...)call is now passingCameraModel.PINHOLEandsh_degreeas positional arguments, but the Python API signature has insertedprojection_methodanddistortion_coeffsbetween them. As written,sh_degreewill be interpreted asprojection_method, which will raise at runtime or select an unintended method. Passprojection_method/distortion_coeffsexplicitly (or switch to keyword args forcamera_modelandsh_degree_to_use) to keep this script usable for regenerating test data.
projected_gaussians = gs3d.project_gaussians_for_images(
cam_to_world_mats,
projection_mats,
width,
height,
near_plane,
far_plane,
CameraModel.PINHOLE,
sh_degree,
min_radius_2d=0.0,
eps_2d=1e-4,
antialias=True,
)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/tests/scripts/write_rasterize_forward_test_data.py:72
GaussianSplat3d.project_gaussians_for_images(...)signature now includesprojection_methodanddistortion_coeffsimmediately aftercamera_model. This call uses positional arguments beyondfar_plane, sosh_degreewill be interpreted asprojection_method, shifting all subsequent parameters and likely breaking the generated test data. Switch to keyword arguments forcamera_model,projection_method(e.g.AUTO),distortion_coeffs, andsh_degree_to_use(or pass the missing positional placeholders explicitly) to avoid accidental mis-ordering when the API evolves.
projected_gaussians = gs3d.project_gaussians_for_images(
cam_to_world_mats,
projection_mats,
width,
height,
near_plane,
far_plane,
CameraModel.PINHOLE,
sh_degree,
min_radius_2d=0.0,
eps_2d=1e-4,
antialias=True,
)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Replace the public Gaussian camera API with CameraModel and ProjectionMethod so analytic and unscented projection paths share one coherent surface. Add the missing from-world depth/RGBD bindings and wrappers while keeping projection_matrices stable, then update typings and tests to cover the new behavior. Signed-off-by: Francis Williams <francis@fwilliams.info> Made-with: Cursor
Signed-off-by: Francis Williams <francis@fwilliams.info>
Signed-off-by: Francis Williams <francis@fwilliams.info>
Signed-off-by: Francis Williams <francis@fwilliams.info>
Signed-off-by: Francis Williams <francis@fwilliams.info>
2779a3f to
a2ac0de
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
fvdb/gaussian_splatting.py:2114
- The
render_images_from_worlddocstring says to useNonefordistortion_coeffs“for no distortion”, but the new camera validation requiresdistortion_coeffsto be provided for OpenCV camera models (it can be a zero-filled(C, 12)tensor). Update the docstring to reflect the actual contract:distortion_coeffsmust beNonefor PINHOLE/ORTHOGRAPHIC and a(C,12)tensor forCameraModel.OPENCV_*.
:attr:`fvdb.ProjectionMethod.AUTO`.
distortion_coeffs (torch.Tensor | None): Distortion coefficients for OpenCV camera
models. Use ``None`` for no distortion. Expected shape is ``(C, 12)`` with packed
layout ``[k1,k2,k3,k4,k5,k6,p1,p2,s1,s2,s3,s4]``. For camera models that use fewer
coefficients, unused entries should be set to 0.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Centralize shared camera projection validation so empty-camera checks and matrix validation stay consistent across analytic and unscented paths, and drop an unnecessary settings-header dependency. Add a focused C++ regression covering the empty-camera contract. Signed-off-by: Francis Williams <francis@fwilliams.info> Made-with: Cursor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
This PR updates Gaussian splatting camera APIs to separate camera semantics from projection implementation choice, adds world-space render parity for depth and RGBD paths, and finishes the follow-up validation/test cleanup needed to make the new API consistent across C++, Python bindings, Python wrappers, and typing stubs.
What changed
ProjectionType/DistortionModelsplit with explicitCameraModelandProjectionMethodcontrolsProjectedGaussianSplatscarriescamera_modelandprojection_methodrender_depths_from_world(...)andrender_images_and_depths_from_world(...)to match the existing world-space image render pathantialiasis honored consistently in all camera render entrypointsGaussianRenderSettings.hAPI design
The public Gaussian camera API now uses two independent axes:
CameraModel: what camera is being modeledProjectionMethod: how projection is evaluatedProjectionMethod.AUTOremains the default dispatch behavior:PINHOLEandORTHOGRAPHICDistortion coefficients contract
This PR defines the intended contract for
distortion_coeffs:CameraModel.OPENCV_*: a contiguous tensor with shape(C, 12)is requiredCameraModel.PINHOLE/CameraModel.ORTHOGRAPHIC: callers may passNoneor a(C, 12)tensor; if a tensor is provided it is ignored(C, 12)tensor represents "no distortion" for OpenCV camera modelsTesting
Validated with:
conda run -n fvdb black --target-version=py311 --line-length=120 --extend-exclude='wip/' --check fvdb/gaussian_splatting.py tests/unit/test_gaussian_splat_3d.py src/tests/scripts/write_rasterize_forward_test_data.pyconda run -n fvdb ./build.sh install gtestsctest --output-on-failure -R GaussianCamerasTestctest --output-on-failure -R GaussianSplat3dCameraApiTestcd tests && conda run -n fvdb pytest unit/test_gaussian_splat_3d.py -k 'camera_api_validation_errors or pinhole_and_orthographic_ignore_distortion_coeffs_tensor or projection_method_resolution_and_metadata' -vcd tests && conda run -n fvdb pytest unit/test_gaussian_splat_3d.py -v