Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

vitavision.dev

Part I: Orientation

Part of the vitavision.dev computer-vision atlas. Self-contained algorithm overviews live at vitavision.dev/atlas/chess-corners and vitavision.dev/atlas/duda-radon-corners; this book is the implementation reference for the Rust workspace.

1.1 What the library does

chess-corners-rs detects the corners of a chessboard pattern — the X-junctions where four alternating dark/bright cells meet — to sub-pixel precision. It is the kind of detector that sits at the front of a camera calibration, pose estimation, or AR alignment pipeline.

Two independent detectors and five subpixel refiners live behind a single configuration type:

Both produce the same CornerDescriptor output, and both feed the same multiscale pipeline.

Once a detector has produced integer-pixel seeds, one of five subpixel refiners brings the coordinates under a pixel: CenterOfMass, Förstner, SaddlePoint, RadonPeak, or an ONNX-backed ML refiner. Each is selected through the active strategy’s refiner field. The refiners are described in Part V and benchmarked in Part VIII.

The same DetectorConfig drives a Rust API, a Python package, a browser WebAssembly package, and a CLI. They call the same Rust detector pipeline and use the same configuration schema.

1.2 Typical use cases

  • Camera calibration (mono, stereo, or multi-camera) with printed or screen-displayed chessboard targets.
  • Pose estimation of calibration rigs and fixtures.
  • Robotics and AR setups where a chessboard is a temporary alignment target.
  • Offline evaluation of external calibration pipelines: the detectors here are deterministic and independent of OpenCV.

Compared with other corner pipelines:

  • Versus generic corner detectors (Harris, Shi–Tomasi, FAST): both detectors here are specialized for chessboard X-junctions and reject edges, blobs, and texture that generic detectors accept.
  • Versus ID-based markers (AprilTag, ArUco): this library detects unlabeled grid corners. It does not decode an ID, so you need to know the board layout separately.

1.3 Workspace layout

The library is split across six crates; three are user-facing and three are implementation detail you only need if you want to go below the facade.

┌─ chess-corners-py      (PyO3 bindings, pip package: chess-corners)
├─ chess-corners-wasm    (wasm-bindgen, npm package: @vitavision/chess-corners)
│                        ▲
│                        │
├─ chess-corners         (high-level Rust API, CLI, multiscale pipeline)
│                        ▲
│                        │
├─ chess-corners-core    (low-level algorithms: ChESS + Radon detectors,
│                         refiners, descriptors)
│
├─ box-image-pyramid     (standalone u8 pyramid builder, fully
│                         independent — no chess-specific coupling)
│
└─ chess-corners-ml      (optional ONNX refiner; gated behind
                          `ml-refiner` feature)

Layering rules enforced by CI:

  • chess-corners-core does not depend on chess-corners.
  • box-image-pyramid has no chess-specific code — it is a reusable grayscale pyramid builder that happens to be used here.
  • Algorithms go in chess-corners-core; the facade crate adds the public DetectorConfig type, CLI, multiscale wiring, and feature gates.

Support directories:

  • config/ — example CLI JSON configs.
  • testdata/ — sample images used by tests, examples, and book plots.
  • tools/ — Python scripts for plotting, benchmarking, and the ML refiner training pipeline.
  • docs/ — design notes, proposals, and backlog.
  • book/ — this book (mdBook source under book/src/).

1.4 The CornerDescriptor output

Every detector in the workspace returns Vec<CornerDescriptor>. The type lives in chess-corners-core and is re-exported by the facade. Fields:

FieldTypeMeaning
x, yf32Subpixel position in input image pixels.
responsef32Raw detector response at the peak. Scale is detector-specific.
contrastf32 (≥ 0)Bright/dark amplitude from the ring intensity fit (gray levels).
fit_rmsf32 (≥ 0)RMS residual of that fit (gray levels).
axes[0, 1][AxisEstimate; 2]The two local grid axis directions, each with a 1σ angular uncertainty.

The two axes are not assumed orthogonal — projective warp or lens distortion tilts the sectors independently, and the fit recovers both directions. Polarity convention: axes[0].angle ∈ [0, π), axes[1].angle ∈ (axes[0].angle, axes[0].angle + π), with the CCW arc from axis 0 to axis 1 crossing a dark sector. Full details and the fit math are in Part III §3.4.

1.5 Where to go next

  • To run the detector on an image: Part II.
  • To understand the ChESS response: Part III.
  • To understand the Radon response: Part IV.
  • To pick a refiner: Part V for algorithms, Part VIII for measurements.
  • Orientation methods (RingFit / DiskFit): Part VI.
  • Multiscale pipeline and pyramid tuning: Part VII.
  • To contribute: Part IX.

Rust API documentation builds alongside this book and is published at the same site:

1.6 Installation and features

Rust

[dependencies]
chess-corners = "0.11"
image = "0.25"      # if you want GrayImage integration

Feature flags on the chess-corners facade:

FeatureEffect
imageDefault. image::GrayImage convenience entry points.
rayonParallelize response computation and multiscale refinement over cores.
simdPortable SIMD for the ChESS kernel. Nightly only.
par_pyramidSIMD / Rayon acceleration inside the pyramid downsampler.
tracingStructured tracing spans for the detector pipeline.
ml-refinerEnable the ONNX-backed refiner (chess-corners-ml dependency).
cliBuild the chess-corners binary.

All feature combinations produce the same numerical results; features only affect performance and observability.

Python

python -m pip install chess-corners

JavaScript / WebAssembly

wasm-pack build crates/chess-corners-wasm --target web
# installs an npm package: chess-corners-wasm

CLI

cargo run -p chess-corners --release --bin chess-corners -- \
    run config/chess_cli_config_example.json

Every surface consumes the same DetectorConfig JSON schema. Examples live under config/. The next part walks through the public API in all four surfaces.