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