Spherical feature API

The Stable panorai-spherical-features/v1 core orchestrates OpenCV feature algorithms over PanorAi’s canonical gnomonic geometry. Direct spherical DoG detection, multiscale routing, and virtual-rig/PyCOLMAP export are explicitly Experimental extensions. The resolution-selection report is also Experimental and never resizes caller data implicitly. Detector-only spherical DoG, coarse-to-fine proposals, tangent patches, and tangent OpenCV descriptors are Experimental composition surfaces. The typed image-pair, feature-pair, matching and bearing-conversion stages used by SphericalRelativePose are also Experimental; their default configuration delegates to the frozen relative-pose feature profile. See Spherical features and matching for the workflow and integration rules.

Stable spherical-feature core with Experimental optional extensions.

OpenCV implements detection, description, and nearest-neighbour matching. PanorAi owns the panorama geometry, result objects, masks, deduplication, and provenance. No OpenCV result object crosses the normal public API. Multiscale routing, virtual rigs, and PyCOLMAP export remain explicitly Experimental.

class panorai.features.DeduplicationResult(selected_indices: 'np.ndarray', group_index_for_input: 'np.ndarray', angular_distance_to_selected_rad: 'np.ndarray', duplicate_groups: 'tuple[tuple[int, ...], ...]', selection_reasons: 'tuple[str, ...]')
selected_indices
group_index_for_input
angular_distance_to_selected_rad
duplicate_groups
selection_reasons
class panorai.features.FaceSetSpec(sampler='icosahedron', shape_hw=(1024, 1024), fov_deg=(80.0, 80.0), overlap_deg=0.0, count=None, subdivisions=0)

Serializable materialization contract for virtual gnomonic cameras.

sampler
shape_hw
fov_deg
overlap_deg
count
subdivisions
property effective_fov_deg

Return nominal FOV plus the declared overlap expansion.

to_dict()
class panorai.features.ExtractSphericalFeaturePair(frontend_config=None)

Extract one PanorAi feature set for each image in a typed pair.

frontend_config=None deliberately calls the frozen relative-pose reference profile. A custom configuration is always explicit.

frontend_config
execute(value)
input_kind = 'spherical_image_pair'
interface = 'panorai-spherical-relative-pose-pipeline/v1-experimental'
output_kind = 'spherical_feature_pair'
stability = 'experimental'
class panorai.features.FeatureExtractor(config=None, *, backend=None, minimum_opencv_version='4.9.0')

Extract OpenCV features and express them in spherical PanorAi objects.

extract(panorama, *, face_set=None, face_set_spec=None, panorama_id=None, validity_mask=None)

Materialize views, run OpenCV, and return spherical features.

class panorai.features.FeatureExtractorConfig(method='sift', max_features=4096, contrast_threshold=0.04, edge_threshold=10.0, edge_margin_px=16, deduplicate_overlaps=True, angular_dedup_threshold_deg=0.15, akaze_descriptor_type='binary', parameters=<factory>, validity_margin_px=0, validity_scale_margin=0.0, max_features_per_face=None)

Declarative OpenCV feature-extractor configuration.

method
max_features
contrast_threshold
edge_threshold
edge_margin_px
deduplicate_overlaps
angular_dedup_threshold_deg
akaze_descriptor_type
parameters
validity_margin_px
validity_scale_margin
max_features_per_face
property effective_max_features_per_face
property parameter_dict
to_dict()
class panorai.features.FeatureMatcher(config=None, *, backend=None, minimum_opencv_version='4.9.0')

Match PanorAi feature sets through an encapsulated OpenCV matcher.

match(features_a, features_b)
class panorai.features.FeatureMatcherConfig(method='auto', ratio_test=0.75, cross_check=False, max_distance=None, deduplicate_matches=True, angular_dedup_threshold_deg=0.15, parameters=<factory>)

Declarative OpenCV descriptor-matcher configuration.

method
ratio_test
cross_check
max_distance
deduplicate_matches
angular_dedup_threshold_deg
parameters
property parameter_dict
to_dict()
class panorai.features.FeatureProvenance(interface: 'str', source_panorama_checksum: 'str', projection_backend: 'str', projection_backend_version: 'str', face_id: 'str', generating_commit: 'str | None' = None, alternative_face_ids: 'tuple[str, ...]' = (), duplicate_descriptor_indices: 'tuple[int, ...]' = (), duplicate_angular_distances_deg: 'tuple[float, ...]' = (), selection_reason: 'str' = 'highest-response-then-source-order')
interface
source_panorama_checksum
projection_backend
projection_backend_version
face_id
generating_commit
alternative_face_ids
duplicate_descriptor_indices
duplicate_angular_distances_deg
selection_reason
to_dict()
class panorai.features.FaceDetectionDiagnostics(face_id, detected_count, valid_count)

Detection and validity counts for one projected face.

face_id
detected_count
valid_count
to_dict()
class panorai.features.GnomonicRig(panorama_id: 'str', cameras: 'tuple[GnomonicRigCamera, ...]', face_set_spec: 'FaceSetSpec', interface: 'str' = 'panorai-spherical-rig/v1')
panorama_id
cameras
face_set_spec
interface
class panorai.features.GnomonicRigCamera(camera_id: 'str', face_id: 'str', width: 'int', height: 'int', K: 'np.ndarray', R_panorama_from_face: 'np.ndarray', translation_panorama_from_face: 'np.ndarray' = <factory>)
camera_id
face_id
width
height
K
R_panorama_from_face
translation_panorama_from_face
class panorai.features.MatchProvenance(interface: 'str', source_checksums: 'tuple[str, str]', face_pairs: 'tuple[tuple[str, str], ...]', face_pair_groups: 'tuple[tuple[tuple[str, str], ...], ...]', deduplicated: 'bool', selection_reason: 'str' = 'minimum-distance-then-source-order', calibration_id: 'str | None' = None)
interface
source_checksums
face_pairs
face_pair_groups
deduplicated
selection_reason
calibration_id
to_dict()
class panorai.features.MatchSphericalFeatures(frontend_config=None)

Match an ordered feature pair with the selected frontend matcher.

frontend_config
execute(value)
input_kind = 'spherical_feature_pair'
interface = 'panorai-spherical-relative-pose-pipeline/v1-experimental'
output_kind = 'spherical_matches'
stability = 'experimental'
class panorai.features.MultifaceDetectionDiagnostics(face_count, per_face_capacity, per_face_capacity_hit_count, detected_count, valid_count, unique_after_deduplication, output_after_budget, duplicate_group_count, duplicate_candidate_count, cross_face_ambiguous_group_count, cross_face_duplicate_candidate_count, same_face_duplicate_candidate_count, maximum_group_multiplicity, multiplicity_histogram, maximum_unique_face_multiplicity, unique_face_multiplicity_histogram, descriptor_pair_count, normalized_descriptor_l2_median, normalized_descriptor_l2_p90, normalized_descriptor_l2_maximum, descriptor_cosine_similarity_median, descriptor_cosine_similarity_p10, duplicate_face_pair_histogram, per_face)

Stage counts and overlap ambiguity for a multiface extraction.

face_count
per_face_capacity
per_face_capacity_hit_count
detected_count
valid_count
unique_after_deduplication
output_after_budget
duplicate_group_count
duplicate_candidate_count
cross_face_ambiguous_group_count
cross_face_duplicate_candidate_count
same_face_duplicate_candidate_count
maximum_group_multiplicity
multiplicity_histogram
maximum_unique_face_multiplicity
unique_face_multiplicity_histogram
descriptor_pair_count
normalized_descriptor_l2_median
normalized_descriptor_l2_p90
normalized_descriptor_l2_maximum
descriptor_cosine_similarity_median
descriptor_cosine_similarity_p10
duplicate_face_pair_histogram
per_face
to_dict()
class panorai.features.MultiscaleEmbeddingConfig(local_fov_deg=(42.0, 42.0), local_grid_size=2, max_local_views_per_root=2, context_similarity_threshold=0.82, scale_similarity_threshold=0.94, node_match_similarity_threshold=0.55, node_match_top_k=2, cross_scale_nms_threshold_deg=0.2, fallback_weight=0.35, regional_weight_gain=1.0, embedding_shape_hw=(64, 64), interface='panorai-multiscale-visual-features/v1')

Serializable policy for adaptive wide/local spherical views.

local_fov_deg
local_grid_size
max_local_views_per_root
context_similarity_threshold
scale_similarity_threshold
node_match_similarity_threshold
node_match_top_k
cross_scale_nms_threshold_deg
fallback_weight
regional_weight_gain
embedding_shape_hw
interface
to_dict()
class panorai.features.MultiscaleFeatureMatches(base, sampling_weights, match_sources, node_similarities, diagnostics)

Normal PanorAi matches with explicit proposal-only guidance.

base
sampling_weights
match_sources
node_similarities
diagnostics
describe()
to_bearing_correspondences()
class panorai.features.MultiscaleFeatureSet(base, nodes, feature_guidance, feature_scale_states, provider_name, provider_version, config)

Base spherical features plus scale/context evidence.

base
nodes
feature_guidance
feature_scale_states
provider_name
provider_version
config
describe()
class panorai.features.MultiscaleSphericalFeaturePipeline(base_pipeline, config=None, *, embedding_provider=None)

Adaptive wide/local feature pipeline with embedding graph routing.

describe()
extract(panorama, *, panorama_id=None, validity_mask=None)
extract_and_match(panorama_a, panorama_b, *, panorama_id_a=None, panorama_id_b=None, validity_mask_a=None, validity_mask_b=None)
classmethod from_preset(name, *, multiscale_config=None, embedding_provider=None, **base_options)
match(features_a, features_b)
class panorai.features.OpenCVFeatureBackend(*, extractor=None, matcher=None)

Encapsulate OpenCV detectors, descriptors, and matchers.

Injected OpenCV-compatible objects are an advanced route. The normal API never returns cv2.KeyPoint or cv2.DMatch instances.

create_extractor(config)
create_matcher(descriptor_metric, config)
describe_keypoints(image, pixels_xy, sizes, angles_deg, responses, octaves, config, *, extractor=None)

Compute descriptors for caller-owned keypoints without detection.

descriptor_metadata(config, extractor)
detect_and_describe(image, mask, config)
match(descriptors_a, descriptors_b, descriptor_metric, config)
name = 'opencv'
require_version(minimum)
property version
class panorai.features.OpenCVContextEmbedding(*, shape_hw=(64, 64))

Small deterministic visual-context descriptor with no model weights.

This is a reference provider for testing the routing mechanics, not a claim of learned semantic understanding. It combines coarse luminance, colour, gradient-orientation and low-frequency DCT evidence. Production experiments may inject a learned provider through the same contract.

embed(images, *, masks=None)
name = 'opencv-context'
version = '1'
class panorai.features.OpenCVTangentDescriptor(config=None, *, backend=None)

Apply SIFT, ORB, or AKAZE semantics to generic tangent patches.

describe(patches, *, responses=None)
class panorai.features.OpenCVTangentDescriptorConfig(method='sift', keypoint_diameter_in_scales=3.0, orientation_policy='dominant-gradient', orientation_bins=36, root_sift=False, algorithm_parameters=(), minimum_opencv_version='4.9.0')

Descriptor semantics applied to already-materialized tangent patches.

method
keypoint_diameter_in_scales
orientation_policy
orientation_bins
root_sift
algorithm_parameters
minimum_opencv_version
to_dict()
class panorai.features.OpenCVTangentDescriptorV2(config=None, *, backend=None)

Describe one physical keypoint with one or more explicit hypotheses.

describe(patches, *, responses=None)
class panorai.features.OpenCVTangentDescriptorV2Config(method='sift', keypoint_diameter_in_scales=1.25, scale_multipliers=(1.0,), orientation_policy='fixed-zero', orientation_bins=36, orientation_peak_ratio=0.8, max_orientations=2, photometric_normalization='local-standardization', minimum_descriptor_valid_fraction=0.99, root_sift=True, algorithm_parameters=(), minimum_opencv_version='4.9.0')

Experimental descriptor hypotheses over descriptor-neutral patches.

The v2 adapter leaves patch geometry untouched and makes every additional source of invariance explicit. Defaults use the calibrated single- hypothesis RootSIFT profile consumed by the canonical spherical extractor.

method
keypoint_diameter_in_scales
scale_multipliers
orientation_policy
orientation_bins
orientation_peak_ratio
max_orientations
photometric_normalization
minimum_descriptor_valid_fraction
root_sift
algorithm_parameters
minimum_opencv_version
to_dict()
class panorai.features.PyCOLMAPExportResult(database_path: 'str', camera_ids: 'dict[str, int]', image_ids: 'dict[str, int]', feature_rows: 'dict[str, np.ndarray]', panorama_rig_rotations: 'dict[str, np.ndarray]', interface: 'str' = 'panorai-pycolmap-export/v1')
database_path
camera_ids
image_ids
feature_rows
panorama_rig_rotations
interface
class panorai.features.ResolutionLevelReport(erp_shape_hw, face_shape_hw, feature_count_a, feature_count_b, match_count, valid_match_count, pose_returned, pose_accepted, rejection_reasons, num_inliers, effective_inlier_count, coverage_entropy_a, coverage_entropy_b, rotation_stability_p90_deg, rotation, runtime_seconds)

Compact evidence recorded for one evaluated resolution.

erp_shape_hw
face_shape_hw
feature_count_a
feature_count_b
match_count
valid_match_count
pose_returned
pose_accepted
rejection_reasons
num_inliers
effective_inlier_count
coverage_entropy_a
coverage_entropy_b
rotation_stability_p90_deg
rotation
runtime_seconds
to_dict()
class panorai.features.ResolutionSelectionObservation(erp_shape_hw, face_shape_hw, features_a, features_b, matches, pose, runtime_seconds=None, inlier_weights=None)

Feature, match, and pose products measured at one ERP resolution.

erp_shape_hw
face_shape_hw
features_a
features_b
matches
pose
runtime_seconds
inlier_weights
class panorai.features.ResolutionSelectionPolicy(min_feature_repeatability=0.85, min_effective_inlier_retention=0.8, min_coverage_retention=0.9, target_rotation_accuracy_deg=0.15, stability_multiplier=2.0, max_repeatability_error_pixels=2.0, require_accepted_pose=True, interface='panorai-resolution-selection-policy/v1')

Dataset-agnostic convergence thresholds for adjacent resolutions.

Thresholds are ratios or angular task tolerances. No absolute feature or inlier count is embedded in this policy; absolute evidence admission stays with the relative-pose quality policy.

min_feature_repeatability
min_effective_inlier_retention
min_coverage_retention
target_rotation_accuracy_deg
stability_multiplier
max_repeatability_error_pixels
require_accepted_pose
interface
to_dict()
class panorai.features.ResolutionSelectionReport(levels, transitions, selected_level_index, decision, converged_plateau, decision_reasons, policy, interface='panorai-resolution-selection/v1', stability='experimental')

Auditable result; selection never changes a pipeline silently.

levels
transitions
selected_level_index
decision
converged_plateau
decision_reasons
policy
interface
stability
property selected_erp_shape_hw
property selected_face_shape_hw
property selected_level
to_dict()
class panorai.features.ResolutionTransitionReport(lower_erp_shape_hw, higher_erp_shape_hw, angular_tolerance_deg, repeatable_features_a, repeatable_features_b, feature_repeatability_a, feature_repeatability_b, effective_inlier_retention, coverage_retention_a, coverage_retention_b, rotation_delta_deg, rotation_tolerance_deg, converged, rejection_reasons)

Convergence evidence from one level to the next higher level.

lower_erp_shape_hw
higher_erp_shape_hw
angular_tolerance_deg
repeatable_features_a
repeatable_features_b
feature_repeatability_a
feature_repeatability_b
effective_inlier_retention
coverage_retention_a
coverage_retention_b
rotation_delta_deg
rotation_tolerance_deg
converged
rejection_reasons
to_dict()
class panorai.features.SphericalBearingCorrespondences(bearings_a: 'np.ndarray', bearings_b: 'np.ndarray', weights: 'np.ndarray', valid: 'np.ndarray')
bearings_a
bearings_b
weights
valid
class panorai.features.SphericalCoarseDoGDetector(config=None)

Generate spherical DoG proposals cheaply and promote them to the source ERP.

This deliberately exposes the coarse proposal stage as a separate experimental detector. It does not claim parity with the dense detector; callers can compare the quality/runtime trade-off without changing the dense detector’s defaults.

detect(panorama, *, panorama_id=None, validity_mask=None)
class panorai.features.SphericalCoarseDoGDetectorConfig(octaves=3, levels_per_octave=3, base_sigma_px=0.5, contrast_threshold=0.012, edge_threshold=10.0, refinement_max_iterations=5, refinement_maximum_offset=1.5, refinement_maximum_hessian_condition=1000000.0, max_keypoints=4096, minimum_valid_support_fraction=0.97, angular_dedup_threshold_deg=0.12, scale_dedup_log2=0.5, selection_policy='equal-area-round-robin', selection_grid_shape=(12, 24), convolution_backend='auto', proposal_height=512, proposal_resampling='gaussian', proposal_prefilter_sigma_px=2.0, proposal_prefilter_intermediate_height=1024, fine_verification='none', fine_candidate_multiplier=2.0, fine_patch_size=15, fine_samples_per_sigma=2.0, fine_search_radius_samples=2)

CPU proposal detector evaluated on a reduced spherical raster.

The output bearings, pixels, checksum, and shape are promoted back to the source panorama. Only the proposal scale space is reduced; descriptor extraction can therefore continue on the original panorama without a geometry adapter or a second back-projection contract.

proposal_height
proposal_resampling
proposal_prefilter_sigma_px
proposal_prefilter_intermediate_height
fine_verification
fine_candidate_multiplier
fine_patch_size
fine_samples_per_sigma
fine_search_radius_samples
proposal_config()
to_dict()
class panorai.features.SphericalDoGSIFTConfig(octaves=3, levels_per_octave=3, base_sigma_px=1.6, contrast_threshold=0.012, edge_threshold=10.0, max_features=1000, patch_size=48, descriptor_radius_sigmas=6.0, minimum_valid_fraction=0.99, minimum_valid_support_fraction=0.99, angular_dedup_threshold_deg=0.12, scale_dedup_log2=0.5, selection_policy='equal-area-round-robin', selection_grid_shape=(12, 24), descriptor_config=<factory>, convolution_backend='auto')

Configuration for direct spherical DoG detection and SIFT description.

base_sigma_px is measured at each octave’s ERP vertical resolution; returned feature scales are converted to degrees. contrast_threshold is an absolute DoG amplitude after grayscale normalization to [0, 1].

octaves
levels_per_octave
base_sigma_px
contrast_threshold
edge_threshold
max_features
patch_size
descriptor_radius_sigmas
minimum_valid_fraction
minimum_valid_support_fraction
angular_dedup_threshold_deg
scale_dedup_log2
selection_policy
selection_grid_shape
descriptor_config
convolution_backend
to_dict()
class panorai.features.SphericalDoGSIFTExtractor(config=None, *, backend=None, minimum_opencv_version='4.9.0')

Detect DoG extrema on the sphere and describe local tangent patches.

describe_keypoints(panorama, keypoints, *, validity_mask=None)

Describe a SphericalKeypointSet on tangent SIFT patches.

detect(panorama, *, panorama_id=None, validity_mask=None)

Return descriptor-free keypoints from the corrected spherical detector.

extract(panorama, *, panorama_id=None, validity_mask=None)

Detect keypoints with the public detector and describe them with SIFT.

class panorai.features.SphericalDoGSIFTPipeline(detector_config=None, matcher_config=None, *, backend=None)

Experimental direct spherical detector plus existing L2 matcher.

describe()
extract(panorama, **kwargs)
extract_and_match(panorama_a, panorama_b, *, panorama_id_a=None, panorama_id_b=None, validity_mask_a=None, validity_mask_b=None)
match(features_a, features_b)
class panorai.features.SphericalDetectionDiagnostics(raw_extrema_count, refinement_converged_count, interpolated_contrast_count, refined_edge_count, valid_support_count, unique_after_deduplication, output_after_budget, octaves)

Stage counts for descriptor-free spherical detection.

raw_extrema_count
refinement_converged_count
interpolated_contrast_count
refined_edge_count
valid_support_count
unique_after_deduplication
output_after_budget
octaves
to_dict()
class panorai.features.SphericalDoGDetector(config=None)

Detect keypoints in a spherical DoG scale space without descriptors.

detect(panorama, *, panorama_id=None, validity_mask=None)
detect_batch(panoramas, *, panorama_ids=None, validity_masks=None)

Detect same-shape panoramas with shared spherical pyramid traversals.

class panorai.features.SphericalDoGDetectorConfig(octaves=3, levels_per_octave=3, base_sigma_px=1.6, contrast_threshold=0.012, edge_threshold=10.0, refinement_max_iterations=5, refinement_maximum_offset=1.5, refinement_maximum_hessian_condition=1000000.0, max_keypoints=1000, minimum_valid_support_fraction=0.99, angular_dedup_threshold_deg=0.12, scale_dedup_log2=0.5, selection_policy='equal-area-round-robin', selection_grid_shape=(12, 24), convolution_backend='auto')

Configuration for descriptor-independent spherical DoG detection.

octaves
levels_per_octave
base_sigma_px
contrast_threshold
edge_threshold
refinement_max_iterations
refinement_maximum_offset
refinement_maximum_hessian_condition
max_keypoints
minimum_valid_support_fraction
angular_dedup_threshold_deg
scale_dedup_log2
selection_policy
selection_grid_shape
convolution_backend
to_dict()
class panorai.features.SphericalKeypoint(source_erp_xy, bearing_xyz, response, scale_deg, octave, level, valid_support_fraction)

Common descriptor-independent spherical keypoint fields.

The direct DoG detector returns SphericalRefinedKeypoint objects. This base remains public so descriptor and patch consumers can depend only on location, bearing, response, angular scale, and support.

source_erp_xy
bearing_xyz
response
scale_deg
octave
level
valid_support_fraction
class panorai.features.SphericalKeypointSet(panorama_id, keypoints, source_shape_hw, source_checksum, config, generating_commit, projection_backend_version, diagnostics, interface='panorai-spherical-dog-detector/v2', stability='experimental')

Descriptor-free spherical detections with explicit provenance.

panorama_id
keypoints
source_shape_hw
source_checksum
config
generating_commit
projection_backend_version
diagnostics
interface
stability
property bearings
describe()
property levels
property octaves
property refined_levels
property responses
property scales_deg
property source_erp_xy
property valid_support_fractions
class panorai.features.SphericalOctaveDetectionDiagnostics(octave, shape_hw, raw_extrema_count, refinement_converged_count, interpolated_contrast_count, refined_edge_count, valid_support_count, rejected_nonconverged_count, rejected_ill_conditioned_count)

Candidate counts through localization and validity filtering.

octave
shape_hw
raw_extrema_count
refinement_converged_count
interpolated_contrast_count
refined_edge_count
valid_support_count
rejected_nonconverged_count
rejected_ill_conditioned_count
to_dict()
class panorai.features.SphericalRefinedKeypoint(source_erp_xy, bearing_xyz, response, scale_deg, octave, level, valid_support_fraction, refined_level, tangent_offset_rad, interpolated_dog_response, edge_score, hessian_condition, localization_iterations)

A DoG extremum localized continuously in tangent position and scale.

tangent_offset_rad is [east, north] from the final discrete scale-space sample. refined_level is continuous within octave. The signed interpolated DoG value is retained separately from the non-negative response used for ranking.

refined_level
tangent_offset_rad
interpolated_dog_response
edge_score
hessian_condition
localization_iterations
class panorai.features.SphericalFeature(feature_id: 'str', panorama_id: 'str', face_id: 'str', pixel_xy: 'np.ndarray', source_erp_xy: 'np.ndarray | None', bearing_xyz: 'np.ndarray', response: 'float', scale: 'float', angle_deg: 'float', octave: 'int', descriptor_index: 'int', valid: 'bool', projection_spec: 'GnomonicSpec', provenance: 'FeatureProvenance')
feature_id
panorama_id
face_id
pixel_xy
source_erp_xy
bearing_xyz
response
scale
angle_deg
octave
descriptor_index
valid
projection_spec
provenance
class panorai.features.SphericalFeaturePair(reference, source)

Feature sets extracted from an ordered spherical image pair.

reference
source
class panorai.features.SphericalFeatureMatches(panorama_id_a: 'str', panorama_id_b: 'str', feature_indices_a: 'np.ndarray', feature_indices_b: 'np.ndarray', bearings_a: 'np.ndarray', bearings_b: 'np.ndarray', descriptor_distances: 'np.ndarray', ratio_scores: 'np.ndarray | None', mutual: 'np.ndarray | None', valid: 'np.ndarray', matcher_name: 'str', matcher_config: 'dict[str, Any]', backend_name: 'str', backend_version: 'str', provenance: 'MatchProvenance', keypoint_responses: 'np.ndarray', face_ids_a: 'np.ndarray', face_ids_b: 'np.ndarray', interface: 'str' = 'panorai-spherical-features/v1', stability: 'str' = 'stable')
panorama_id_a
panorama_id_b
feature_indices_a
feature_indices_b
bearings_a
bearings_b
descriptor_distances
ratio_scores
mutual
valid
matcher_name
matcher_config
backend_name
backend_version
provenance
keypoint_responses
face_ids_a
face_ids_b
interface
stability
describe()
to_bearing_correspondences()

Return uniform-weight spherical correspondences for estimators.

Descriptor metrics have incompatible scales, so PanorAi deliberately does not invent a cross-descriptor confidence calibration here.

class panorai.features.SphericalFeaturePipeline(config, *, backend=None)

Extract and match panorama features without exposing OpenCV objects.

Extraction, matching, configuration and PanorAi-owned result objects form the Stable panorai-spherical-features/v1 core. Virtual-rig construction and PyCOLMAP export remain method-level Experimental extensions.

build_virtual_camera_rig(panorama, *, panorama_id=None)
describe()
export_pycolmap(*, rig, features, output_database, matches=None)
extract(panorama, *, panorama_id=None, validity_mask=None)
extract_and_match(panorama_a, panorama_b, *, panorama_id_a=None, panorama_id_b=None, validity_mask_a=None, validity_mask_b=None)
classmethod for_relative_pose(*, backend=None)

Build the frozen v1 reference profile for spherical relative pose.

The profile fixes cube sampling, SIFT/FLANN parameters, adaptive validity-boundary rejection, and bilateral spherical match NMS. It intentionally keeps reciprocal descriptor cross-checking disabled: the validated profile preserves recall and delegates geometric rejection to the spherical relative-pose estimator.

classmethod from_preset(name, *, face_sampler='icosahedron', face_fov_deg=80.0, face_shape_hw=(1024, 1024), face_overlap_deg=0.0, count=None, subdivisions=0, edge_margin_px=None, validity_margin_px=None, validity_scale_margin=None, ratio_test=None, cross_check=None, max_distance=None, deduplicate_matches=None, max_features=None, max_features_per_face=None, angular_dedup_threshold_deg=None, backend=None)
match(features_a, features_b)
class panorai.features.SphericalFeaturePipelineConfig(extractor=<factory>, matcher=<factory>, face_set=<factory>, interface='panorai-spherical-features/v1', preset_name=None, preset_version=1, minimum_opencv_version='4.9.0')

Complete reproducible configuration for the high-level facade.

extractor
matcher
face_set
interface
preset_name
preset_version
minimum_opencv_version
replace(**changes)
to_dict()
class panorai.features.SphericalFeatureSet(panorama_id: 'str', features: 'list[SphericalFeature]', descriptors: 'np.ndarray', descriptor_type: 'str', descriptor_metric: 'str', extractor_name: 'str', extractor_config: 'dict[str, Any]', backend_name: 'str', backend_version: 'str', face_set_spec: 'FaceSetSpec', projection_backend: 'str', projection_backend_version: 'str', panorama_checksum: 'str', generating_commit: 'str | None' = None, interface: 'str' = 'panorai-spherical-features/v1', stability: 'str' = 'stable', detection_diagnostics: 'MultifaceDetectionDiagnostics | None' = None)
panorama_id
features
descriptors
descriptor_type
descriptor_metric
extractor_name
extractor_config
backend_name
backend_version
face_set_spec
projection_backend
projection_backend_version
panorama_checksum
generating_commit
interface
stability
detection_diagnostics
property bearings
describe()
property face_ids
property pixels_xy
property responses
property source_erp_xy
class panorai.features.SphericalImagePair(reference, source, reference_id=None, source_id=None)

Two canonical ERP containers ordered as reference then source.

Relative pose follows the convention source-from-reference. Image validity and geometric support remain properties of each EquirectangularImage; they are never inferred from pixel values.

reference
source
reference_id
source_id
class panorai.features.TangentDescriptorSet(patch_indices, descriptors, angles_deg, descriptor_type, descriptor_metric, extractor_name, config, patch_interface='panorai-tangent-patches/v1', interface='panorai-tangent-opencv-descriptor/v1', stability='experimental')

Descriptors and metadata aligned to a subset of a tangent patch set.

patch_indices
descriptors
angles_deg
descriptor_type
descriptor_metric
extractor_name
config
patch_interface
interface
stability
class panorai.features.TangentDescriptorHypothesisSet(physical_keypoint_ids, patch_indices, scale_multipliers, orientation_ranks, orientation_confidences, descriptor_valid_fractions, descriptors, angles_deg, descriptor_type, descriptor_metric, extractor_name, config, patch_interface='panorai-tangent-patches/v1', interface='panorai-tangent-opencv-descriptor/v2', stability='experimental')

Descriptor hypotheses retaining their physical keypoint identity.

physical_keypoint_ids
patch_indices
scale_multipliers
orientation_ranks
orientation_confidences
descriptor_valid_fractions
descriptors
angles_deg
descriptor_type
descriptor_metric
extractor_name
config
patch_interface
interface
stability
class panorai.features.TangentPatch(geometry, image, support_mask, validity_mask, valid_weight, valid_fraction, valid, source_panorama_checksum, interface='panorai-tangent-patches/v1')

One projected patch, with support and observed-data validity separated.

geometry
image
support_mask
validity_mask
valid_weight
valid_fraction
valid
source_panorama_checksum
interface
class panorai.features.TangentPatchGeometry(patch_id, keypoint_index, source_erp_xy, center_bearing_xyz, detector_scale_deg, requested_radius_deg, actual_radius_deg, samples_per_scale_xy, projection_spec, K, R_panorama_from_patch, source_frame='panorama-camera', patch_frame='gnomonic-camera:+x-right,+y-down,+z-forward')

Geometry and sampling metadata for a materialized tangent patch.

patch_id
keypoint_index
source_erp_xy
center_bearing_xyz
detector_scale_deg
requested_radius_deg
actual_radius_deg
samples_per_scale_xy
projection_spec
K
R_panorama_from_patch
source_frame
patch_frame
class panorai.features.TangentPatchProvider(*, max_workers=1)

Materialize descriptor-neutral patches through public PanorAi geometry.

materialize(panorama, keypoints, request, *, validity_mask=None, rolls_deg=None)
class panorai.features.TangentPatchRequest(output_shape_hw=(48, 48), radius_in_scales=6.0, minimum_fov_deg=1.0, maximum_fov_deg=120.0, interpolation='bilinear', invalid_policy='propagate', min_valid_weight=None, minimum_valid_fraction=1.0, orientation_policy='upright', fixed_roll_deg=0.0)

Descriptor-neutral request for one patch around every keypoint.

radius_in_scales is the angular half-extent divided by the detector’s scale sigma. Consequently, the requested full FOV is 2 * radius_in_scales * scale_deg. output_shape_hw independently controls sampling density. No descriptor-specific window size is hidden in the provider.

orientation_policy='upright' keeps north/up aligned with the patch. 'per-keypoint-roll' requires one explicit roll angle per keypoint.

output_shape_hw
radius_in_scales
minimum_fov_deg
maximum_fov_deg
interpolation
invalid_policy
min_valid_weight
minimum_valid_fraction
orientation_policy
fixed_roll_deg
to_dict()
class panorai.features.TangentPatchSet(panorama_id, source_shape_hw, source_checksum, keypoint_interface, request, patches, interface='panorai-tangent-patches/v1', stability='experimental')

Ordered tangent patches aligned to a descriptor-free keypoint set.

panorama_id
source_shape_hw
source_checksum
keypoint_interface
request
patches
interface
stability
property valid_count
class panorai.features.ToBearingCorrespondences(weighting='uniform-valid')

Convert feature matches to explicit weighted spherical bearings.

weighting
execute(value)
input_kind = 'spherical_matches'
interface = 'panorai-spherical-relative-pose-pipeline/v1-experimental'
output_kind = 'bearing_correspondences'
stability = 'experimental'
class panorai.features.VisualContextNode(node_id: 'str', parent_id: 'str | None', level: 'int', spec: 'GnomonicSpec', embedding: 'np.ndarray', selected: 'bool', global_local_similarity: 'float | None' = None, same_support_similarity: 'float | None' = None, novelty: 'float' = 0.0, solid_angle_sr: 'float' = 0.0, feature_indices: 'np.ndarray' = <factory>, feature_density_per_sr: 'float' = 0.0)
node_id
parent_id
level
spec
embedding
selected
global_local_similarity
same_support_similarity
novelty
solid_angle_sr
feature_indices
feature_density_per_sr
describe()
class panorai.features.VisualEmbeddingProvider(*args, **kwargs)

Caller-injectable, batch visual embedding contract.

Providers return one finite floating vector per image. They may use a learned model, but model selection, weights and licensing remain explicit caller concerns and are recorded through name and version.

embed(images, *, masks=None)
name
version
panorai.features.available_presets()
panorai.features.deduplicate_spherical_keypoints(bearings_xyz, responses, *, angular_threshold_rad)

Apply deterministic angular NMS to already-detected keypoints.

Higher response wins. Exact ties are resolved by the original source order. Detection, descriptor generation, and nearest-neighbour matching remain wholly outside this function.

panorai.features.extract_opencv_features(erp_image, face_specs, detector, *, edge_margin_px=0, validity_mask=None)

Advanced route using an injected OpenCV-compatible detector.

panorai.features.gnomonic_feature_mask(projection_result, *, edge_margin_px, validity_mask=None, user_mask=None)

Combine geometric support, data validity, edge margin and user mask.

The input may be a canonical ProjectionResult or a workflow-created GnomonicFace. The result preserves the mask backend and device.

panorai.features.match_opencv_features(features_a, features_b, matcher, *, knn=2)

Advanced route using an injected OpenCV-compatible matcher.

panorai.features.select_feature_resolution(observations, *, policy=None)

Select the lowest spherical resolution on a converged level plateau.

Observations may arrive in any order. They are sorted by ERP width, and every adjacent pair is compared. If no pair converges, the highest tested level is returned only when its pose passed its own quality gate; that fallback is explicitly marked as not adjacent-level converged.

Advanced OpenCV backend

OpenCV implementation adapter for PanorAi’s spherical feature facade.

class panorai.features.backends.opencv.OpenCVFeatureBackend(*, extractor=None, matcher=None)

Encapsulate OpenCV detectors, descriptors, and matchers.

Injected OpenCV-compatible objects are an advanced route. The normal API never returns cv2.KeyPoint or cv2.DMatch instances.

describe_keypoints(image, pixels_xy, sizes, angles_deg, responses, octaves, config, *, extractor=None)

Compute descriptors for caller-owned keypoints without detection.