Skip to main content

calib-targets — Python bindings

Book

Native-feeling Python API for the calib-targets Rust workspace. Detects chessboards, ChArUco, PuzzleBoard, and marker boards, and generates printable target bundles (JSON + SVG + PNG + DXF). Built with PyO3 + maturin.

Python package name: calib_targets (the Rust crate is calib-targets-py).

Install

# From source — this repo:
uv pip install maturin
uv run maturin develop --release -m crates/calib-targets-py/Cargo.toml

# Or from PyPI (pre-built wheels):
pip install calib-targets

Hello world

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)
result = ct.detect_chessboard_best(image, [ct.ChessboardParams()])
if result is not None:
    print(f"labelled {len(result.corners)} corners")

End-to-end round-trip per target type

Each snippet covers: generate a printable target → load the PNG → detect → export detection to JSON.

Runnable scripts at crates/calib-targets-py/examples/. Use any of them as a starting point.

Chessboard

import io, json
import numpy as np
from PIL import Image
import calib_targets as ct

# 1. Generate target.
doc = ct.PrintableTargetDocument(
    target=ct.ChessboardTargetSpec(inner_rows=7, inner_cols=9, square_size_mm=20.0),
    page=ct.PageSpec(size=ct.PageSize.custom(width_mm=220.0, height_mm=180.0), margin_mm=10.0),
    render=ct.RenderOptions(png_dpi=150),
)
bundle = ct.render_target_bundle(doc)

# 2. Load as grayscale numpy array.
image = np.asarray(Image.open(io.BytesIO(bundle.png_bytes)).convert("L"), dtype=np.uint8)

# 3. Detect — prefer *_best for robustness.
chess_cfg = ct.ChessConfig(threshold=15.0)
configs = [
    ct.ChessboardParams(),
    ct.ChessboardParams(min_labeled_corners=12),
    ct.ChessboardParams(max_components=1),
]
result = ct.detect_chessboard_best(image, configs, chess_cfg=chess_cfg)

# 4. Export detection to JSON.
print(json.dumps(result.to_dict(), indent=2)[:200])

Runnable: examples/chessboard_roundtrip.py.

ChArUco

import calib_targets as ct
# (synthesise PNG as above; build matching board spec)
board = ct.CharucoBoardSpec(
    rows=5, cols=7, cell_size=1.0, marker_size_rel=0.75,
    dictionary="DICT_4X4_50", marker_layout=ct.MarkerLayout.OPENCV_CHARUCO,
)
params = ct.CharucoParams(
    board=board, px_per_square=60.0,
    chessboard=ct.ChessboardParams(),
    min_marker_inliers=4,
)
result = ct.detect_charuco(image, params=params)   # raises on failure
print(len(result.corners), "corners,", len(result.markers), "markers")

Runnable: examples/charuco_roundtrip.py.

Marker board

circles = (
    ct.MarkerCircleSpec(i=3, j=2, polarity=ct.CirclePolarity.WHITE),
    ct.MarkerCircleSpec(i=4, j=2, polarity=ct.CirclePolarity.BLACK),
    ct.MarkerCircleSpec(i=4, j=3, polarity=ct.CirclePolarity.WHITE),
)
board = ct.MarkerBoardSpec(rows=6, cols=8, cell_size=1.0, circles=circles)
params = ct.MarkerBoardParams(board=board, chessboard=ct.ChessboardParams())
result = ct.detect_marker_board(image, params=params)

MarkerBoardSpec is also exported under its previous name MarkerBoardLayout (a backward-compatible alias that stays live this release).

Runnable: examples/markerboard_roundtrip.py.

PuzzleBoard

params = ct.default_puzzleboard_params(rows=10, cols=10)
params.decode.search_mode = ct.PuzzleBoardSearchMode.fixed_board()
params.decode.scoring_mode = ct.PuzzleBoardScoringMode.soft_log_likelihood()
params.decode.symmetry_mode = ct.PuzzleBoardSymmetryMode.rotations()  # default
result = ct.detect_puzzleboard(image, params=params)
# Every corner has an absolute master ID: result.corners[0].id
# Soft-mode scoring evidence is available from diagnose_puzzleboard().

Runnable: examples/puzzleboard_roundtrip.py.

Inputs

  • image: numpy.ndarray[uint8] with shape (h, w). Grayscale only; convert RGB upstream (Image.convert("L")).
  • chess_cfg: ChessConfig | None — overrides the default ChESS corner detector.
  • params: *Params — typed dataclass matching the detector. Dict inputs are rejected; use the typed classes.

Outputs

Every detection result is a typed dataclass with full attribute access, editor autocomplete, and type stubs. Round-trip through JSON with to_dict() and from_dict(...) — the dict schema matches the Rust crate's serde_json output byte-for-byte.

payload = json.dumps(result.to_dict())
# ... later, elsewhere:
restored = ct.ChessboardDetectionResult.from_dict(json.loads(payload))

Every config / result type has these methods — ChessConfig, ChessboardParams, CharucoParams, PuzzleBoardParams, MarkerBoardParams, PrintableTargetDocument, and all result types.

Printable targets

One-liner helpers with sensible defaults (A4 portrait, 10 mm margins, 300 DPI):

doc = ct.charuco_document(rows=5, cols=7, square_size_mm=20.0,
                          marker_size_rel=0.75, dictionary="DICT_4X4_50")
written = ct.write_target_bundle(doc, "out/charuco_a4")
print(written.json_path, written.svg_path, written.png_path, written.dxf_path)

Other helpers: chessboard_document, puzzleboard_document, marker_board_document. Each accepts optional page= / render= overrides. For full control, construct PrintableTargetDocument directly with one of the target specs (ChessboardTargetSpec, CharucoTargetSpec, MarkerBoardTargetSpec, PuzzleBoardTargetSpec).

CLI

pip install calib-targets installs a calib-targets console script that mirrors the Rust CLI:

calib-targets gen puzzleboard --rows 8 --cols 10 --square-size-mm 15 \
    --out-stem puzzle
calib-targets list-dictionaries
calib-targets init chessboard --out spec.json \
    --inner-rows 6 --inner-cols 8 --square-size-mm 20
calib-targets generate --spec spec.json --out-stem my_board

See testdata/printable/*.json for ready-made spec files; every file is PrintableTargetDocument.from_dict( json.load(open(path)))-compatible.

Tuning difficult cases

  1. Replace detect_* with detect_*_best and pass the matching sweep preset — ChessboardParams.sweep_default(), CharucoParams.sweep_for_board(board), MarkerBoardParams.sweep_for_board(board) or PuzzleBoardParams.sweep_for_board(board). Each preset is computed by Rust and handed to Python, so both language surfaces search the same configuration space. This is the recommended default.
  2. Increase rasterisation / input resolution if cells are smaller than ~20 px across.
  3. Open the per-detector README for deeper guidance: chessboard, ChArUco, PuzzleBoard, marker. Python passes all parameters through to Rust, so tuning advice applies identically.

Limitations

  • One target instance per image. Multiple simultaneous boards are not detected; pass cropped sub-images per target.
  • Pinhole-ish optics only. Moderate radial / perspective distortion is handled gracefully; fisheye is not supported.
  • Grayscale uint8 numpy arrays only. No torch tensors, no GPU.
  • Board PNG / SVG generation for chessboard, ChArUco, marker board, and PuzzleBoard is supported; other target kinds are not.

Migration from pre-0.7 dict-based API

Old New
detect_chessboard(img, params={"min_corner_strength": 0.5}) detect_chessboard(img, params=ChessboardParams(min_corner_strength=0.5))
detect_charuco(..., params={"board": {...}}) detect_charuco(..., params=CharucoParams(board=CharucoBoardSpec(...)))
result["corners"] result.corners
json.dumps(result_dict) json.dumps(result.to_dict())

Dict-based configuration is rejected in the new API; use the typed dataclasses.

ChessboardParams keeps the per-stage tuning knobs flat for ergonomics, but to_dict() now nests everything except the four stable fields (graph_build_algorithm, min_labeled_corners, max_components, min_corner_strength) under an "advanced" block — matching the Rust wire format. These advanced knobs are not covered by semver. The unused projective_line_tol_rel knob was removed (it was a no-op); drop it from any ChessboardParams(...) call that set it.

Feature parity vs Rust facade

  • detect_chessboard / _all / _best / _debug — ✔
  • detect_charuco / _with_corners / _best, detect_puzzleboard / _with_corners / _best, detect_marker_board / _with_corners / _best — ✔
  • diagnose_charuco / _with_corners, diagnose_puzzleboard / _with_corners, diagnose_marker_board / _with_corners — ✔
  • Printable targets for all four target kinds — ✔
  • to_dict / from_dict round-trip on every config + result type — ✔

Reusing a corner cloud across detectors

Each of ChArUco, PuzzleBoard, and marker board runs its own ChESS corner pass from params.chess inside detect_*. The _with_corners variant skips that pass and takes a corner cloud directly — useful when several detectors should share one pass, or the corners come from a custom upstream:

corners = ct.trace_chessboard_topological(image, params=None)["corners"]
result = ct.detect_charuco_with_corners(image, corners, params=params)

corners is a list of ChessCorner-shaped dicts: {"position": [x, y], "axes": [...], "strength": ...}.

Implementation note

The compiled Rust module is internal (calib_targets._core). Public API stability is guaranteed only for top-level calib_targets exports.

Metadata

Release files for calib-targets 0.14.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for calib-targets 0.14.0
File Size Uploaded
calib_targets-0.14.0.tar.gz 799.5 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for calib-targets 0.14.0
File Interpreter ABI Platform
calib_targets-0.14.0-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
calib_targets-0.14.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details
calib_targets-0.14.0-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details

Total release size: 5.0 MB

Release files / calib_targets-0.14.0.tar.gz

Download URL calib_targets-0.14.0.tar.gz
Size 799.5 kB
Tags Source
SHA-256 checksum
How to use checksums
82fd9f9a0086ae0be889a404d43a36d7d023a30a998803657aa9408b97968d14
BLAKE2b-256 checksum
How to use checksums
17d98fbab9e0eb8b55d46ad3a57a3f3ebf354425a8c9219dfc8b70cdf0a76c3e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.

Transparency log

Release files / calib_targets-0.14.0-cp310-abi3-win_amd64.whl

Download URL calib_targets-0.14.0-cp310-abi3-win_amd64.whl
Size 1.3 MB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
a85d749b2b3bec176473a7739c21d6d1a98ef2dacf4c836e5d0c1f3512c03550
BLAKE2b-256 checksum
How to use checksums
f5738980036c401e9c85944edcef01031744dde69caafdcffc8b73bdb0dd350b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.

Transparency log

Release files / calib_targets-0.14.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL calib_targets-0.14.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 1.6 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
29337f7daddf4c469623d0c3dba7a8c5d5876a60a90a33ec92724d95071d3576
BLAKE2b-256 checksum
How to use checksums
fd3fd51b5af18fda1e97df3c687923777a95cef3a5ff01034389d3e530d1bc79
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.

Transparency log

Release files / calib_targets-0.14.0-cp310-abi3-macosx_11_0_arm64.whl

Download URL calib_targets-0.14.0-cp310-abi3-macosx_11_0_arm64.whl
Size 1.4 MB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
07eded64d828d16b475ef2d12a02f6a10582b39d8ccbb05da5a63a439d94c813
BLAKE2b-256 checksum
How to use checksums
5ead4de564b1b1719d0212c76cbf32f3b282ecadf459dad7a79dfa91aaf94085
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.

Transparency log

Release history Release notifications | RSS feed

0.15.3

4 release files

0.15.2

4 release files

0.15.1

4 release files

This release

0.14.0 This release

4 release files

0.13.0

4 release files

0.12.1

4 release files

0.12.0

4 release files

0.11.2

4 release files

0.11.1

4 release files

0.11.0

4 release files

0.9.0

4 release files

0.8.0

4 release files

0.7.3

4 release files

0.7.2

4 release files

0.7.1

4 release files

0.7.0

4 release files

0.6.0

4 release files

0.5.3

4 release files

0.5.2

4 release files

0.5.1

4 release files

0.5.0

4 release files

0.4.2

4 release files

0.4.0

4 release files

0.3.2

4 release files

0.3.1

4 release files

0.2.5

4 release files

0.2.4

4 release files

0.2.3

4 release files

0.2.2

4 release files

0.2.1

3 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page