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=Nonedeliberately 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.KeyPointorcv2.DMatchinstances.- 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_pxis measured at each octave’s ERP vertical resolution; returned feature scales are converted to degrees.contrast_thresholdis 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
SphericalKeypointSeton 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
SphericalRefinedKeypointobjects. 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_radis[east, north]from the final discrete scale-space sample.refined_levelis continuous withinoctave. 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/v1core. 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 eachEquirectangularImage; 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_scalesis the angular half-extent divided by the detector’s scale sigma. Consequently, the requested full FOV is2 * radius_in_scales * scale_deg.output_shape_hwindependently 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
nameandversion.- 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
ProjectionResultor a workflow-createdGnomonicFace. 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.KeyPointorcv2.DMatchinstances.- describe_keypoints(image, pixels_xy, sizes, angles_deg, responses, octaves, config, *, extractor=None)¶
Compute descriptors for caller-owned keypoints without detection.