1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//! Error types for the detection pipeline.
use thiserror::Error;
/// Errors that can occur during detector configuration validation.
#[derive(Debug, Clone, Error)]
pub enum ConfigError {
/// Threshold tile size must be >= 2.
#[error("threshold_tile_size must be >= 2, got {0}")]
TileSizeTooSmall(usize),
/// Decimation factor must be >= 1.
#[error("decimation factor must be >= 1, got {0}")]
InvalidDecimation(usize),
/// Upscale factor must be >= 1.
#[error("upscale_factor must be >= 1, got {0}")]
InvalidUpscaleFactor(usize),
/// Minimum fill ratio must be in [0.0, 1.0].
#[error("fill ratio range invalid: min={min}, max={max} (must be 0.0..=1.0, min < max)")]
InvalidFillRatio {
/// The minimum fill ratio that was set.
min: f32,
/// The maximum fill ratio that was set.
max: f32,
},
/// Minimum edge length must be positive.
#[error("quad_min_edge_length must be positive, got {0}")]
InvalidEdgeLength(f64),
/// Structure tensor radius must stay within the supported kernel bound.
#[error("structure_tensor_radius must be <= 8, got {0}")]
InvalidStructureTensorRadius(u8),
/// EdLines is geometrically incompatible with Erf corner refinement.
///
/// Erf performs an independent 1-D search per corner which destroys the
/// planarity constraint established by the joint Gauss-Newton solver in
/// the EdLines pipeline, degrading corner RMSE from ~0.17 px to ~0.59 px.
#[error(
"EdLines + Erf refinement are incompatible: use CornerRefinementMode::None or \
CornerRefinementMode::Gwlf with EdLines"
)]
EdLinesIncompatibleWithErf,
/// EdLines is statistically incompatible with Soft (LLR) decoding.
///
/// EdLines produces a large number of background line-segment candidates.
/// Soft decoding forces deep probabilistic evaluation of all of them,
/// causing a 10–22% precision collapse compared to Hard decoding.
#[error("EdLines + Soft decoding are incompatible: use DecodeMode::Hard with EdLines")]
EdLinesIncompatibleWithSoftDecode,
/// EdLines is geometrically incompatible with distorted cameras.
///
/// EdLines' Huber IRLS line fit, micro-ray parabola, and GN refinement all
/// assume Euclidean pixel geometry. A Brown-Conrady or Kannala-Brandt
/// intrinsic bends marker edges into curves, invalidating that assumption.
/// Use `QuadExtractionMode::ContourRdp` when passing distortion coefficients.
#[error(
"EdLines is geometrically incompatible with distorted cameras (BrownConrady / \
KannalaBrandt): use QuadExtractionMode::ContourRdp"
)]
EdLinesUnsupportedWithDistortion,
/// Profile JSON failed to parse (malformed syntax or unknown fields).
///
/// `serde_json::Error` is not `Clone`, so its `Display` form is captured
/// at construction time. The wrapping `ConfigError` stays `Clone`.
#[error("profile JSON parse error: {0}")]
ProfileParse(String),
}
/// Errors that can occur during tag detection.
#[derive(Debug, Clone, Error)]
pub enum DetectorError {
/// Image preprocessing (decimation or upscaling) failed.
#[error("preprocessing failed: {0}")]
Preprocessing(String),
/// Image view construction failed (invalid dimensions/stride).
#[error("invalid image: {0}")]
InvalidImage(String),
/// Configuration validation failed.
#[error("config error: {0}")]
Config(#[from] ConfigError),
}