Skip to main content

locus-tag

CI Docs License: MIT OR Apache-2.0

Locus detects AprilTag and ArUco markers as well as AprilGrid and ChArUco boards. The library is implemented in Rust and provides zero-copy Python bindings.

[!WARNING] Experimental Status: API is subject to breaking changes until 1.0.0 ships. The main workstreams towards 1.0.0 are reducing the API surface and validating against non-synthetic data. Until then, this library isn't recommended for production systems. The support for distortion models is experimental and requires a ground-up redesign. Addition of default tag families may happen on request, the current defaults were chosen to be minimal and support most commonly used tags.

Technical Capabilities

  • Zero-Copy Ingestion: Accesses NumPy arrays via the Python Buffer Protocol.
  • Parallel Execution: Releases the Python GIL during detection to allow multi-threaded use.
  • Vectorized Results: Returns a DetectionBatch with parallel arrays for IDs, corners, and poses.
  • Memory: Uses bumpalo arena allocation for zero heap allocations in the detection loop.
  • Solvers: 6-DOF recovery using IPPE-Square or weighted Levenberg-Marquardt with corner uncertainty.

Performance Profiles

Locus optimises for high recall, low corner RMSE, and low latency. Profiles are selected by name; the three shipped profiles are authored as JSON files and embedded in the wheel.

profile Primary characteristic
"standard" Production default; balanced recall + precision.
"grid" 4-connectivity for touching tags — ChArUco / AprilGrid boards.
"high_accuracy" EdLines + axis-imbalance gate + adaptive PPB; prioritises pose precision and tail-rotation control.

ICRA 2020 Forward (community benchmark)

ICRA 2020 Forward is the closest thing the AprilTag community has to a neutral benchmark. The 50-frame subset we report on is synthetic (not real-camera), but it's public, peer-reviewed, and the basis for prior detector comparisons — we report on it for continuity with the literature.

Detector Recall Corner RMSE
Locus (standard) 96.2 % 0.315 px
AprilTag 3 (UMich) 62.3 % 0.22 px
OpenCV (cv2.aruco) 52.6 % 0.98 px

The OpenCV row is its recall-best OpenCV 5.0 config (tuned subpix); the tag-aware apriltag refinement more than halves corner RMSE (0.39 px) but rejects ICRA's marginal small tags, dropping recall to ~30 %.

render-tag (high-fidelity Blender + PSF)

render-tag is our in-house render suite — Blender with calibrated PSF, exposure, sensor noise, and lens distortion models. The detection scenes carry pixel-accurate ground truth for both corners and 6-DOF pose, which lets us report translation / rotation percentiles in addition to recall. Numbers below are the 2026-07-13 single-threaded SOTA snapshot on the 1080p 50-scene subset (OpenCV 5.0.0, re-tuned) (see docs/engineering/benchmarking/render_tag_sota_20260713.md for methodology, the 2160p table, and OpenCV's two operating points).

Detector Recall Trans p50 Trans p99 Rot p50 Rot p99 Latency
Locus (high_accuracy) 100 % 0.4 mm 18.6 mm 0.057 ° 0.600 ° 13.8 ms
Locus (standard) 100 % 3.5 mm 50.3 mm 0.288 ° 27.248 ° 32.7 ms
OpenCV (cv2.aruco, subpix) 100 % 3.5 mm 66.6 mm 0.127 ° 0.569 ° 101.1 ms
OpenCV (cv2.aruco, apriltag) 100 % 3.0 mm 55.3 mm 0.067 ° 0.376 ° 195.8 ms
AprilTag-C (pupil) 100 % 2.9 mm 54.4 mm 0.061 ° 65.365 ° 78.5 ms

Latencies are single-thread. Locus high_accuracy wins the translation tail and is 14× faster than OpenCV's best-accuracy apriltag config; that config in turn has the best rotation tail among the default profiles (0.376°). OpenCV ships two operating points — fast subpix and accurate-but-~2×-slower apriltag. AprilTag-C's median rotation is best in class (0.06°) but its p99 explodes to 65° on symmetric-tag IRLS branch-ambiguity failures.

Optional: model-edge pose refinement. Setting pose.pose_edge_refinement_enabled = True adds an Accurate-mode stage that refines each decoded tag's pose against its ~40 internal bit-grid edges (rotation from the distributed edges; translation re-anchored to the corners). It takes high_accuracy rotation p99 to 0.249° (p95 0.180°) — below OpenCV apriltag's 0.376° — at ~2.7× better translation and +~1 ms/frame, with 2D corner RMSE unchanged and reprojection RMSE improved. Off by default (shipped detection stays byte-identical); requires camera intrinsics + tag_size. See docs/…/model_edge_refinement_20260715.md.

Installation

pip install locus-tag

The PyPI wheel is compiled for rectified (pinhole) imagery. For unrectified cameras (Brown-Conrady polynomial, Kannala-Brandt equidistant fisheye), see Install with distortion support.

Quick Start

Basic Detection

import cv2
import locus

img = cv2.imread("tags.jpg", cv2.IMREAD_GRAYSCALE)
detector = locus.Detector(families=[locus.TagFamily.AprilTag36h11])

# batch contains parallel NumPy arrays
batch = detector.detect(img)
print(f"IDs: {batch.ids}")
print(f"Corners: {batch.corners.shape}") # (N, 4, 2)

6-DOF Pose Estimation

from locus import Detector, CameraIntrinsics

# fx, fy, cx, cy
intrinsics = CameraIntrinsics(fx=800.0, fy=800.0, cx=640.0, cy=360.0)

# Returns [tx, ty, tz, qx, qy, qz, qw] for each tag
batch = detector.detect(
    img,
    intrinsics=intrinsics,
    tag_size=0.10,  # physical side length in meters
)

if batch.poses is not None:
    # First tag translation
    print(batch.poses[0, :3])

Configuration Overrides

Settings are nested and validated by Pydantic. Start from a shipped profile, edit the group you care about, and hand it back to the detector:

base = locus.DetectorConfig.from_profile("high_accuracy").model_dump()
base["quad"]["upscale_factor"] = 2
base["decoder"]["max_hamming_error"] = 1

detector = locus.Detector(config=locus.DetectorConfig.model_validate(base))

Visual Debugging

Built-in integration with the Rerun SDK:

batch = detector.detect(img, debug_telemetry=True)
if batch.telemetry:
    print(batch.telemetry.subpixel_jitter)

Documentation

License

Dual-licensed under Apache 2.0 or MIT.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

locus_tag-0.7.0.tar.gz (392.0 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

locus_tag-0.7.0-cp310-abi3-win_amd64.whl (589.6 kB view details)

Uploaded CPython 3.10+Windows x86-64

locus_tag-0.7.0-cp310-abi3-musllinux_1_2_x86_64.whl (917.7 kB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ x86-64

locus_tag-0.7.0-cp310-abi3-musllinux_1_2_aarch64.whl (822.5 kB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ ARM64

locus_tag-0.7.0-cp310-abi3-manylinux_2_28_x86_64.whl (702.4 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ x86-64

locus_tag-0.7.0-cp310-abi3-manylinux_2_28_aarch64.whl (645.1 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ ARM64

locus_tag-0.7.0-cp310-abi3-macosx_11_0_arm64.whl (641.7 kB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

locus_tag-0.7.0-cp310-abi3-macosx_10_12_x86_64.whl (665.4 kB view details)

Uploaded CPython 3.10+macOS 10.12+ x86-64

File details

Details for the file locus_tag-0.7.0.tar.gz.

File metadata

  • Download URL: locus_tag-0.7.0.tar.gz
  • Upload date:
  • Size: 392.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for locus_tag-0.7.0.tar.gz
Algorithm Hash digest
SHA256 d58251e3a99ec630384eaf699d15597ca069cf6beb6e383ef2229a57e8a4d82c
MD5 dbb70919e79e0930d5ec3c086fc42cf7
BLAKE2b-256 4d4cb8e76c1801ba8cb1e84535fc6669353f130cbf442e639cb43e5e47784f35

See more details on using hashes here.

Provenance

The following attestation bundles were made for locus_tag-0.7.0.tar.gz:

Publisher: release.yml on NoeFontana/locus-tag

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file locus_tag-0.7.0-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: locus_tag-0.7.0-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 589.6 kB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for locus_tag-0.7.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 f737356092e09f2153e3c44a4231d63c619e42f27c11e4a282d451f44f38452a
MD5 4ad4a178e7660eb28a9e94ce17f9e0cc
BLAKE2b-256 19e51c94a9860d2282b234314f08a4ee1f1444429133be7fbbbe83281159a1cc

See more details on using hashes here.

Provenance

The following attestation bundles were made for locus_tag-0.7.0-cp310-abi3-win_amd64.whl:

Publisher: release.yml on NoeFontana/locus-tag

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file locus_tag-0.7.0-cp310-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for locus_tag-0.7.0-cp310-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 7c1798fd5c05fe2f4746a6ed6b86e5cad687c6d4348d791178f4ffd7ca6cc89f
MD5 9ec430c071b594240e5a24bde9ca83bc
BLAKE2b-256 98851b49ef5ff01999d3b87a2791b69a395a4c075290ee0e986869096d5775cc

See more details on using hashes here.

Provenance

The following attestation bundles were made for locus_tag-0.7.0-cp310-abi3-musllinux_1_2_x86_64.whl:

Publisher: release.yml on NoeFontana/locus-tag

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file locus_tag-0.7.0-cp310-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for locus_tag-0.7.0-cp310-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 4e247a3eaed712d59d783fd5dd44f96712bd8223a41cebd633ac7a13628731ef
MD5 1d5c25407a3baef825cdb73d80ebe31e
BLAKE2b-256 9655b6e8bc058387171224ab3eca2478abe1a2a3f7def58556f2a3a7a1812dc1

See more details on using hashes here.

Provenance

The following attestation bundles were made for locus_tag-0.7.0-cp310-abi3-musllinux_1_2_aarch64.whl:

Publisher: release.yml on NoeFontana/locus-tag

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file locus_tag-0.7.0-cp310-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for locus_tag-0.7.0-cp310-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 8e5d18f7bbb77648f1154fef5819cd772f1fde403dd3bd5582b22f992772acc1
MD5 9b29d643deb6ad07b5e1aca1ea3114df
BLAKE2b-256 50c7dff7cb960b6a9ec936bcd100d59ee76f9c5e3904e9ae250c116424f1d0fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for locus_tag-0.7.0-cp310-abi3-manylinux_2_28_x86_64.whl:

Publisher: release.yml on NoeFontana/locus-tag

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file locus_tag-0.7.0-cp310-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for locus_tag-0.7.0-cp310-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 33aaad7e7b864fdb137e1c523e4af4a7de2307c9b97a1cb5914203b5a8420ebd
MD5 9e23fb956056b762ba1a92c54d12ab56
BLAKE2b-256 16aa26d7a9668ababc44cd8d7a4c3dd6a2fde24e11e7ce4af197e8b7805665fb

See more details on using hashes here.

Provenance

The following attestation bundles were made for locus_tag-0.7.0-cp310-abi3-manylinux_2_28_aarch64.whl:

Publisher: release.yml on NoeFontana/locus-tag

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file locus_tag-0.7.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for locus_tag-0.7.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4734468b8128076a65395fc263c829be427a8f11863fdee43d6a50e9ecb90eee
MD5 796cc78fe0cef9f19442283e39caf456
BLAKE2b-256 9e8f812ec9a0d21e6e207fc89a59b066818f929787374d9107f6ed5e0f4bb7db

See more details on using hashes here.

Provenance

The following attestation bundles were made for locus_tag-0.7.0-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on NoeFontana/locus-tag

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file locus_tag-0.7.0-cp310-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for locus_tag-0.7.0-cp310-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 55a98343be3ae4c19ad0214c7fe946500340a8d44e499c0cf74704b8193ed1ac
MD5 0cf881f092069b7ae0c208c6652ea0f1
BLAKE2b-256 8b1750691c6d6d94bf4f85545fdc10dd99d94f71de29d2c0b7db8beda28f98c7

See more details on using hashes here.

Provenance

The following attestation bundles were made for locus_tag-0.7.0-cp310-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on NoeFontana/locus-tag

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.7.1

8 files

This release

0.7.0 This release

8 files

0.6.0

8 files

0.4.0

3 files

0.3.1

3 files

0.3.0

3 files

0.2.6

3 files

0.2.5

3 files

0.2.4

3 files

0.2.3

3 files

0.2.2

3 files

0.2.1

2 files

0.2.0

2 files

0.1.3

5 files

0.1.2

1 file

0.1.1

1 file

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