Native Shell
Native Shell: AI-generated UI, native in your app, on every platform. Apps on iOS, Android, macOS, Windows and Linux, GPUI apps and web pages load signed, sandboxed TSX modules at run time and draw th
Calibration-target detection in Rust — chessboards, ChArUco, PuzzleBoard, and marker boards from grayscale images. One grid-first algorithmic core, typed results per target.
Developer toolsRust · PythonGitHub @VitalyVorobyevOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
A collection of algorithms for detection of calibration targets
Translation pending
Taken from the repository README
Loading the full README.
Read the full README ↗Calibration-target detection in Rust. Detects chessboards, ChArUco, PuzzleBoard, PuzzlePole, and checkerboard marker boards from grayscale images. Ships as Rust crates, Python bindings, WebAssembly bindings, and a stable C ABI. One grid-first algorithmic core; typed result objects per target, with a shared corner vocabulary.
Status: feature-complete. The public API is being finalised ahead of a stable release and may still change at minor versions.
| Target | What it is |
|---|---|
| Chessboard | Plain checkerboard. Detector returns labelled corner positions with (0, 0) rebased to the visual top-left. No markers; corners are not individually identified. |
| ChArUco | Chessboard with ArUco markers in white squares. Each labelled corner gets a globally-unique ID derived from the surrounding markers; partial views decode. |
| PuzzleBoard | Self-identifying chessboard (Stelldinger 2024) with edge-midpoint dots encoding a 501 × 501 master pattern. Any visible fragment yields the same absolute corner IDs a full-view decode would. Full and FixedBoard search modes; soft-log-likelihood evidence is available through diagnostics for downstream consistency checks. |
| PuzzlePole | The PuzzleBoard pattern wrapped round a cylinder (Zach & Stelldinger 2025), so the target is identifiable from a full 360°. The only family here that is not flat, and the only one whose corners carry 3-D object points — ready for PnP, which stays with the caller. |
| Marker board | Plain checkerboard with three large circle markers establishing a unique origin without a dictionary. |
Full documentation: book · API reference · getting-started tutorial. Upgrading from an earlier release? See the Migration Guide (book chapter); the 0.15.0 guide is kept for consumers upgrading across two releases.
calib-targets-chessboard and
projective-grid.detect_chessboard_all returns
every connected component when occlusion splits the board.Detection.detect_*_best tries three built-in presets
and keeps the best result — no hand-tuning required for the common
failure cases.cargo add calib-targets image
use calib_targets::chessboard::ChessboardParams;
use calib_targets::detect;
use image::ImageReader;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let img = ImageReader::open("board.png")?.decode()?.to_luma8();
// The simplest call: default ChESS corner config + default detector params.
let detection = detect::detect_chessboard(
&img,
&detect::default_chess_config(),
&ChessboardParams::default(),
);
match detection {
Ok(det) => {
println!("detected {} corners", det.corners.len());
for c in &det.corners {
// position: sub-pixel (x, y) in pixels; grid: (u, v) lattice index
println!(" ({:.1}, {:.1}) -> grid ({}, {})",
c.position.x, c.position.y, c.grid.u, c.grid.v);
}
}
// `is_not_found` separates a miss from a misuse (a bad image or config).
Err(err) if err.is_not_found() => println!("no board detected: {err}"),
Err(err) => return Err(err.into()),
}
Ok(())
}
If detection is unreliable on a hard image (steep angle, blur, glare), reach
for the sweep helper instead of hand-tuning. detect_chessboard_best runs
several parameter presets and keeps the richest result;
ChessboardParams::sweep_default() supplies three that bracket the
robustness/precision trade-off (balanced, tighter for clean boards, looser
for distorted views):
use calib_targets::chessboard::ChessboardParams;
use calib_targets::detect;
use image::ImageReader;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let img = ImageReader::open("board.png")?.decode()?.to_luma8();
let detection = detect::detect_chessboard_best(
&img,
&detect::default_chess_config(),
&ChessboardParams::sweep_default(),
)?;
println!("detected {} corners", detection.corners.len());
Ok(())
}
The other targets follow the same shape — detect_charuco,
detect_puzzleboard, detect_puzzlepole, detect_marker_board. Each also has a
*_with_corners variant for reusing one ChESS corner pass across several
target detectors, diagnose_* / diagnose_*_with_corners counterparts
(diagnostics feature) for per-stage rejection detail, and a *_best
sweep variant. Runnable examples:
detect_charuco,
detect_markerboard,
detect_puzzleboard,
detect_puzzlepole.
pip install calib-targets numpy Pillow
import numpy as np
from PIL import Image
import calib_targets as ct
image = np.asarray(Image.open("board.png").convert("L"), dtype=np.uint8)
# Simplest call — all defaults:
result = ct.detect_chessboard(image)
if result is not None:
print(f"detected {len(result.corners)} corners")
for c in result.corners:
print(f" pos={c.position} grid={c.grid}") # position in pixels, grid = (i, j)
# If detection is unreliable, try several presets and keep the best result:
configs = [
ct.ChessboardParams(), # balanced default
ct.ChessboardParams(min_labeled_corners=12), # require a denser board
ct.ChessboardParams(max_components=1), # single connected grid only
]
result = ct.detect_chessboard_best(image, configs)
End-to-end round-trip examples per target type (generate → detect →
export to JSON) live under
crates/calib-targets-py/examples/ —
one runnable script per target:
chessboard_roundtrip.py, charuco_roundtrip.py,
markerboard_roundtrip.py, puzzleboard_roundtrip.py.
Browser-ready WASM bindings, with a React demo:
scripts/build-wasm.sh
cd demo && bun install && bun run dev
See @vitavision/calib-targets on npm
(source under crates/calib-targets-wasm/) for the TypeScript API
and per-target snippets.
Generate a target, print at 100 % scale, then detect:
import calib_targets as ct
doc = ct.PrintableTargetDocument(
target=ct.CharucoTargetSpec(
rows=5, cols=7, square_size_mm=20.0,
marker_size_rel=0.75, dictionary="DICT_4X4_50",
)
)
ct.write_target_bundle(doc, "my_board/charuco_a4") # .json + .svg + .png
Ready-made specs for all four target types: testdata/printable/.
Canonical guide: printable-target chapter.
Each detector returns a typed result; its corners share a common vocabulary.
A chessboard corner (ChessboardCorner) carries:
position — sub-pixel (x, y) in pixels (image origin top-left).grid — integer lattice index Coord { u, v } (u increases
right, v down), rebased so the top-left visible corner is (0, 0).score — corner quality.ChArUco, PuzzleBoard, and marker corners add an id (a globally unique
corner identifier) and a target_position (the corner's location on the
physical board, in millimetres) once the board is aligned. The book chapter
Understanding Results documents exactly when each optional field
is populated; the API reference lists every result type and field.
| Crate | crates.io | Role |
|---|---|---|
calib-targets | published | Facade — the crate most users install. End-to-end detect_* / detect_*_best. |
projective-grid | published | Backbone — standalone grid graph, traversal, homography. |
calib-targets-core | published | Shared types: Corner, LabeledCorner, TargetDetection. |
calib-targets-chessboard | published | Invariant-first chessboard detector. |
calib-targets-aruco | published | ArUco / AprilTag dictionaries and decoding. |
calib-targets-charuco | published |
The printable-target CLI now ships with both the facade crate and the Python
package: cargo install calib-targets provides a calib-targets binary, and
pip install calib-targets provides the same command as a Python console
script. See crates/calib-targets/README.md
for usage.
cargo fmt --all --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace --all-features
cargo doc --workspace --no-deps # must produce zero warnings
mdbook build book
Pre-release quality gates (binding parity, typing stubs, WASM build, etc.)
are documented in docs/development/release-gates.md.
This project is developed with AI coding assistants (Codex and Claude Code) as implementation tools. The project author is an expert in computer vision, validates algorithmic behaviour and numerical results, and enforces quality gates before release.
Dual-licensed under MIT or Apache-2.0, at your option. See LICENSE
and LICENSE-APACHE.
| ChArUco alignment and IDs. |
calib-targets-puzzleboard | published | Self-identifying PuzzleBoard, and the cylindrical PuzzlePole built on it. |
calib-targets-marker | published | Checkerboard + 3-circle marker boards. |
calib-targets-print | published | Printable target generation (JSON / SVG / PNG). |
calib-targets-py | PyPI | Python bindings (PyO3 / maturin). |
@vitavision/calib-targets | npm / repo-local | WebAssembly bindings. |
calib-targets-ffi | repo-local | C ABI bindings (docs). |