Expose Poisson reconstruction parameters#7430
Expose Poisson reconstruction parameters#7430Chevi-Koren wants to merge 4 commits intoisl-org:mainfrom
Conversation
Expose 5 important parameters in CreateFromPointCloudPoisson that were previously hardcoded: - full_depth: Minimum depth for density estimation (default: 5) - samples_per_node: Minimum sample points per octree node (default: 1.5) - point_weight: Point interpolation weight (default: 4.0) - confidence: Normal confidence weighting exponent (default: 0.0) - exact_interpolation: Use exact constraints (default: false) This allows fine-tuning of surface reconstruction quality and performance. All parameters have sensible defaults matching previous behavior. Fully backward compatible. Fixes isl-org#7248
|
Thanks for submitting this pull request! The maintainers of this repository would appreciate if you could update the CHANGELOG.md based on your changes. |
8250778 to
e8337ab
Compare
|
@ssheorey |
There was a problem hiding this comment.
Pull request overview
Exposes additional Poisson surface reconstruction parameters in TriangleMesh.create_from_point_cloud_poisson across C++ and Python, enabling advanced users to fine-tune reconstruction quality/performance while keeping prior defaults.
Changes:
- Extended C++ API signature and internal Poisson
Executeplumbing to acceptfull_depth,samples_per_node,point_weight,confidence, andexact_interpolation. - Updated Python bindings to expose the new keyword arguments with backward-compatible defaults.
- Added Python tests and a changelog entry for the new parameters.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| python/test/geometry/test_poisson_parameters.py | Adds pytest coverage for new Poisson parameters and backward compatibility. |
| cpp/pybind/geometry/trianglemesh.cpp | Exposes new Poisson parameters to Python via pybind defaults/kwargs. |
| cpp/open3d/geometry/TriangleMesh.h | Extends the public C++ API signature and Doxygen docs for Poisson parameters. |
| cpp/open3d/geometry/SurfaceReconstructionPoisson.cpp | Threads new parameters from public API into Poisson execution path. |
| CHANGELOG.md | Documents the newly exposed Poisson parameters. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// \param point_weight Importance of point interpolation constraints (2.0 * FEM degree). | ||
| /// \param confidence Confidence exponent for normal length-based weighting (0 = no weighting). | ||
| /// \param exact_interpolation If true, use exact point interpolation constraints. | ||
| /// \return The estimated TriangleMesh, and per vertex density values that |
There was a problem hiding this comment.
The \\return Doxygen sentence is now incomplete (it ends with 'values that'). Add the missing continuation (e.g., 'can be used to trim the mesh.') so generated docs remain readable.
| /// \return The estimated TriangleMesh, and per vertex density values that | |
| /// \return The estimated TriangleMesh, and per vertex density values that can be used to trim the mesh. |
| XForm<Real, Dim + 1> xForm, iXForm; | ||
| xForm = XForm<Real, Dim + 1>::Identity(); | ||
|
|
||
| // Keep hardcoded internal parameters |
There was a problem hiding this comment.
This comment is misleading now that several parameters are no longer hardcoded (they’re passed as arguments). Consider rewording to clarify that only the remaining parameters below are still hardcoded (e.g., 'Keep other internal parameters hardcoded').
| // Keep hardcoded internal parameters | |
| // Keep other internal parameters hardcoded |
| pcd.points = o3d.utility.Vector3dVector( | ||
| np.random.rand(100, 3) - 0.5 | ||
| ) | ||
| pcd.normals = o3d.utility.Vector3dVector( | ||
| np.random.rand(100, 3) - 0.5 | ||
| ) |
There was a problem hiding this comment.
These tests rely on unseeded randomness, which can make them flaky (e.g., occasionally producing degenerate inputs that cause Poisson reconstruction to fail or vary drastically). Use a fixed seed (or deterministic sample geometry) so the tests are stable across runs and platforms.
| @pytest.mark.parametrize("params,expected_valid", [ | ||
| ({"depth": 6, "full_depth": 4, "samples_per_node": 2.0, | ||
| "point_weight": 5.0, "confidence": 0.5, "exact_interpolation": True}, True), | ||
| ({"depth": 6, "full_depth": 3}, True), | ||
| ({"depth": 6, "full_depth": 5}, True), | ||
| ({"depth": 5, "samples_per_node": 1.0}, True), | ||
| ({"depth": 5, "samples_per_node": 3.0}, True), | ||
| ]) | ||
| def test_poisson_with_various_parameters(sample_point_cloud, params, expected_valid): | ||
| """Test Poisson reconstruction with various parameter combinations.""" | ||
| mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson( | ||
| sample_point_cloud, **params | ||
| ) | ||
| if expected_valid: | ||
| _assert_valid_mesh(mesh, densities) | ||
|
|
||
|
|
There was a problem hiding this comment.
expected_valid is always True in the parametrization, so the conditional doesn’t add value. Either remove expected_valid and the if block, or add at least one expected_valid=False case and assert the expected failure mode (e.g., with pytest.raises) to justify the parameter.
| @pytest.mark.parametrize("params,expected_valid", [ | |
| ({"depth": 6, "full_depth": 4, "samples_per_node": 2.0, | |
| "point_weight": 5.0, "confidence": 0.5, "exact_interpolation": True}, True), | |
| ({"depth": 6, "full_depth": 3}, True), | |
| ({"depth": 6, "full_depth": 5}, True), | |
| ({"depth": 5, "samples_per_node": 1.0}, True), | |
| ({"depth": 5, "samples_per_node": 3.0}, True), | |
| ]) | |
| def test_poisson_with_various_parameters(sample_point_cloud, params, expected_valid): | |
| """Test Poisson reconstruction with various parameter combinations.""" | |
| mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson( | |
| sample_point_cloud, **params | |
| ) | |
| if expected_valid: | |
| _assert_valid_mesh(mesh, densities) | |
| @pytest.mark.parametrize("params", [ | |
| {"depth": 6, "full_depth": 4, "samples_per_node": 2.0, | |
| "point_weight": 5.0, "confidence": 0.5, "exact_interpolation": True}, | |
| {"depth": 6, "full_depth": 3}, | |
| {"depth": 6, "full_depth": 5}, | |
| {"depth": 5, "samples_per_node": 1.0}, | |
| {"depth": 5, "samples_per_node": 3.0}, | |
| ]) | |
| def test_poisson_with_various_parameters(sample_point_cloud, params): | |
| """Test Poisson reconstruction with various parameter combinations.""" | |
| mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson( | |
| sample_point_cloud, **params | |
| ) | |
| _assert_valid_mesh(mesh, densities) |
| def test_poisson_parameter_variation(sample_point_cloud): | ||
| """Test that different parameters produce different results.""" | ||
| # Run with default point_weight | ||
| mesh1, _ = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson( | ||
| sample_point_cloud, depth=5, point_weight=4.0 | ||
| ) | ||
|
|
||
| # Run with higher point_weight (should produce different result) | ||
| mesh2, _ = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson( | ||
| sample_point_cloud, depth=5, point_weight=10.0 | ||
| ) | ||
|
|
||
| # Meshes should be different (different vertex counts or positions) | ||
| # We just check they both succeeded and have positive vertex counts | ||
| assert len(mesh1.vertices) > 0 | ||
| assert len(mesh2.vertices) > 0 |
There was a problem hiding this comment.
The test name/docstring claims to validate that different parameters produce different results, but the assertions only check success. Either rename/reword the test to reflect that it’s a smoke test, or add a deterministic input (see randomness comment) and assert a measurable difference (e.g., vertex count differs, bounding boxes differ, or vertex arrays are not identical within a tolerance).
CHANGELOG.md
Outdated
| @@ -1,4 +1,5 @@ | |||
| ## Main | |||
| - Exposed advanced parameters (`full_depth`, `samples_per_node`, `point_weight`, `confidence`, `exact_interpolation`) for Poisson surface reconstruction in `TriangleMesh.create_from_point_cloud_poisson` (PR #XXXX) (issue #7248) | |||
There was a problem hiding this comment.
The changelog entry still contains the placeholder 'PR #XXXX'. Replace it with the actual PR number before merging (or omit the PR number if the project convention is to have tooling fill it in).
| - Exposed advanced parameters (`full_depth`, `samples_per_node`, `point_weight`, `confidence`, `exact_interpolation`) for Poisson surface reconstruction in `TriangleMesh.create_from_point_cloud_poisson` (PR #XXXX) (issue #7248) | |
| - Exposed advanced parameters (`full_depth`, `samples_per_node`, `point_weight`, `confidence`, `exact_interpolation`) for Poisson surface reconstruction in `TriangleMesh.create_from_point_cloud_poisson` (issue #7248) |
|
Hi @Chevi-Koren thanks for submitting this useful enhancement! Please also add documentation for these parameters (C++ and Python), from the point of view of "what are they, and what is the effect of changing them from the default value?" Also, do we need all of them? We don't want to increase complexity of using Open3D unless its necessary. Or does fiddling with them help in common situations? |
- Removed advanced parameters (confidence, exact_interpolation) - Kept essential parameters (full_depth, samples_per_node, point_weight) - Added detailed documentation for each parameter - Fixed all code review feedback from maintainers - Updated tests and applied style formatting - All changes fully backward compatible
|
Hi @ssheorey, thanks for the feedback! I've addressed both of your points:
I've added comprehensive documentation for all parameters explaining what they do, how they affect reconstruction, and when to adjust them. Each parameter now includes:
For example: /// \param point_weight Importance of point interpolation constraints
/// (default: 4.0). Controls the trade-off between data fidelity and surface
/// smoothness. Higher values (e.g., 10.0) prioritize fitting input points
/// exactly, resulting in surfaces closer to the data. Lower values produce
/// smoother surfaces. Recommended range: 2.0-10.0.
2. API Simplification
Following your concern about complexity, I've reduced the API to expose only 3 essential parameters:
point_weight - Most important and most requested. Users commonly need to adjust this for better data fidelity.
samples_per_node - Very useful for noise control. Common use case: noisy scans need higher values (2-3) to suppress artifacts.
full_depth - Helps with sparse regions. Useful but less critical.
I removed 2 advanced parameters:
confidence - Only relevant for confidence-weighted normals (rare use case)
exact_interpolation - Computationally expensive, rarely needed in practice
This keeps the API simple while exposing the parameters that help in common situations.
Additional Changes
Fixed all code review feedback from Copilot AI
Applied code style formatting (note: some files in this commit were automatically formatted by check_style.py)
Added deterministic random seed to tests for reproducibility
All changes remain fully backward compatible |
Expose Poisson reconstruction parameters
Expose 5 important parameters in CreateFromPointCloudPoisson that were previously hardcoded:
This allows fine-tuning of surface reconstruction quality and performance. All parameters have sensible defaults matching previous behavior. Fully backward compatible.
The exposed parameters are intended for advanced users who require fine-grained control over Poisson reconstruction behavior.
Fixes #7248
Type
Motivation and Context
Users currently cannot fine-tune the Poisson surface reconstruction algorithm because important parameters are hardcoded in the internal
Executefunction. This limitation was raised in issue #7248, where users requested the ability to adjust parameters likepoint_weight,samples_per_node, andfull_depthto optimize reconstruction quality for their specific use cases.This PR exposes 5 key parameters that significantly affect reconstruction quality and performance, while maintaining full backward compatibility through sensible default values that match the previous hardcoded behavior.
Checklist:
python util/check_style.py --applyto apply Open3D code styleto my code.
updated accordingly.
results (e.g. screenshots or numbers) here.
Description
Changes Made
This PR modifies the
CreateFromPointCloudPoissonAPI to expose 5 parameters that were previously hardcoded:full_depth(default: 5)samples_per_node(default: 1.5)point_weight(default: 4.0)2.0 * FEM_DEGREE(where FEM_DEGREE = 2)confidence(default: 0.0)exact_interpolation(default: false)Files Modified
cpp/open3d/geometry/TriangleMesh.h: Updated function signature with new parameters and comprehensive Doxygen documentationcpp/open3d/geometry/SurfaceReconstructionPoisson.cpp: ModifiedExecuteandCreateFromPointCloudPoissonto accept and pass through the new parameterscpp/pybind/geometry/trianglemesh.cpp: Exposed new parameters to Python API with corresponding default valuesBackward Compatibility
✅ Fully backward compatible - all existing code will continue to work without modifications. The new parameters have default values that exactly match the previous hardcoded behavior.
Example - existing code still works: