A high-performance fiducial marker detector for robotics.
Project description
locus-tag
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
DetectionBatchwith parallel arrays for IDs, corners, and poses. - Memory: Uses
bumpaloarena 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) |
33.2 % | 0.92 px |
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 from the
2026-04-25 SOTA snapshot on the 1080p 50-scene subset (see
docs/engineering/benchmarking/render_tag_sota_20260425.md
for methodology).
| Detector | Recall | Trans p50 | Trans p99 | Rot p50 | Rot p99 | Latency |
|---|---|---|---|---|---|---|
Locus (high_accuracy) |
100 % | 0.4 mm | 25.6 mm | 0.058 ° | 1.897 ° | 11.67 ms |
Locus (standard) |
100 % | 3.5 mm | 50.3 mm | 0.288 ° | 27.248 ° | 19.24 ms |
| AprilTag-C (pupil) | 100 % | 2.9 mm | 54.4 mm | 0.061 ° | 65.365 ° | 25.54 ms |
OpenCV (cv2.aruco) |
100 % | 3.4 mm | 141.4 mm | 0.113 ° | 1.228 ° | 44.45 ms |
Per-percentile is load-bearing: AprilTag-C's median rotation is the best in class (0.06 °) but its p99 explodes to 65 ° on the symmetric-tag IRLS branch-ambiguity failures.
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file locus_tag-0.6.0.tar.gz.
File metadata
- Download URL: locus_tag-0.6.0.tar.gz
- Upload date:
- Size: 371.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3e7d7b659a921b61d1b463e0906400cd33ba4349764b6221e3eab3b87daa896b
|
|
| MD5 |
0613b93e4178753ecebd530060bb278a
|
|
| BLAKE2b-256 |
67376239fe3b3ddf577d9b35a2ae2a7c449a62ea08af8f9d1a2028d1cc860f4f
|
Provenance
The following attestation bundles were made for locus_tag-0.6.0.tar.gz:
Publisher:
release.yml on NoeFontana/locus-tag
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
locus_tag-0.6.0.tar.gz -
Subject digest:
3e7d7b659a921b61d1b463e0906400cd33ba4349764b6221e3eab3b87daa896b - Sigstore transparency entry: 1819746777
- Sigstore integration time:
-
Permalink:
NoeFontana/locus-tag@ad89561b14e28de4b63907764e584489669355f5 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/NoeFontana
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ad89561b14e28de4b63907764e584489669355f5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file locus_tag-0.6.0-cp310-abi3-win_amd64.whl.
File metadata
- Download URL: locus_tag-0.6.0-cp310-abi3-win_amd64.whl
- Upload date:
- Size: 535.3 kB
- Tags: CPython 3.10+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b69304b4d8e0ccf77547d39edfe318eb1763d931f7077bc13f6923a5ccb6803d
|
|
| MD5 |
987d448da22f1002d0204afdc2355c09
|
|
| BLAKE2b-256 |
f50e1839971f7fb03567f81338bc6a50df9b5acbed78f2af3db59ea5e9943783
|
Provenance
The following attestation bundles were made for locus_tag-0.6.0-cp310-abi3-win_amd64.whl:
Publisher:
release.yml on NoeFontana/locus-tag
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
locus_tag-0.6.0-cp310-abi3-win_amd64.whl -
Subject digest:
b69304b4d8e0ccf77547d39edfe318eb1763d931f7077bc13f6923a5ccb6803d - Sigstore transparency entry: 1819746882
- Sigstore integration time:
-
Permalink:
NoeFontana/locus-tag@ad89561b14e28de4b63907764e584489669355f5 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/NoeFontana
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ad89561b14e28de4b63907764e584489669355f5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file locus_tag-0.6.0-cp310-abi3-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: locus_tag-0.6.0-cp310-abi3-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 863.0 kB
- Tags: CPython 3.10+, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e56496b8c7282f89703c68c2d9d98f5d6470cf6aa11e50d1ba3409827fbdeeb3
|
|
| MD5 |
f1d13cbd35fe1bb5a69b4066fc034af2
|
|
| BLAKE2b-256 |
f45b4b01fdd41b2556e2de1bcc906dca7103963e63646a9a0e7c252c74aa52ea
|
Provenance
The following attestation bundles were made for locus_tag-0.6.0-cp310-abi3-musllinux_1_2_x86_64.whl:
Publisher:
release.yml on NoeFontana/locus-tag
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
locus_tag-0.6.0-cp310-abi3-musllinux_1_2_x86_64.whl -
Subject digest:
e56496b8c7282f89703c68c2d9d98f5d6470cf6aa11e50d1ba3409827fbdeeb3 - Sigstore transparency entry: 1819747138
- Sigstore integration time:
-
Permalink:
NoeFontana/locus-tag@ad89561b14e28de4b63907764e584489669355f5 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/NoeFontana
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ad89561b14e28de4b63907764e584489669355f5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file locus_tag-0.6.0-cp310-abi3-musllinux_1_2_aarch64.whl.
File metadata
- Download URL: locus_tag-0.6.0-cp310-abi3-musllinux_1_2_aarch64.whl
- Upload date:
- Size: 775.9 kB
- Tags: CPython 3.10+, musllinux: musl 1.2+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc5dd6627736aeaf8e24487944a44993b96ba725290126e63c0acb53d56f78a0
|
|
| MD5 |
9c2eaad454adff866a42f300b2105f1a
|
|
| BLAKE2b-256 |
87495590cda876205a48a40fa7394c6ccd15ec2b7265f8928570b4192950f7ad
|
Provenance
The following attestation bundles were made for locus_tag-0.6.0-cp310-abi3-musllinux_1_2_aarch64.whl:
Publisher:
release.yml on NoeFontana/locus-tag
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
locus_tag-0.6.0-cp310-abi3-musllinux_1_2_aarch64.whl -
Subject digest:
bc5dd6627736aeaf8e24487944a44993b96ba725290126e63c0acb53d56f78a0 - Sigstore transparency entry: 1819746981
- Sigstore integration time:
-
Permalink:
NoeFontana/locus-tag@ad89561b14e28de4b63907764e584489669355f5 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/NoeFontana
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ad89561b14e28de4b63907764e584489669355f5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file locus_tag-0.6.0-cp310-abi3-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: locus_tag-0.6.0-cp310-abi3-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 647.4 kB
- Tags: CPython 3.10+, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1e1bb09f67b8dd6a4c6754b653ecf51a3a05c4b802e285e0a206b5f8641601f7
|
|
| MD5 |
590611a24c629f444eee295a16c3332a
|
|
| BLAKE2b-256 |
eac7d19f7d2d6bc871ea2435538a00a8ec3bebd81b4726da3f2e8a91fa35ba02
|
Provenance
The following attestation bundles were made for locus_tag-0.6.0-cp310-abi3-manylinux_2_28_x86_64.whl:
Publisher:
release.yml on NoeFontana/locus-tag
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
locus_tag-0.6.0-cp310-abi3-manylinux_2_28_x86_64.whl -
Subject digest:
1e1bb09f67b8dd6a4c6754b653ecf51a3a05c4b802e285e0a206b5f8641601f7 - Sigstore transparency entry: 1819747207
- Sigstore integration time:
-
Permalink:
NoeFontana/locus-tag@ad89561b14e28de4b63907764e584489669355f5 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/NoeFontana
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ad89561b14e28de4b63907764e584489669355f5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file locus_tag-0.6.0-cp310-abi3-manylinux_2_28_aarch64.whl.
File metadata
- Download URL: locus_tag-0.6.0-cp310-abi3-manylinux_2_28_aarch64.whl
- Upload date:
- Size: 597.8 kB
- Tags: CPython 3.10+, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
414d51c16c790fec019cdbcd12aa27bbac51d62bac298e148e0b679725e12466
|
|
| MD5 |
543add037bf89ae5fd1e0cffb2d99d18
|
|
| BLAKE2b-256 |
55369d1aa1b987c1a74d9e73454499d08319388442a3b0f11b41002042d92281
|
Provenance
The following attestation bundles were made for locus_tag-0.6.0-cp310-abi3-manylinux_2_28_aarch64.whl:
Publisher:
release.yml on NoeFontana/locus-tag
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
locus_tag-0.6.0-cp310-abi3-manylinux_2_28_aarch64.whl -
Subject digest:
414d51c16c790fec019cdbcd12aa27bbac51d62bac298e148e0b679725e12466 - Sigstore transparency entry: 1819747311
- Sigstore integration time:
-
Permalink:
NoeFontana/locus-tag@ad89561b14e28de4b63907764e584489669355f5 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/NoeFontana
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ad89561b14e28de4b63907764e584489669355f5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file locus_tag-0.6.0-cp310-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: locus_tag-0.6.0-cp310-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 592.6 kB
- Tags: CPython 3.10+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
123f6a78bddfaf4dd315e3282b757b5b64fcf0945de614e195f4ce3d50257c9c
|
|
| MD5 |
25d44a7717d055a08c4a84af421258b5
|
|
| BLAKE2b-256 |
205cb266b9df3dd7a533002db0fdfc6166041032a2c2628da48fdb33b395dc57
|
Provenance
The following attestation bundles were made for locus_tag-0.6.0-cp310-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on NoeFontana/locus-tag
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
locus_tag-0.6.0-cp310-abi3-macosx_11_0_arm64.whl -
Subject digest:
123f6a78bddfaf4dd315e3282b757b5b64fcf0945de614e195f4ce3d50257c9c - Sigstore transparency entry: 1819747061
- Sigstore integration time:
-
Permalink:
NoeFontana/locus-tag@ad89561b14e28de4b63907764e584489669355f5 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/NoeFontana
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ad89561b14e28de4b63907764e584489669355f5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file locus_tag-0.6.0-cp310-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: locus_tag-0.6.0-cp310-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 610.1 kB
- Tags: CPython 3.10+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9bfc6e57f367c9ed7fd7dec6168a80d528517d0ddf29923f187b34fa8213875d
|
|
| MD5 |
a1d78b32344b1aaff8fc693e41459c6d
|
|
| BLAKE2b-256 |
f21fac023443e9434b19f0fb5d139c41d6d38339e044e3eb2b4957d008cbcac4
|
Provenance
The following attestation bundles were made for locus_tag-0.6.0-cp310-abi3-macosx_10_12_x86_64.whl:
Publisher:
release.yml on NoeFontana/locus-tag
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
locus_tag-0.6.0-cp310-abi3-macosx_10_12_x86_64.whl -
Subject digest:
9bfc6e57f367c9ed7fd7dec6168a80d528517d0ddf29923f187b34fa8213875d - Sigstore transparency entry: 1819747396
- Sigstore integration time:
-
Permalink:
NoeFontana/locus-tag@ad89561b14e28de4b63907764e584489669355f5 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/NoeFontana
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ad89561b14e28de4b63907764e584489669355f5 -
Trigger Event:
push
-
Statement type: