Global spherical reconstruction

panorai.reconstruction contains separate Experimental sparse and dense reconstruction surfaces for central panoramas. The sparse mapper can attach soft radial-range priors to matched features and optional measured metric baselines. It refines points while all camera poses remain frozen before any pose block is opened. Its equations, policies and orchestration are PanorAi NumPy/SciPy code, with optional first-party C++ acceleration for repeated numerical kernels. OpenCV remains responsible for optional feature extraction and matching, and this mapper does not call OpenCV, PyCOLMAP, COLMAP, or Torch for geometry.

The high-level input is a sequence of panorai.features.SphericalFeatureMatches objects. Pairwise poses may be estimated internally with SphericalRelativePoseEstimator or computed once and supplied as SphericalPairwisePoseEdge objects:

from panorai.reconstruction import SphericalGlobalMapper

mapper = SphericalGlobalMapper(relative_pose_estimator=relative_estimator)

result = mapper.reconstruct(matches=pairwise_matches)

# Equivalent route when pairwise estimation is intentionally reused.
edges = mapper.estimate_pairwise(pairwise_matches)
reused = mapper.reconstruct(edges=edges)

if result.success:
    pose = result.pose("panorama-003")
    R_world_to_panorama = pose.R
    center_world = pose.center
    points_world = result.points_xyz
else:
    inspect(result.failure_reasons)

Exactly one of matches and edges is accepted. Invalid contracts raise TypeError or ValueError. Insufficient geometry returns an unsuccessful result with no fabricated partial poses or points.

The metric-prior route is explicit and opt-in:

from panorai.reconstruction import (
    SphericalGlobalMapper,
    SphericalGlobalMapperOptions,
    SphericalBaselinePrior,
    SphericalRangePrior,
)

mapper = SphericalGlobalMapper(options=SphericalGlobalMapperOptions())
priors = [
    SphericalRangePrior("panorama-001", feature_index, radial_range_m)
    for feature_index, radial_range_m in feature_ranges
]
baseline = SphericalBaselinePrior(
    "panorama-001", "panorama-002", baseline_m=1.279521, sigma_m=0.01
)
result = mapper.reconstruct(
    edges=accepted_edges,
    range_priors=priors,
    baseline_priors=(baseline,),
)

Only priors attached to admitted inlier tracks participate. At least range_prior_min_count matched priors are required when any are supplied. The result records matched and unused counts, the robust scale factor, and range and baseline residuals before and after refinement. A metric baseline is not inferred from two-view bearing geometry: it must come from a measurement, registration, or a separately validated metric sensor/depth source. The connected reconstruction must still contain at least three panoramas.

One measured baseline fixes the global scale gauge, but a tree with only two pairwise directions may still leave another camera’s relative distance weakly constrained. Prefer a closed three-view cycle, additional measured baselines, or sufficiently many tracks observed in all three panoramas. The permissive edge_admission="successful" option can retain an audited low-support loop edge, but it is not enabled automatically and keeps the risk described below.

Frames and scale

The public pose convention is

\[x_i = R_i (X - C_i),\]

where R_i is rotation_world_to_panorama and C_i is center_world. A relative-pose edge follows

\[R_{ba} = R_b R_a^T, \qquad C_b-C_a \parallel -R_b^T t_{ba}.\]

The reference panorama has identity rotation and zero center. Bearings alone do not contain metric scale, so the ordinary result uses result.scale == "arbitrary". With sufficient SphericalRangePrior evidence, a robust log-range scale fit changes this to "metric-range-prior". Range values remain soft evidence: a Huber IRLS scale fit limits outliers, and the bundle objective retains their declared sigma_log_range and confidence.

When a SphericalBaselinePrior is supplied, it is the preferred scale gauge and the result reports "metric-baseline-prior" or "metric-baseline-and-range-priors". This transfers the successful pair-refinement setup into global mapping: the measured baseline fixes scale while the depth map remains a soft range prior, and the whole connected three-or-more-view component supplies global geometric support. A monocular depth map may have severe absolute scale bias and should not silently replace a measured baseline.

GlobalMapper-aligned stages

The mapper follows the current global-SfM decomposition without copying COLMAP code or claiming numerical identity:

  1. admit pairwise poses with quality_report.accepted by default;

  2. retain the deterministic largest connected component;

  3. initialize through a maximum-support spanning tree and robustly average rotations on \(SO(3)\);

  4. filter rotation-inconsistent edges and resolve the surviving component;

  5. build conflict-free tracks by unioning only components with disjoint panorama IDs;

  6. solve a translation-independent linear camera/point initialization from track bearings using several deterministic positive-depth scale anchors; select first by the weakest per-camera cheirality support, then total support and scale-normalized robust residual;

  7. compare every relative translation as an unsigned axis against those centers, resolve its sign jointly, and remove the worst direction-inconsistent edge before rebuilding tracks and re-estimating;

  8. refine centers from the surviving, consistently oriented relative translations;

  9. jointly position cameras and points using

    \[X_k - C_i - s_{ik}R_i^T b_{ik} \simeq 0, \qquad s_{ik}>0;\]
  10. robustly establish scale from the measured baseline when available, otherwise from declared metric range priors;

  11. when range priors are present, optimize only the 3D points while all \(R,t\) blocks remain frozen;

  12. run fixed-rotation and joint spherical bundle adjustment;

  13. filter angular reprojection outliers and weak triangulation, retriangulate, and perform a final joint refinement;

  14. independently repeat the position solve using only tracks observed by at least three panoramas, then require its pairwise camera-center directions to agree with the primary reconstruction.

Bundle adjustment compares the measured bearing with

\[\hat b_{ik} = \frac{R_i(X_k-C_i)}{\|X_k-C_i\|}\]

using a two-dimensional log-map residual in the tangent plane of the measured bearing. The BATA and bundle residuals are evaluated in vectorized batches; this is an execution change, not a different objective. Descriptor distance is not treated as a calibrated geometric weight.

Native bundle computation

SphericalGlobalMapperOptions(bundle_compute_backend="auto") uses the optional first-party C++17 kernel when it is present and otherwise retains the NumPy reference path. "numpy" forces the readable reference with SciPy’s sparse finite-difference Jacobian; "native" requires the compiled kernel and fails explicitly when it is unavailable.

The native kernel evaluates the same tangent-plane log-map residual and its analytic local Jacobian blocks with respect to the rotation increment, camera center and world point. Python still owns graph admission, gauges, robust loss, SciPy optimization, filtering, provenance and result construction. The resolved route is recorded as diagnostics.bundle_compute_backend. Native and NumPy paths are required to agree against independent finite differences and complete reconstruction fixtures; the native path is acceleration, not a second reconstruction method.

Range- and baseline-prior bundle adjustment currently uses the NumPy/SciPy path because the native kernel does not yet expose those residual blocks. This fallback is explicit in diagnostics.bundle_compute_backend and does not silently drop the priors.

Metric landmark-only support

refine_metric_spherical_landmarks is a separate Experimental entry point for an already constructed sparse graph with a known metric baseline. It accepts two or more cameras, multiply observed landmarks, unit bearings and optional soft monocular radial-range priors. Passing every camera ID in fixed_camera_ids refines only landmark positions; fixing only the reference camera permits joint camera/landmark refinement.

The result explicitly reports support="supplied-landmarks-only". It never interpolates, splats or otherwise converts sparse points into a depth image. Sparse landmark metrics must not be presented as full-panorama accuracy, and dense propagation is outside this API contract.

Admission and failure policy

edge_admission="accepted" is the default. The explicit "successful" override admits every numerical pairwise result, including one rejected by its quality policy. Relative-pose quality now records all four Essential decompositions, the best and alternative positive-depth counts, and their normalized cheirality margin. A small margin is reported as ambiguous-translation-orientation.

The global mapper treats pairwise translation as an axis before assigning a sign. translation_max_error_deg controls removal against the independent track-bearing initialization; the default is 20 degrees. Inconsistent edges are removed worst-first for at most translation_consistency_rounds solves, rather than all at once. bearing_position_anchor_trials bounds the deterministic scale-anchor candidates. Rejected edges, rotation- and translation-filtered edges, sign flips, per-edge axis errors, positive-depth coverage, final reprojection percentiles, excluded panoramas, active-track counts per panorama, multiview-corroboration status and angular disagreement, track conflicts, costs, gauges, and stage names remain in SphericalReconstructionDiagnostics.

The default require_multiview_corroboration=True prevents a map supported only by independent two-view tracks from being reported as trustworthy. The independent solve uses tracks of length three or greater and rejects the result if it fails or if the P90 disagreement between pairwise center directions exceeds 15 degrees. These controls are exposed as multiview_corroboration_min_track_length and multiview_corroboration_max_position_error_deg. Disabling corroboration is an explicit permissive override; it increases coverage but removes this independent check against repeated-texture and weak-translation solutions.

The mapper requires at least three connected panoramas. Pure rotation, insufficient tracks, low triangulation angle, disconnected reference cameras, complete filtering, or a panorama with fewer than min_active_tracks_per_panorama surviving tracks return success=False and an explicit reason. A camera is therefore never reported as registered solely because it survived graph connectivity while all of its observations were rejected. Failed independent multiview corroboration likewise returns no partial geometry and starts its reason list with multiview-corroboration-failed.

A reference_id that does not identify any input panorama remains invalid and raises ValueError. If it identifies an input panorama that is excluded from the selected connected component, that is geometric insufficiency: the mapper returns success=False with reference-not-in-selected-component instead of raising during a batch.

Limitations

This first version assumes calibrated central panoramas and NumPy bearings. It does not select image pairs, discover loops, estimate metric scale, adjust intrinsics, or replace the existing PyCOLMAP database exporter. Promotion from Experimental requires independent real multiview consumers and broader degeneracy/performance evidence.

The current promotion decision is explicitly negative. In the metadata-blind 423-set census, the current conservative policy fully registered 131 sets (31.0%); all 131 complete results were strict-accurate, but coverage remained too low. A development-tuned group-held-out Matterport gate selected 18/22 successes (81.8%), but the threshold was not prospectively frozen and external Stanford evidence covered only three spatial groups. Use explicit failure/recapture handling and do not treat this surface as an unattended Stable mapper. The next evidence order is: independent real consumer, prospective broader-domain validation, degeneracy corpus, then scalability and bounded-failure measurements.

Registered dense surface reconstruction

RegisteredSphericalView binds an EquirectangularImage to a SphericalCameraPose. RegisteredSphericalScene validates shared units, unique camera IDs and at least two supplied central-camera poses. The candidate reviewed application profile requires at least three views.

SphericalDenseReconstruction in panorai.applications exposes the complete route. The reusable contracts and Stages live here:

The typed values are RegisteredSphericalView, RegisteredSphericalScene, MultiViewRangeMap, MultiViewRangeSet, TSDFSpec, TSDFVolume, SurfaceMesh and SphericalDenseReconstructionResult. The public Stages are BuildRegisteredReferenceSets, EstimateMultiViewRanges, FuseTSDF, ExtractSurface, ColorizeSurface and ValidateDenseReconstruction.

FuseTSDF accepts a MultiViewRangeSet directly, including one produced by another range method. TSDFVolume.weight_zyx == 0 means unknown. Surface extraction requires the configured view count and does not close unknown holes. SurfaceMesh is canonical; panorai.pcd.surface_mesh_to_open3d is a lazy optional adapter.

The candidate profile is not Stable. Promotion requires the prospectively frozen multi-corpus surface metrics, installed-wheel Python matrix, memory and runtime evidence, content/license audit and independent review described in the concept.

API

Experimental PanorAi-owned global spherical reconstruction.

The implementation consumes panorama-frame bearings and uses NumPy/SciPy. It does not call OpenCV, PyCOLMAP, COLMAP, or Torch for geometry.

class panorai.reconstruction.BuildRegisteredReferenceSets(reference_ids=None)

Create one deterministic registered MVS set per reference view.

reference_ids
execute(value)
input_kind = 'registered-spherical-scene'
output_kind = 'dense-reconstruction-workspace'
stability = 'experimental'
class panorai.reconstruction.ColorizeSurface(enabled=True)

Fuse range-consistent ERP colors into surface vertices.

enabled
execute(value)
input_kind = 'dense-reconstruction-workspace'
output_kind = 'dense-reconstruction-workspace'
stability = 'experimental'
class panorai.reconstruction.DenseReconstructionWorkspace(*, scene, reference_sets=None, ranges=None, volume=None, surface=None, diagnostics=<factory>, rejection_reasons=())

Typed state passed between public dense-reconstruction stages.

scene
reference_sets
ranges
volume
surface
diagnostics
rejection_reasons
class panorai.reconstruction.EstimateMultiViewRanges(options=<factory>)

Run the existing full-sphere MVS engine for every reference.

options
execute(value)
input_kind = 'dense-reconstruction-workspace'
output_kind = 'dense-reconstruction-workspace'
stability = 'experimental'
class panorai.reconstruction.ExtractSurface

Extract a world-frame mesh from a sufficiently observed TSDF.

execute(value)
input_kind = ('dense-reconstruction-workspace', 'tsdf-volume')
output_kind = ('dense-reconstruction-workspace', 'surface-mesh')
stability = 'experimental'
class panorai.reconstruction.FuseTSDF(spec)

Fuse a range set (or workspace range set) into a dense TSDF.

spec
execute(value)
input_kind = ('dense-reconstruction-workspace', 'multi-view-range-set')
output_kind = ('dense-reconstruction-workspace', 'tsdf-volume')
stability = 'experimental'
class panorai.reconstruction.MultiViewRangeMap(*, reference_id, pose, radial_range, validity, sampling_support, observable, confidence, observable_source_count, source_count, source_consensus_count, contribution_count, source_ids, diagnostics=<factory>, interface='panorai-spherical-dense-reconstruction/v1-experimental')

One reference ERP radial-range estimate with its complete evidence.

reference_id
pose
radial_range
validity
sampling_support
observable
confidence
observable_source_count
source_count
source_consensus_count
contribution_count
source_ids
diagnostics
interface
classmethod from_stereo_result(*, reference_id, pose, result)
class panorai.reconstruction.MultiViewRangeSet(*, scene, maps, diagnostics=<factory>, interface='panorai-spherical-dense-reconstruction/v1-experimental')

Per-camera radial ranges tied to their registered input scene.

scene
maps
diagnostics
interface
by_reference(reference_id)
class panorai.reconstruction.RegisteredReferenceSets(*, scene, sets)

Deterministic MVS inputs, one for every selected reference camera.

scene
sets
class panorai.reconstruction.RegisteredSphericalScene(*, views, units, frame='world')

Metric central-camera ERPs registered in one named world frame.

views
units
frame
property panorama_ids
registered_set(reference_id)

Build the exact source-from-reference relations consumed by MVS.

view(panorama_id)
class panorai.reconstruction.RegisteredSphericalView(*, image, pose, validity=None)

One central ERP and its metric camera pose in a shared world frame.

image
pose
validity
effective_validity()

Return explicit image validity intersected with geometric support.

property panorama_id
property shape_hw
class panorai.reconstruction.SphericalBaselinePrior(panorama_id_a, panorama_id_b, baseline_m, sigma_m=0.01, confidence=1.0)

Soft metric distance evidence between two panorama centers.

panorama_id_a
panorama_id_b
baseline_m
sigma_m
confidence
property pair
class panorai.reconstruction.SphericalCameraPose(panorama_id: 'str', rotation_world_to_panorama: 'np.ndarray', center_world: 'np.ndarray')
panorama_id
rotation_world_to_panorama
center_world
property R
property center
class panorai.reconstruction.SphericalDenseReconstructionResult(*, status, reasons, diagnostics, surface=None, ranges=None, volume=None, interface='panorai-spherical-dense-reconstruction/v1-experimental')

Auditable accepted or rejected dense-reconstruction outcome.

status
reasons
diagnostics
surface
ranges
volume
interface
property accepted
require_success()
class panorai.reconstruction.SphericalGlobalMapper(relative_pose_estimator=None, options=None)

PanorAi-owned Experimental global mapper for central panoramas.

estimate_pairwise(matches)

Estimate one relative pose for every supplied match set.

Pairs for which the relative estimator returns None are omitted. Rejected but numerically successful poses remain available for audit; normal global reconstruction admission filters them later.

reconstruct(*, matches=None, edges=None, panorama_ids=None, reference_id=None, range_priors=(), baseline_priors=())

Reconstruct a panorama rig and sparse points.

Exactly one of matches and edges is required. Invalid input is rejected. Soft feature-aligned radial ranges and measured baselines can establish metric scale before any camera pose is refined. Geometric insufficiency returns an unsuccessful result with explicit reasons and no partial geometry.

class panorai.reconstruction.SphericalGlobalMapperOptions(edge_admission='accepted', min_panoramas=3, min_track_length=2, min_active_tracks_per_panorama=3, rotation_max_error_deg=10.0, rotation_robust_scale_deg=5.0, rotation_max_iterations=100, translation_max_error_deg=20.0, translation_consistency_rounds=4, translation_min_positive_depth_ratio=0.55, bearing_position_irls_steps=3, bearing_position_anchor_trials=8, require_multiview_corroboration=True, multiview_corroboration_min_track_length=3, multiview_corroboration_max_position_error_deg=15.0, max_reprojection_error_deg=2.0, min_triangulation_angle_deg=0.5, bundle_loss='cauchy', bundle_loss_scale_deg=1.0, bundle_max_nfev=100, max_refinement_rounds=3, initial_fixed_pose_refinement=True, range_prior_min_count=3, range_prior_huber_delta_log=0.1, bundle_compute_backend='auto')

Numerical and admission policy for SphericalGlobalMapper.

edge_admission
min_panoramas
min_track_length
min_active_tracks_per_panorama
rotation_max_error_deg
rotation_robust_scale_deg
rotation_max_iterations
translation_max_error_deg
translation_consistency_rounds
translation_min_positive_depth_ratio
bearing_position_irls_steps
bearing_position_anchor_trials
require_multiview_corroboration
multiview_corroboration_min_track_length
multiview_corroboration_max_position_error_deg
max_reprojection_error_deg
min_triangulation_angle_deg
bundle_loss
bundle_loss_scale_deg
bundle_max_nfev
max_refinement_rounds
initial_fixed_pose_refinement
range_prior_min_count
range_prior_huber_delta_log
bundle_compute_backend
to_dict()
class panorai.reconstruction.SphericalPairwisePoseEdge(matches, pose)

A match set and its panorama-B-from-panorama-A pose estimate.

matches
pose
property accepted
property pair
property panorama_id_a
property panorama_id_b
class panorai.reconstruction.SphericalRangePrior(panorama_id, feature_index, range_m, sigma_log_range=0.15, confidence=1.0)

Soft radial-range evidence attached to one panorama feature.

panorama_id
feature_index
range_m
sigma_log_range
confidence
class panorai.reconstruction.SphericalReconstructionDiagnostics(input_edge_count: 'int' = 0, successful_edge_count: 'int' = 0, admitted_edge_count: 'int' = 0, rejected_edge_pairs: 'tuple[tuple[str, str], ...]' = (), rotation_filtered_pairs: 'tuple[tuple[str, str], ...]' = (), translation_filtered_pairs: 'tuple[tuple[str, str], ...]' = (), translation_flipped_pairs: 'tuple[tuple[str, str], ...]' = (), translation_axis_errors_deg: 'tuple[tuple[tuple[str, str], float], ...]' = (), translation_positive_depth_ratio: 'float | None' = None, bearing_position_anchors_tested: 'int' = 0, bearing_position_min_camera_positive_depth_ratio: 'float | None' = None, excluded_panoramas: 'tuple[str, ...]' = (), candidate_match_count: 'int' = 0, track_count: 'int' = 0, track_conflict_count: 'int' = 0, filtered_observation_count: 'int' = 0, rotation_initial_cost: 'float | None' = None, rotation_final_cost: 'float | None' = None, position_initial_cost: 'float | None' = None, position_final_cost: 'float | None' = None, bundle_costs: 'tuple[tuple[str, float, float], ...]' = (), reprojection_median_deg: 'float | None' = None, reprojection_p90_deg: 'float | None' = None, reprojection_max_deg: 'float | None' = None, camera_max_reprojection_deg: 'tuple[tuple[str, float], ...]' = (), camera_active_track_counts: 'tuple[tuple[str, int], ...]' = (), multiview_corroboration_passed: 'bool | None' = None, multiview_corroboration_track_count: 'int' = 0, multiview_corroboration_position_p90_deg: 'float | None' = None, multiview_corroboration_failure_reasons: 'tuple[str, ...]' = (), range_prior_count: 'int' = 0, range_prior_unused_count: 'int' = 0, range_prior_scale_factor: 'float | None' = None, range_prior_median_abs_log_error_before: 'float | None' = None, range_prior_median_abs_log_error_after: 'float | None' = None, baseline_prior_count: 'int' = 0, baseline_prior_unused_count: 'int' = 0, baseline_prior_scale_factor: 'float | None' = None, baseline_prior_median_abs_log_error_after: 'float | None' = None, scale_anchor: 'str | None' = None, ba_scale_anchor: 'str | None' = None, stage_messages: 'tuple[str, ...]' = (), bundle_compute_backend: 'str' = 'numpy')
input_edge_count
successful_edge_count
admitted_edge_count
rejected_edge_pairs
rotation_filtered_pairs
translation_filtered_pairs
translation_flipped_pairs
translation_axis_errors_deg
translation_positive_depth_ratio
bearing_position_anchors_tested
bearing_position_min_camera_positive_depth_ratio
excluded_panoramas
candidate_match_count
track_count
track_conflict_count
filtered_observation_count
rotation_initial_cost
rotation_final_cost
position_initial_cost
position_final_cost
bundle_costs
reprojection_median_deg
reprojection_p90_deg
reprojection_max_deg
camera_max_reprojection_deg
camera_active_track_counts
multiview_corroboration_passed
multiview_corroboration_track_count
multiview_corroboration_position_p90_deg
multiview_corroboration_failure_reasons
range_prior_count
range_prior_unused_count
range_prior_scale_factor
range_prior_median_abs_log_error_before
range_prior_median_abs_log_error_after
baseline_prior_count
baseline_prior_unused_count
baseline_prior_scale_factor
baseline_prior_median_abs_log_error_after
scale_anchor
ba_scale_anchor
stage_messages
bundle_compute_backend
to_dict()
class panorai.reconstruction.SphericalReconstructionResult(success: 'bool', failure_reasons: 'Sequence[str]', poses: 'Sequence[SphericalCameraPose]', tracks: 'Sequence[SphericalTrack]', pairwise_edges: 'Sequence[SphericalPairwisePoseEdge]', admitted_edge_indices: 'Sequence[int]', reference_panorama_id: 'str | None', diagnostics: 'SphericalReconstructionDiagnostics', options: 'SphericalGlobalMapperOptions', interface: 'str' = 'panorai-spherical-reconstruction/v1', scale: 'str' = 'arbitrary', _points_xyz: 'np.ndarray' = <factory>)
success
failure_reasons
poses
tracks
pairwise_edges
admitted_edge_indices
reference_panorama_id
diagnostics
options
interface
scale
describe()
property points_xyz
pose(panorama_id)
require_success()
class panorai.reconstruction.SphericalTrack(track_id: 'str', point_xyz: 'np.ndarray', observations: 'tuple[SphericalTrackObservation, ...]', valid: 'bool' = True)
track_id
point_xyz
observations
valid
class panorai.reconstruction.SphericalTrackObservation(panorama_id: 'str', feature_index: 'int', bearing_xyz: 'np.ndarray', residual_rad: 'float', active: 'bool' = True, rejection_reason: 'str | None' = None)
panorama_id
feature_index
bearing_xyz
residual_rad
active
rejection_reason
class panorai.reconstruction.SurfaceMesh(*, vertices_xyz, faces, normals_xyz, vertex_weight, vertex_view_count, colors_rgb=None, color_validity=None, color_contribution_count=None, units='m', frame='world', provenance=<factory>, interface='panorai-spherical-dense-reconstruction/v1-experimental')

World-frame triangle mesh with geometric and color evidence.

vertices_xyz
faces
normals_xyz
vertex_weight
vertex_view_count
colors_rgb
color_validity
color_contribution_count
units
frame
provenance
interface
class panorai.reconstruction.TSDFSpec(*, voxel_size, bounds=None, truncation_distance=None, max_voxels=8000000, chunk_voxels=262144, min_surface_views=2, min_valid_weight=1.0, weighting='uniform')

Deterministic bounded dense-TSDF configuration.

voxel_size
bounds
truncation_distance
max_voxels
chunk_voxels
min_surface_views
min_valid_weight
weighting
class panorai.reconstruction.TSDFVolume(*, tsdf_zyx, weight_zyx, view_count_zyx, origin_xyz, voxel_size, truncation_distance, units, frame, min_surface_views, diagnostics=<factory>, interface='panorai-spherical-dense-reconstruction/v1-experimental')

Dense ZYX TSDF grid in a named world frame.

tsdf_zyx
weight_zyx
view_count_zyx
origin_xyz
voxel_size
truncation_distance
units
frame
min_surface_views
diagnostics
interface
property bounds_xyz
class panorai.reconstruction.ValidateDenseReconstruction(retain_intermediates='ranges')

Turn scientific acceptance or rejection into an auditable result.

retain_intermediates
execute(value)
input_kind = 'dense-reconstruction-workspace'
output_kind = 'spherical-dense-reconstruction-result'
stability = 'experimental'
panorai.reconstruction.colorize_surface(surface, range_set, *, truncation_distance)

Median-fuse range-consistent colors while preserving valid black.

panorai.reconstruction.extract_surface(volume)

Extract a zero-level surface without inventing unknown-space geometry.

panorai.reconstruction.fuse_tsdf(range_set, spec)

Fuse accepted radial ranges into a bounded dense world-frame TSDF.