calib-targets 0.12.0

Main entry point crate for a collection of plain calibration target detectors built on top of ChESS corners
Documentation

calib-targets

Target gallery — chessboard, ChArUco, PuzzleBoard, marker board

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

cargo add calib-targets

The image crate is re-exported as calib_targets::image (it ships with the default image feature), so you do not need to add it separately. Importing through the re-export guarantees your GrayImage type is exactly the one the helpers accept — no version-drift expected GrayImage, found GrayImage surprises. A direct cargo add image dependency still works.

Quickstart (chessboard)

use calib_targets::chessboard::ChessboardParams;
use calib_targets::detect;
use calib_targets::image::ImageReader;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let img = ImageReader::open("board.png")?.decode()?.to_luma8();
    let chess_cfg = detect::default_chess_config();
    let params = ChessboardParams::default();

    match detect::detect_chessboard(&img, &chess_cfg, &params) {
        Ok(det) => println!("labelled {} corners", det.corners.len()),
        Err(err) => println!("no board: {err}"),
    }
    Ok(())
}

Inputs (every helper)

  • image::GrayImage (or a GrayImageView on the detector traits).
  • A *Params config struct (ChessboardParams, CharucoParams, PuzzleBoardParams, MarkerBoardParams). Use ::default() for chessboard, ::for_board(spec) when a layout is required (constructors that store the board take it by value; the sweep_for_board(&spec) presets take it by reference).
  • For the *_best sweep helpers, a slice &[Params] — typically the 3-config preset ChessboardParams::sweep_default() for chessboards, or {Charuco,PuzzleBoard,MarkerBoard}Params::sweep_for_board(&spec) for the board detectors.

Outputs

Every detector emits a typed result object with a corners vector. Chessboard returns ChessboardCorner; ChArUco, PuzzleBoard, and marker boards return target-specific corner structs that can be converted to the shared TargetDetection carrier when needed. Each corner carries:

Field Meaning
position: Point2<f32> Sub-pixel image location.
grid (i, j) integer grid index, i right, j down, rebased so bounding-box min is (0, 0) where applicable.
id Logical corner ID on targets that provide one (ChArUco marker-referenced, PuzzleBoard master ID).
target_position 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_with_diagnostics 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-chessboard and projective-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:

  1. Switch to detect_*_best with the built-in 3-config sweep.
  2. Inspect which config succeeded (or none) — the sweep logs counts.
  3. 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
calib-targets gen chessboard \
    --inner-rows 6 --inner-cols 8 --square-size-mm 20 \
    --out-stem my_board

calib-targets gen puzzleboard \
    --rows 8 --cols 10 --square-size-mm 15 \
    --out-stem puzzle

# Two-step: init a reviewable spec first, then render
calib-targets init charuco \
    --out spec.json \
    --rows 5 --cols 7 --square-size-mm 20 \
    --marker-size-rel 0.75 --dictionary DICT_4X4_50
calib-targets validate --spec spec.json
calib-targets generate --spec spec.json --out-stem my_charuco

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 the calib_targets::detect helpers that take image::GrayImage inputs and run chess-corners internally.
  • tracing — gates tracing spans across the workspace crates.
  • diagnostics (off) — forwards to calib-targets-chessboard/diagnostics and gates detect_chessboard_with_diagnostics (the DebugFrame channel). The hot detect_chessboard path builds no trace when this is off.

Migrating to the current release

The chessboard detector's ChessboardParams is split into a stable core of four fields plus an opt-in, unstable advanced block (ChessboardAdvancedTuning); diagnostics moved behind a cargo feature; cell_size is back on ChessboardDetection; and the public config / result types are #[non_exhaustive] with named constructors. See the Migration Guide (also at MIGRATION.md) for before/after snippets covering Rust, the JSON config wire format, and Python.

Examples

cargo run -p calib-targets --example detect_chessboard -- path/to/image.png
cargo run -p calib-targets --example detect_chessboard_best -- path/to/image.png
cargo run -p calib-targets --example detect_charuco -- path/to/image.png
cargo run -p calib-targets --example detect_charuco_best -- path/to/image.png
cargo run -p calib-targets --example detect_markerboard -- path/to/image.png
cargo run -p calib-targets --example detect_puzzleboard -- path/to/image.png
cargo run -p calib-targets --example detect_puzzleboard_best -- path/to/image.png
cargo run -p calib-targets --example generate_printable \
    -- testdata/printable/charuco_a4.json tmpdata/printable/charuco_a4

Other bindings

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.

Links