Skip to main content

chess_corners/config/
chess.rs

1use chess_corners_core::{CenterOfMassConfig, ForstnerConfig, SaddlePointConfig};
2use serde::{Deserialize, Serialize};
3
4// ---------------------------------------------------------------------------
5// Detector kernel / ring selection
6// ---------------------------------------------------------------------------
7
8/// ChESS sampling ring radius. Selects the `r=5` (canonical) or `r=10`
9/// (broad) ring used by the dense response kernel.
10#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
11#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
12#[serde(rename_all = "snake_case")]
13#[non_exhaustive]
14pub enum ChessRing {
15    /// Paper-default radius-5 ring (16 samples).
16    #[default]
17    Canonical,
18    /// Radius-10 ring. Larger support window for callers that want the
19    /// detector to sample farther from the candidate center.
20    Broad,
21}
22
23// ---------------------------------------------------------------------------
24// Refiner enum
25// ---------------------------------------------------------------------------
26
27/// Subpixel refiner selection for the ChESS detector.
28///
29/// Each variant carries its own tuning struct as a payload: there is
30/// no shared discriminator + parallel-tuning-struct shape, so
31/// switching variants can never leave a stale config field behind.
32#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
33#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
34#[serde(rename_all = "snake_case")]
35#[non_exhaustive]
36pub enum ChessRefiner {
37    /// Center-of-mass (intensity centroid) refinement on the response
38    /// map. Cheapest refiner in the shipped benchmark; the library default.
39    CenterOfMass(CenterOfMassConfig),
40    /// Förstner structure-tensor refinement on the image patch.
41    Forstner(ForstnerConfig),
42    /// Quadratic surface fit at the saddle point.
43    SaddlePoint(SaddlePointConfig),
44    /// ML-backed subpixel refinement. Runs a small ONNX model on a
45    /// normalized intensity patch around each candidate. Requires the
46    /// `ml-refiner` feature.
47    #[cfg(feature = "ml-refiner")]
48    Ml,
49}
50
51impl Default for ChessRefiner {
52    fn default() -> Self {
53        Self::CenterOfMass(CenterOfMassConfig::default())
54    }
55}
56
57impl ChessRefiner {
58    /// Center-of-mass refinement with default tuning.
59    pub fn center_of_mass() -> Self {
60        Self::CenterOfMass(CenterOfMassConfig::default())
61    }
62    /// Förstner structure-tensor refinement with default tuning.
63    pub fn forstner() -> Self {
64        Self::Forstner(ForstnerConfig::default())
65    }
66    /// Saddle-point quadratic fit with default tuning.
67    pub fn saddle_point() -> Self {
68        Self::SaddlePoint(SaddlePointConfig::default())
69    }
70}
71
72// ---------------------------------------------------------------------------
73// Per-strategy config
74// ---------------------------------------------------------------------------
75
76/// Configuration for the ChESS detector branch of [`crate::DetectionStrategy`].
77///
78/// Carries the detector ring choice and the subpixel refiner. The shared
79/// NMS / clustering thresholds ([`crate::DetectionParams`]), multiscale, and
80/// upscale live at the top level of [`crate::DetectorConfig`] and apply to both
81/// strategies. Descriptors always sample at the detector ring radius.
82///
83/// # Common knobs
84///
85/// - [`ring`](ChessConfig::ring) — choose the detector kernel radius.
86/// - [`refiner`](ChessConfig::refiner) — select and configure the
87///   subpixel refinement backend.
88#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
89#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
90#[serde(default)]
91#[non_exhaustive]
92pub struct ChessConfig {
93    /// Detector ring radius. `Canonical` selects the paper's `r=5`,
94    /// `Broad` selects `r=10`. Descriptors sample at this same radius.
95    pub ring: ChessRing,
96    /// Subpixel refiner. Each variant carries its tuning struct.
97    pub refiner: ChessRefiner,
98}
99
100impl Default for ChessConfig {
101    fn default() -> Self {
102        Self {
103            ring: ChessRing::Canonical,
104            refiner: ChessRefiner::default(),
105        }
106    }
107}