Skip to main content

radsym/
lib.rs

1//! # radsym
2//!
3//! Radial symmetry detection library: center proposal generation, local
4//! circular and elliptical support analysis, support scoring, and local
5//! image-space refinement. CPU-first, deterministic, composable tools.
6//!
7//! ## Quick start
8//!
9//! ```rust
10//! use radsym::{
11//!     ImageView, FrstConfig, Circle, Polarity, ScoringConfig, NmsConfig,
12//!     sobel_gradient, frst_response, extract_proposals, score_circle_support,
13//! };
14//!
15//! // 1. Load or create an image (here: synthetic bright disk)
16//! let size = 64;
17//! let mut data = vec![0u8; size * size];
18//! for y in 0..size {
19//!     for x in 0..size {
20//!         let dx = x as f32 - 32.0;
21//!         let dy = y as f32 - 32.0;
22//!         if (dx * dx + dy * dy).sqrt() <= 10.0 {
23//!             data[y * size + x] = 255;
24//!         }
25//!     }
26//! }
27//! let image = ImageView::from_slice(&data, size, size).unwrap();
28//!
29//! // 2. Compute gradient and FRST response
30//! let gradient = sobel_gradient(&image).unwrap();
31//! let config = FrstConfig { radii: vec![9, 10, 11], ..FrstConfig::default() };
32//! let response = frst_response(&gradient, &config).unwrap();
33//!
34//! // 3. Extract proposals via NMS
35//! let nms = NmsConfig { radius: 5, threshold: 0.0, max_detections: 5 };
36//! let proposals = extract_proposals(&response, &nms, Polarity::Bright);
37//!
38//! // 4. Score the best proposal
39//! if let Some(best) = proposals.first() {
40//!     let circle = Circle::new(best.seed.position, 10.0);
41//!     let score = score_circle_support(&gradient, &circle, &ScoringConfig::default());
42//!     assert!(score.total > 0.0);
43//! }
44//! ```
45//!
46//! ## Modules
47//!
48//! - [`core`] — fundamental types, image views, geometry, gradient, NMS,
49//!   homography, circle fitting
50//! - [`propose`] — center-proposal generation (FRST, RSD, homography-aware)
51//! - [`support`] — local support extraction and scoring
52//! - [`refine`] — local hypothesis refinement (Parthasarathy radial center,
53//!   iterative circle/ellipse, homography-aware ellipse)
54//! - [`diagnostics`] — visualization: heatmaps, overlays
55//!
56//! ## Feature flags
57//!
58//! - `rayon` — parallel execution for multi-radius proposals
59//! - `image-io` — load images via the `image` crate
60//! - `tracing` — structured logging
61//! - `affine` — experimental affine-aware extensions (GFRS)
62//! - `serde` — serialization support
63
64pub mod core;
65pub mod diagnostics;
66pub mod pipeline;
67pub mod prelude;
68pub mod propose;
69pub mod refine;
70pub mod support;
71
72#[cfg(feature = "affine")]
73pub mod affine;
74
75// Re-export the most commonly used types at crate root.
76
77// Core types
78pub use crate::core::circle_fit::{fit_circle, fit_circle_weighted};
79pub use crate::core::coords::PixelCoord;
80pub use crate::core::error::{RadSymError, Result};
81pub use crate::core::geometry::{Annulus, Circle, Ellipse};
82pub use crate::core::gradient::{
83    compute_gradient, compute_gradient_f32, scharr_gradient, scharr_gradient_f32, sobel_gradient,
84    sobel_gradient_f32, GradientField, GradientOperator,
85};
86pub use crate::core::homography::{rectified_circle_to_image_ellipse, Homography, RectifiedGrid};
87pub use crate::core::image_view::{ImageView, OwnedImage};
88pub use crate::core::nms::NmsConfig;
89pub use crate::core::polarity::Polarity;
90pub use crate::core::pyramid::{
91    pyramid_level_owned, OwnedPyramidLevel, PyramidLevelView, PyramidWorkspace,
92};
93
94// Proposal generation
95pub use crate::propose::extract::{extract_proposals, suppress_proposals_by_distance, ResponseMap};
96pub use crate::propose::frst::{
97    frst_response, frst_response_single, multiradius_response, FrstConfig,
98};
99pub use crate::propose::homography::{
100    extract_rectified_proposals, frst_response_homography, rerank_proposals_homography,
101    HomographyProposal, HomographyRerankConfig, RectifiedResponseMap, RerankedProposal,
102};
103pub use crate::propose::remap::{remap_proposal_to_image, remap_proposals_to_image};
104pub use crate::propose::rsd::{rsd_response, rsd_response_fused, RsdConfig};
105pub use crate::propose::seed::{Proposal, ProposalSource, SeedPoint};
106
107// Support scoring
108pub use crate::support::annulus::AnnulusSamplingConfig;
109pub use crate::support::evidence::SupportEvidence;
110pub use crate::support::hypothesis::{
111    AnnulusHypothesis, CircleHypothesis, ConcentricPairHypothesis, EllipseHypothesis,
112};
113pub use crate::support::score::{
114    score_circle_support, score_ellipse_support, score_rectified_circle_support, ScoringConfig,
115    SupportScore,
116};
117
118// Refinement
119pub use crate::refine::circle::{refine_circle, CircleRefineConfig};
120pub use crate::refine::ellipse::{refine_ellipse, EllipseRefineConfig};
121pub use crate::refine::homography::{
122    refine_ellipse_homography, HomographyEllipseRefineConfig, HomographyRefinementResult,
123};
124pub use crate::refine::radial_center::{
125    radial_center_refine, radial_center_refine_from_gradient, RadialCenterConfig,
126};
127pub use crate::refine::result::{RefinementResult, RefinementStatus};
128
129// Pipeline
130pub use crate::pipeline::{detect_circles, DetectCirclesConfig, Detection};
131
132// Diagnostics
133pub use crate::diagnostics::heatmap::{response_heatmap, Colormap, DiagnosticImage};
134pub use crate::diagnostics::overlay::{overlay_circle, overlay_ellipse};
135
136// I/O (feature-gated)
137#[cfg(feature = "image-io")]
138pub use crate::core::io::load_grayscale;
139#[cfg(feature = "image-io")]
140pub use crate::diagnostics::export::{save_diagnostic, save_grayscale, save_response_map};