calib-targets

Fast, robust calibration-target detection in Rust: chessboard, ChArUco,
PuzzleBoard, and checkerboard marker boards. This is the facade
crate — the one most users install. It re-exports every detector in the
workspace and adds one-call helpers that take an image::GrayImage, run
ChESS corner detection, and return a labelled grid.
Install-friendly entry for the workspace; each detector has its own crate with deeper documentation and tuning reference, linked below.
Book: https://vitalyvorobyev.github.io/calib-targets-rs/
Install
Quickstart (chessboard)
use DetectorParams;
use detect;
use ImageReader;
Inputs (every helper)
image::GrayImage(or aGrayImageViewon the detector traits).- A
*Paramsconfig struct (DetectorParams,CharucoParams,PuzzleBoardParams,MarkerBoardParams). Use::default()for chessboard,::for_board(&spec)when a layout is required. - For the
*_bestsweep helpers, a slice&[Params]— typically the 3-config presetParams::sweep_default(&spec).
Outputs
Every detector emits a TargetDetection (returned directly by
chessboard; wrapped inside CharucoDetectionResult,
PuzzleBoardDetectionResult, MarkerBoardDetectionResult for the
others). Each LabeledCorner carries:
| Field | Meaning |
|---|---|
position: Point2<f32> |
Sub-pixel image location. |
grid: Option<GridCoords> |
(i, j) integer grid index, i right, j down, rebased so bounding-box min is (0, 0). |
id: Option<u32> |
Logical corner ID on the target (ChArUco marker-referenced, PuzzleBoard master ID). |
target_position: Option<Point2<f32>> |
Physical location on the printed board (mm / board units), when cell size and alignment are known. |
score: f32 |
Detector-specific quality score. |
Chessboard enforces two hard invariants on its output: no duplicate
(i, j) labels, and (0, 0) sits at the visual top-left of the
detected grid.
Supported targets
| Target | Facade helpers | Dedicated crate |
|---|---|---|
| Chessboard | detect_chessboard, detect_chessboard_all, detect_chessboard_best, detect_chessboard_debug |
calib-targets-chessboard |
| ChArUco | detect_charuco, detect_charuco_best |
calib-targets-charuco |
| PuzzleBoard | detect_puzzleboard, detect_puzzleboard_best |
calib-targets-puzzleboard |
| Marker board | detect_marker_board, detect_marker_board_best |
calib-targets-marker |
| Printable targets | printable::{render_target_bundle, write_target_bundle} |
calib-targets-print |
| ArUco / AprilTag primitives | aruco::* (dictionaries, matcher) |
calib-targets-aruco |
Every detector ships a single-config helper and a 3-config
*_best sweep. The sweep is the recommended default for new callers:
it handles threshold tradeoffs without forcing manual tuning.
Main ideas
- Grid-first. Every detector reduces to "find a chessboard grid,
then decode anchors / dots / circles in rectified cells". The heavy
lifting lives in
calib-targets-chessboardandprojective-grid. - Precision-by-construction. Wrong
(i, j)labels would corrupt calibration, so the detectors reject before they guess. - Local invariants, not global warps. The graph, seed, and validation pieces work on local neighbourhoods, so moderate perspective and radial distortion are handled without an explicit distortion model.
- Partial boards supported. PuzzleBoard gives absolute IDs from any visible fragment; ChArUco and marker boards label whatever is visible.
Tuning difficult cases
Most callers never need to tune. When defaults fail:
- Switch to
detect_*_bestwith the built-in 3-config sweep. - Inspect which config succeeded (or none) — the sweep logs counts.
- If all fail, open the corresponding detector README: chessboard, ChArUco, PuzzleBoard, marker, or the book tuning chapter for cross-detector guidance.
Limitations
- One target instance per image. Multiple simultaneous boards are not disambiguated; the largest detection wins.
- Pinhole-ish optics only. Moderate perspective and radial distortion are handled gracefully; fisheye and extreme wide-angle lenses are not supported.
- Grayscale input. Colour images must be converted by the caller
(
.to_luma8()). - No temporal tracking. Every call is independent.
- Roughly-square cells. Strongly anisotropic aspect ratios degrade detection — rescale the input first.
Printable targets
calib_targets::printable re-exports calib-targets-print.
PrintableTargetDocument is the canonical JSON input, and
write_target_bundle writes <stem>.json, <stem>.svg, <stem>.png
in one call. The calib_targets::generate module adds ergonomic
constructors (chessboard_document, charuco_document,
puzzleboard_document, marker_board_document) that hide the
TargetSpec enum wrapping. Ready-made specs live under
testdata/printable/.
CLI
cargo install calib-targets ships a calib-targets binary with two
generation flows:
# One-step: flags directly to JSON+SVG+PNG bundle
# Two-step: init a reviewable spec first, then render
Run calib-targets list-dictionaries to enumerate built-in ArUco
dictionaries. The CLI is gated on the default cli feature; library-only
consumers can disable it with default-features = false.
Canonical guide: printable-target book chapter.
Features
image(default) — enables thecalib_targets::detecthelpers that takeimage::GrayImageinputs and runchess-cornersinternally.tracing— gates tracing spans across the workspace crates.
Chessboard API — 0.7 migration note
In 0.7 the chessboard detector's top-level types were renamed from
ChessboardDetector / ChessboardParams / ChessboardDetectionResult
to Detector / DetectorParams / Detection. DetectorParams is
flat — the old nested graph / gap_fill / local_homography
sub-structs are gone. Import paths move from
calib_targets::chessboard::ChessboardParams to
calib_targets::chessboard::DetectorParams; detect_chessboard* now
takes &DetectorParams.
Examples
Other bindings
- Python —
calib-targets-pywraps the same facade viamaturin. The Python package name iscalib_targets. - WebAssembly —
@vitavision/calib-targetson npm exposes the detectors to the browser. - C FFI —
calib-targets-ffiexposes a stable C ABI with CMake package.
Crate map
| Re-export | Crate |
|---|---|
calib_targets::core |
calib-targets-core — shared types, homographies |
calib_targets::chessboard |
calib-targets-chessboard — invariant-first chessboard |
calib_targets::aruco |
calib-targets-aruco — ArUco / AprilTag dictionaries + decoding |
calib_targets::charuco |
calib-targets-charuco — ChArUco detection |
calib_targets::puzzleboard |
calib-targets-puzzleboard — self-identifying chessboard |
calib_targets::marker |
calib-targets-marker — checkerboard + 3 circle markers |
calib_targets::printable |
calib-targets-print — printable targets |
Underneath everything sits the standalone projective-grid library —
useful if you want grid construction without the calibration layer.