Skip to main content

Crate chess_corners

Crate chess_corners 

Source
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 a chess_corners.Detector class whose detect(image) method accepts a 2D uint8 NumPy array and returns a float32 (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-corners npm 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) – enables Detector::detect and image::GrayImage integration.
  • rayon – parallelizes response computation and multiscale refinement over image rows. Combine with par_pyramid to parallelize pyramid downsampling as well.
  • ml-refiner – enables the ML-backed refiner entry points via the chess-corners-ml crate and embedded ONNX model.
  • simd – enables portable-SIMD accelerated inner loops for the response kernel (requires a nightly compiler). Combine with par_pyramid to SIMD-accelerate pyramid downsampling.
  • par_pyramid – opt-in gate for SIMD/rayon acceleration inside the pyramid builder.
  • tracing – emits structured spans for multiscale detection, suitable for use with tracing-subscriber or JSON tracing from the CLI.
  • cli – builds the chess-corners binary 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§

AxisEstimate
Direction of one local grid axis with its 1σ angular uncertainty.
AxisFitResult
Result of a two-axis orientation fit at a single corner.
CenterOfMassConfig
Configuration for the CenterOfMassRefiner.
ChessConfig
Configuration for the ChESS detector branch of DetectionStrategy.
ChessParams
Tunable parameters for the ChESS response computation and corner detection.
CoarseToFineParams
Parameters controlling the coarse-to-fine multiscale detector.
Corner
A detected corner candidate (subpixel position with raw response strength).
CornerDescriptor
Describes a detected chessboard corner in full-resolution image coordinates.
Detector
High-level chessboard-corner detector.
DetectorConfig
High-level detection configuration.
ForstnerConfig
Configuration for the ForstnerRefiner.
ImageBuffer
Owned grayscale image buffer (u8).
ImageView
Minimal grayscale view for refinement without taking a dependency on image.
PyramidBuffers
Reusable backing storage for pyramid construction.
PyramidParams
Parameters controlling pyramid generation.
RadonBuffers
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.
RadonConfig
Configuration for the whole-image Radon detector branch of DetectionStrategy.
RadonDetectorParams
Configuration for the whole-image Radon detector.
RadonPeakConfig
Configuration for RadonPeakRefiner.
RefineResult
Result of refining a single corner candidate.
ResponseMap
Dense response map in row-major layout.
Roi
Rectangular region of interest with half-open coordinate semantics [x0, x1) × [y0, y1).
SaddlePointConfig
Configuration for the SaddlePointRefiner.
UpscaleBuffers
Reusable scratch buffer for the upscaling stage.

Enums§

ChessError
Errors returned by detection and heatmap entry points.
ChessRefiner
Subpixel refiner selection for the ChESS detector.
ChessRing
ChESS sampling ring radius. Selects the r=5 (canonical) or r=10 (broad) ring used by the dense response kernel.
DescriptorRing
Descriptor sampling ring selection. Independent of the detector ring chosen by ChessRing.
DetectionStrategy
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.
MultiscaleConfig
Coarse-to-fine multiscale configuration.
OrientationMethod
Method used to fit the two grid axes at a detected corner.
PeakFitMode
Subpixel peak-fitting mode.
RadonRefiner
Subpixel refiner selection for the whole-image Radon detector.
RefineStatus
Status of a refinement attempt.
Refiner
Runtime refiner with reusable scratch buffers.
RefinerKind
User-facing enum selecting a refinement backend.
Threshold
Detector acceptance threshold.
UpscaleConfig
Optional pre-pipeline integer-factor upscaling.
UpscaleError
Errors returned by upscaling setup or execution.

Traits§

CornerRefiner
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 OrientationMethod at 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.