ringgrid/lib.rs
1//! # ringgrid
2//!
3//! Pure-Rust detector for dense coded ring calibration targets on a hex lattice.
4//!
5//! ringgrid detects ring markers in grayscale images, decodes their 16-sector
6//! binary IDs from the shipped baseline 893-codeword profile (with an opt-in
7//! extended profile available for advanced use), fits subpixel ellipses via
8//! Fitzgibbon's direct method with RANSAC, and estimates a board-to-image
9//! homography. No OpenCV dependency — all image processing is in Rust.
10//!
11//! ## Detection Modes
12//!
13//! - **Simple** — [`Detector::detect`]: single-pass detection in image coordinates.
14//! Use when the camera has negligible distortion.
15//! - **External mapper** — [`Detector::detect_with_mapper`]: two-pass pipeline
16//! with a [`PixelMapper`] (e.g. [`CameraModel`]) for distortion-aware detection.
17//! - **Self-undistort** — [`Detector::detect`] with
18//! [`SelfUndistortConfig::enable`] set to `true`: estimates a 1-parameter
19//! division-model distortion from detected markers and optionally re-runs
20//! detection with the estimated correction.
21//!
22//! ## Quick Start
23//!
24//! ```no_run
25//! use ringgrid::{BoardLayout, Detector};
26//! use std::path::Path;
27//!
28//! let board = BoardLayout::from_json_file(Path::new("target.json")).unwrap();
29//! let image = image::open("photo.png").unwrap().to_luma8();
30//!
31//! let detector = Detector::new(board);
32//! let result = detector.detect(&image);
33//!
34//! for marker in &result.detected_markers {
35//! if let Some(id) = marker.id {
36//! println!("Marker {id} at ({:.1}, {:.1})", marker.center[0], marker.center[1]);
37//! }
38//! }
39//! ```
40//!
41//! ## Coordinate Frames
42//!
43//! Marker centers ([`DetectedMarker::center`]) are always in image-pixel
44//! coordinates, regardless of mapper usage. When a [`PixelMapper`] is active,
45//! [`DetectedMarker::center_mapped`] provides the working-frame (undistorted)
46//! coordinates, and the homography maps board coordinates to the working frame.
47//! [`DetectedMarker::board_xy_mm`] provides board-space marker coordinates in
48//! millimeters when a valid decoded ID is available on the active board.
49//!
50//! See [`DetectionResult::center_frame`] and [`DetectionResult::homography_frame`]
51//! for the frame metadata on each result.
52
53mod api;
54mod board_layout;
55mod conic;
56mod detector;
57mod homography;
58mod marker;
59mod pipeline;
60mod pixelmap;
61pub mod proposal;
62mod ring;
63mod target_generation;
64#[cfg(test)]
65pub(crate) mod test_utils;
66
67// ── Public API ──────────────────────────────────────────────────────────
68
69// High-level detector facade and proposal-only convenience helpers
70pub use api::{
71 propose_with_heatmap_and_marker_diameter, propose_with_heatmap_and_marker_scale,
72 propose_with_marker_diameter, propose_with_marker_scale, Detector,
73};
74
75// Proposal module (standalone ellipse center detection)
76pub use proposal::{find_ellipse_centers, find_ellipse_centers_with_heatmap};
77pub use proposal::{Proposal, ProposalConfig, ProposalResult};
78
79// Result types
80pub use detector::{DetectedMarker, DetectionSource, FitMetrics, InnerFitReason, InnerFitStatus};
81pub use homography::RansacStats;
82pub use marker::DecodeMetrics;
83pub use pipeline::{DetectionFrame, DetectionResult};
84
85// Configuration
86pub use detector::{
87 CircleRefinementMethod, CompletionParams, DetectConfig, IdCorrectionConfig,
88 InnerAsOuterRecoveryConfig, InnerFitConfig, MarkerScalePrior, OuterFitConfig,
89 ProjectiveCenterParams, ProposalDownscale, ScaleTier, ScaleTiers, SeedProposalParams,
90};
91pub use homography::RansacHomographyConfig;
92
93// Sub-configs
94pub use marker::{CodebookProfile, DecodeConfig};
95pub use ring::{EdgeSampleConfig, OuterEstimationConfig};
96
97// Geometry
98pub use board_layout::{
99 BoardLayout, BoardLayoutLoadError, BoardLayoutValidationError, BoardMarker,
100};
101pub use conic::Ellipse;
102pub use marker::MarkerSpec;
103pub use target_generation::{PngTargetOptions, SvgTargetOptions, TargetGenerationError};
104
105// Camera / distortion
106// These raw codebook/codec modules are re-exported for the ringgrid-cli diagnostic
107// commands (codebook-info, decode-test). They are not part of the stable library
108// API — external code should use the high-level Detector interface.
109#[doc(hidden)]
110pub use marker::codebook;
111#[doc(hidden)]
112pub use marker::codec;
113pub use pixelmap::{
114 CameraIntrinsics, CameraModel, DivisionModel, PixelMapper, RadialTangentialDistortion,
115 SelfUndistortConfig, SelfUndistortResult,
116};