Reconstruction¶
Triangulation¶
- aquamvs.triangulate_pair(model_ref, model_src, matches, min_angle=2.0, max_reproj_error=3.0)[source]¶
Triangulate 3D points from matched features between two cameras.
For each pair of matched keypoints, casts rays through both projection models and finds the point of closest approach. Applies quality filtering to reject unreliable triangulations.
- Parameters:
model_ref (ProjectionModel) – Projection model for the reference camera.
model_src (ProjectionModel) – Projection model for the source camera.
matches (dict[str, Tensor]) – Matches dict from match_pair(). Keys: “ref_keypoints”: (M, 2) pixel coords in reference image. “src_keypoints”: (M, 2) pixel coords in source image. “scores”: (M,) match confidence scores.
min_angle (float) – Minimum intersection angle in degrees. Rejects triangulations from nearly-parallel rays. Default: 2.0 degrees.
max_reproj_error (float) – Maximum reprojection error in pixels. Rejects points that don’t reproject within this distance of the original keypoints. Default: 3.0 pixels.
- Returns:
"points_3d": shape (M, 3), float32 – triangulated world points"scores": shape (M,), float32 – match confidence (passed through)"ref_pixels": shape (M, 2), float32 – reference pixel coords"src_pixels": shape (M, 2), float32 – source pixel coords"valid": shape (M,), bool – True if triangulation succeeded
Invalid entries in points_3d are zeros (masked by valid). Returns empty tensors if M=0.
- Return type:
Dict with keys
- aquamvs.triangulate_all_pairs(projection_models, all_matches)[source]¶
Triangulate 3D points from all matched camera pairs.
Iterates over all pairs, triangulates each, and concatenates the results into a single sparse point cloud. Points that fail triangulation are excluded.
- Parameters:
- Returns:
"points_3d": shape (N_total, 3), float32 – all valid triangulated points"scores": shape (N_total,), float32 – match confidence scores
Where N_total is the sum of valid triangulated points across all pairs. Returns empty tensors if no valid points.
- Return type:
Dict with keys
- aquamvs.triangulate_rays(rays)[source]¶
Find the 3D point minimizing sum of squared distances to all rays.
Uses the closed-form linear least squares solution. For each ray (origin o_i, direction d_i), the distance from a point P to the ray is minimized by solving the normal equations.
- Parameters:
rays (list[tuple[Tensor, Tensor]]) – List of (origin, direction) tuples. Each origin is shape (3,), each direction is shape (3,) unit vector. Must have at least 2 rays.
- Returns:
3D point in world frame, shape (3,), float32.
- Raises:
ValueError – If fewer than 2 rays provided or system is degenerate (e.g., parallel rays).
- Return type:
- aquamvs.filter_sparse_cloud(sparse_cloud, water_z, max_depth=2.0)[source]¶
Filter triangulated points by physical plausibility.
Removes points that are above the water surface (physically impossible for refracted rays) and extreme depth outliers.
- Parameters:
sparse_cloud (dict[str, Tensor]) – Sparse cloud from triangulate_all_pairs(). Must contain “points_3d” (N, 3) and “scores” (N,).
water_z (float) – Z-coordinate of water surface in world frame. Points must have Z > water_z (below surface in Z-down frame).
max_depth (float) – Maximum depth below water surface in meters. Points with Z > water_z + max_depth are rejected as outliers.
- Returns:
Filtered sparse cloud dict with same keys but fewer points. Returns empty tensors if all points are filtered out.
- Return type:
- aquamvs.compute_depth_ranges(projection_models, sparse_cloud, margin=0.05)[source]¶
Compute per-camera depth ranges from sparse triangulated points.
For each camera, casts rays from the camera to each sparse 3D point, computes the ray depth (distance along the refracted ray from origin), and returns the [d_min - margin, d_max + margin] range.
- Parameters:
projection_models (dict[str, ProjectionModel]) – Camera name to ProjectionModel mapping.
sparse_cloud (dict[str, Tensor]) – Sparse point cloud from triangulate_all_pairs(). Must contain “points_3d” (N, 3).
margin (float) – Margin added to each side of the depth range (meters). Corresponds to DenseStereoConfig.depth_margin.
- Returns:
Dict mapping camera name to (d_min, d_max) tuple. d_min and d_max are in ray-depth space (meters along the refracted ray). If a camera has no visible points, uses a fallback range.
- Return type:
Depth Fusion¶
- aquamvs.filter_depth_map(ref_name, ref_model, ref_depth, ref_confidence, target_names, target_models, target_depths, config)[source]¶
Filter a depth map by cross-view geometric consistency.
For each valid pixel in the reference depth map, reprojects into each target camera and checks depth agreement. Pixels consistent with fewer than min_consistent_views other cameras are invalidated.
- Parameters:
ref_name (str) – Reference camera name.
ref_model (ProjectionModel) – Projection model for the reference camera.
ref_depth (Tensor) – Reference depth map, shape (H, W), float32. NaN = invalid.
ref_confidence (Tensor) – Reference confidence map, shape (H, W), float32.
target_names (list[str]) – List of other camera names to check against.
target_models (dict[str, ProjectionModel]) – Camera name to ProjectionModel mapping.
target_depths (dict[str, Tensor]) – Camera name to depth map (H, W) mapping.
config (ReconstructionConfig) – Fusion configuration.
- Returns:
- Depth map with inconsistent pixels set to NaN,
shape (H, W), float32.
- filtered_confidence: Confidence map with inconsistent pixels set to 0,
shape (H, W), float32.
- consistency_count: Number of agreeing views per pixel,
shape (H, W), int32. 0 for invalid/filtered pixels.
- Return type:
filtered_depth
- aquamvs.fuse_depth_maps(ring_cameras, projection_models, filtered_depth_maps, filtered_confidence_maps, images, config)[source]¶
Fuse filtered depth maps from all ring cameras into a single point cloud.
Back-projects each camera’s filtered depth map to 3D with colors, concatenates all points, deduplicates via voxel grid downsampling, and estimates normals.
- Parameters:
projection_models (dict[str, ProjectionModel]) – Camera name to ProjectionModel mapping.
filtered_depth_maps (dict[str, Tensor]) – Camera name to filtered depth map (H, W) mapping (output of filter_all_depth_maps).
filtered_confidence_maps (dict[str, Tensor]) – Camera name to filtered confidence map (H, W) mapping.
images (dict[str, Tensor]) – Camera name to BGR image (H, W, 3) uint8 mapping.
config (ReconstructionConfig) – Fusion configuration.
- Returns:
Open3D PointCloud with positions, colors, and estimated normals.
- Return type:
PointCloud
- aquamvs.backproject_depth_map(model, depth_map, image, confidence=None)[source]¶
Back-project a filtered depth map to a colored 3D point cloud.
For each valid (non-NaN) pixel in the depth map, casts a ray through the projection model, computes the 3D point at the stored ray depth, and samples the color from the reference image.
- Parameters:
model (ProjectionModel) – Projection model for this camera.
depth_map (Tensor) – Filtered depth map, shape (H, W), float32. NaN = invalid.
image (Tensor) – Reference BGR image, shape (H, W, 3), uint8.
confidence (Tensor | None) – Optional confidence map, shape (H, W), float32. If provided, included in the output for downstream use.
- Returns:
“points”: shape (K, 3), float32 – 3D world coordinates
”colors”: shape (K, 3), float32 – RGB colors in [0, 1]
”confidence”: shape (K,), float32 – confidence values (if provided, else ones)
Where K is the number of valid (non-NaN) pixels. Returns empty tensors if no valid pixels.
- Return type:
Dict with keys
Surface Reconstruction¶
- aquamvs.reconstruct_surface(pcd, config)[source]¶
Reconstruct a surface mesh from a fused point cloud.
Dispatches to the appropriate method based on config.
- Parameters:
pcd (PointCloud) – Fused point cloud (from fuse_depth_maps).
config (ReconstructionConfig) – Surface configuration.
- Returns:
Triangle mesh with vertex colors.
- Raises:
ValueError – If config.method is not “poisson”, “heightfield”, or “bpa”.
- Return type:
TriangleMesh
- aquamvs.reconstruct_poisson(pcd, config)[source]¶
Reconstruct a surface mesh using Poisson surface reconstruction.
Produces a watertight mesh from an oriented point cloud. Best for general-purpose use but may hallucinate geometry in regions without point coverage.
- Parameters:
pcd (PointCloud) – Fused point cloud with points, colors, and normals.
config (ReconstructionConfig) – Surface configuration.
- Returns:
Triangle mesh with vertex colors.
- Raises:
ValueError – If the point cloud has no normals.
- Return type:
TriangleMesh
- aquamvs.reconstruct_heightfield(pcd, config)[source]¶
Reconstruct a surface mesh using height-field interpolation.
Projects the point cloud onto a regular XY grid and interpolates Z values using scipy’s griddata. Best for surfaces that are approximately single-valued in Z (e.g., a sand bed viewed from above).
- Parameters:
pcd (PointCloud) – Fused point cloud with points and colors.
config (ReconstructionConfig) – Surface configuration.
- Returns:
Triangle mesh with vertex colors.
- Raises:
ValueError – If the point cloud has fewer than 4 points.
- Return type:
TriangleMesh
- aquamvs.reconstruct_bpa(pcd, config)[source]¶
Reconstruct a surface mesh using the Ball Pivoting Algorithm.
Rolls a ball of varying radii over the point cloud surface, creating triangles where the ball touches three points without enclosing others. Best for incomplete point clouds where Poisson would hallucinate beyond the data extent.
- Parameters:
pcd (PointCloud) – Fused point cloud with points, colors, and normals.
config (ReconstructionConfig) – Surface configuration.
- Returns:
Triangle mesh with vertex colors.
- Raises:
ValueError – If the point cloud has no normals.
- Return type:
TriangleMesh
- aquamvs.export_mesh(input_path, output_path, simplify=None)[source]¶
Export a mesh to a different format with optional simplification.
Supports conversion between PLY, OBJ, STL, GLTF, and GLB formats. STL export automatically computes vertex normals if missing.
- Parameters:
- Raises:
ValueError – If input mesh is empty or invalid.
RuntimeError – If mesh export fails.
- Return type:
None
- aquamvs.simplify_mesh(mesh, target_faces)[source]¶
Simplify a triangle mesh using quadric decimation.
Reduces mesh complexity while preserving shape and features. Useful for reducing file size or improving rendering performance.
- Parameters:
mesh (TriangleMesh) – Input triangle mesh.
target_faces (int) – Target number of triangles after simplification.
- Returns:
Simplified triangle mesh.
- Return type:
TriangleMesh