Expand description
Ergonomic ChESS / Radon corner-detector facade over
chess-corners-core.
§Overview
This crate is the high-level entry point for two chessboard-corner detectors that share the same output surface:
- ChESS (Chess-board Extraction by Subtraction and Summation) — a dense ring-difference response with NMS and a pluggable subpixel refiner. This is the default path and the fastest preset in the repository’s clean-image benchmark.
- Radon — a whole-image Duda-Frese accumulator that scores corners by summing ray intensities through each pixel. It is useful when the ChESS ring does not produce enough seeds, especially in the small-cell, blur, and low-contrast fixtures covered by the tests.
The Detector struct ties together the active strategy, the
orientation fit, and the multiscale / upscale scratch buffers
behind a single detect call. It returns subpixel
CornerDescriptor values in full-resolution input coordinates.
In most applications you construct a DetectorConfig (typically
via DetectorConfig::chess, DetectorConfig::chess_multiscale,
DetectorConfig::radon, or DetectorConfig::radon_multiscale),
optionally tweak its fields, build a Detector, and call
Detector::detect.
Building a Detector once and calling Detector::detect in a
loop reuses the pyramid, response, and upscale scratch buffers
across frames — no per-frame allocation.
§Quick start
§Using image (default)
The default feature set includes integration with the image
crate. This example reads from disk and is marked no_run:
use chess_corners::{ChessRefiner, Detector, DetectorConfig, Threshold};
use image::io::Reader as ImageReader;
let img = ImageReader::open("board.png")?
.decode()?
.to_luma8();
let cfg = DetectorConfig::chess_multiscale()
.with_threshold(Threshold::Relative(0.15))
.with_chess(|c| c.refiner = ChessRefiner::forstner());
let mut detector = Detector::new(cfg)?;
let corners = detector.detect(&img)?;
println!("found {} corners", corners.len());
for c in &corners {
println!(
"corner at ({:.2}, {:.2}), response {:.1}, axes [{:.2}, {:.2}] rad",
c.x, c.y, c.response, c.axes[0].angle, c.axes[1].angle,
);
}§Raw grayscale buffer
If you already have an 8-bit grayscale buffer, call
Detector::detect_u8:
use chess_corners::{Detector, DetectorConfig};
// 8×8 black/white checkerboard of 16-pixel squares (128×128).
let mut img = vec![0u8; 128 * 128];
for y in 0..128 {
for x in 0..128 {
if ((x / 16) + (y / 16)) % 2 == 0 {
img[y * 128 + x] = 255;
}
}
}
let cfg = DetectorConfig::chess();
let mut detector = Detector::new(cfg)?;
let corners = detector.detect_u8(&img, 128, 128)?;
assert!(!corners.is_empty());§Radon strategy
Switch to the whole-image Radon detector when ChESS misses corners on
the images you care about. The strategy lives inside
DetectorConfig::strategy; pick a Radon preset to get sensible
defaults:
use chess_corners::{Detector, DetectorConfig};
let mut img = vec![0u8; 128 * 128];
for y in 0..128 {
for x in 0..128 {
if ((x / 16) + (y / 16)) % 2 == 0 {
img[y * 128 + x] = 255;
}
}
}
let cfg = DetectorConfig::radon();
let mut detector = Detector::new(cfg)?;
let corners = detector.detect_u8(&img, 128, 128)?;
assert!(!corners.is_empty());§ML refiner (feature ml-refiner)
Pick the ML pipeline by selecting ChessRefiner::Ml inside the
ChESS strategy. The example is marked no_run because loading the
embedded ONNX model on first use is not appropriate for a doctest:
use chess_corners::{ChessRefiner, Detector, DetectorConfig};
use image::GrayImage;
let cfg = DetectorConfig::chess()
.with_chess(|c| c.refiner = ChessRefiner::Ml);
let img: GrayImage = image::open("board.png").unwrap().to_luma8();
let mut detector = Detector::new(cfg).unwrap();
let corners = detector.detect(&img).unwrap();The ML refiner runs a small ONNX model on normalized intensity
patches (uint8 / 255.0) centered at each candidate. The model
predicts [dx, dy, conf_logit], but the confidence output is
currently ignored; the offsets are applied directly. Current
accuracy benchmarks are synthetic; real-world accuracy still needs
validation. Per-refiner cost is measured in Part VIII §7.6 of the
book. The ML path is slower than the hand-coded refiners and should
be chosen only after measuring that its behavior helps your data.
§Python and JavaScript bindings
The workspace also ships bindings that wrap this facade:
crates/chess-corners-py(PyO3 / maturin) exposes achess_corners.Detectorclass whosedetect(image)method accepts a 2Duint8NumPy array and returns afloat32(N, 9)array with columns[x, y, response, contrast, fit_rms, axis0_angle, axis0_sigma, axis1_angle, axis1_sigma]. See its README for usage and configuration details.crates/chess-corners-wasm(wasm-bindgen / wasm-pack) exposes the same surface to JavaScript / TypeScript via the@vitavision/chess-cornersnpm package.
§Configuration
DetectorConfig is strategy-typed: the DetectorConfig::strategy
field is a DetectionStrategy enum carrying either a
ChessConfig (detector ring, descriptor ring, NMS, refiner) or
a RadonConfig (whole-image Duda-Frese parameters). Acceptance
is a single Threshold enum (Absolute or Relative).
MultiscaleConfig and UpscaleConfig live at the top level
and apply to both strategies. The detector translates this into
the lower-level ChessParams / RadonDetectorParams structs
internally.
If you need raw response maps or more control, the most useful
low-level primitives are re-exported here:
chess_response_u8, chess_response_u8_patch, Roi,
detect_corners_from_response_with_refiner, Corner, and
describe_corners. For deeper internals (ring offsets,
SAT views, scalar reference paths) depend on chess-corners-core
directly.
§Features
image(default) – enablesDetector::detectandimage::GrayImageintegration.rayon– parallelizes response computation and multiscale refinement over image rows. Combine withpar_pyramidto parallelize pyramid downsampling as well.ml-refiner– enables the ML-backed refiner entry points via thechess-corners-mlcrate and embedded ONNX model.simd– enables portable-SIMD accelerated inner loops for the response kernel (requires a nightly compiler). Combine withpar_pyramidto SIMD-accelerate pyramid downsampling.par_pyramid– opt-in gate for SIMD/rayonacceleration inside the pyramid builder.tracing– emits structured spans for multiscale detection, suitable for use withtracing-subscriberor JSON tracing from the CLI.cli– builds thechess-cornersbinary shipped with this crate; it is not required when using the library as a dependency.
The library API is stable across feature combinations; features only affect performance and observability, not numerical results.
§References
- Bennett, Lasenby. ChESS: A Fast and Accurate Chessboard Corner Detector. CVIU 2014.
- Duda, Frese. Accurate Detection and Localization of Checkerboard Corners for Calibration. BMVC 2018.
Structs§
- Axis
Estimate - Direction of one local grid axis with its 1σ angular uncertainty.
- Axis
FitResult - Result of a two-axis orientation fit at a single corner.
- Center
OfMass Config - Configuration for the
CenterOfMassRefiner. - Chess
Config - Configuration for the ChESS detector branch of
DetectionStrategy. - Chess
Params - Tunable parameters for the ChESS response computation and corner detection.
- Coarse
ToFine Params - Parameters controlling the coarse-to-fine multiscale detector.
- Corner
- A detected corner candidate (subpixel position with raw response strength).
- Corner
Descriptor - Describes a detected chessboard corner in full-resolution image coordinates.
- Detector
- High-level chessboard-corner detector.
- Detector
Config - High-level detection configuration.
- Forstner
Config - Configuration for the
ForstnerRefiner. - Image
Buffer - Owned grayscale image buffer (u8).
- Image
View - Minimal grayscale view for refinement without taking a dependency on
image. - Pyramid
Buffers - Reusable backing storage for pyramid construction.
- Pyramid
Params - Parameters controlling pyramid generation.
- Radon
Buffers - Reusable scratch for the whole-image Radon detector. Holds the
upsampled image buffer, the four summed-area tables, the response
map, and the box-blur scratch. All buffers grow on demand and are
reused across frames — same pattern as
PyramidBuffers. - Radon
Config - Configuration for the whole-image Radon detector branch of
DetectionStrategy. - Radon
Detector Params - Configuration for the whole-image Radon detector.
- Radon
Peak Config - Configuration for
RadonPeakRefiner. - Refine
Result - Result of refining a single corner candidate.
- Response
Map - Dense response map in row-major layout.
- Roi
- Rectangular region of interest with half-open coordinate semantics
[x0, x1) × [y0, y1). - Saddle
Point Config - Configuration for the
SaddlePointRefiner. - Upscale
Buffers - Reusable scratch buffer for the upscaling stage.
Enums§
- Chess
Error - Errors returned by detection and heatmap entry points.
- Chess
Refiner - Subpixel refiner selection for the ChESS detector.
- Chess
Ring - ChESS sampling ring radius. Selects the
r=5(canonical) orr=10(broad) ring used by the dense response kernel. - Descriptor
Ring - Descriptor sampling ring selection. Independent of the detector ring
chosen by
ChessRing. - Detection
Strategy - Top-level detector dispatch. Selects between the ChESS kernel pipeline and the Radon whole-image detector. The chosen variant carries all detector-specific tuning; settings that don’t apply to the active detector are simply unreachable, so the type system enforces correctness instead of silently ignoring fields.
- Multiscale
Config - Coarse-to-fine multiscale configuration.
- Orientation
Method - Method used to fit the two grid axes at a detected corner.
- Peak
FitMode - Subpixel peak-fitting mode.
- Radon
Refiner - Subpixel refiner selection for the whole-image Radon detector.
- Refine
Status - Status of a refinement attempt.
- Refiner
- Runtime refiner with reusable scratch buffers.
- Refiner
Kind - User-facing enum selecting a refinement backend.
- Threshold
- Detector acceptance threshold.
- Upscale
Config - Optional pre-pipeline integer-factor upscaling.
- Upscale
Error - Errors returned by upscaling setup or execution.
Traits§
- Corner
Refiner - Trait implemented by pluggable refinement backends.
Functions§
- chess_
response_ u8 - Compute the dense ChESS response for an 8-bit grayscale image.
- chess_
response_ u8_ patch - Compute the ChESS response only inside a rectangular ROI of the image.
- describe_
corners - Convert raw corner candidates into full descriptors by sampling the
source image and running the chosen
OrientationMethodat each corner. - detect_
corners_ from_ response - Core detector: run NMS + refinement on an existing response map.
- detect_
corners_ from_ response_ with_ refiner - Detector variant that accepts a user-provided refiner implementation.
- radon_
heatmap_ image - Compute the Radon response heatmap from an
image::GrayImage. - radon_
heatmap_ u8 - Compute the whole-image Radon response heatmap from a raw grayscale buffer.
- rescale_
descriptors_ to_ input - Rescale corner positions from an upscaled image back to the original input-image pixel frame.
- upscale_
bilinear_ u8 - Bilinear upscaling by an integer factor into the provided buffer.