Skip to main content

A high-performance fiducial marker detector for robotics.

Project description

locus-tag

CI License: MIT

Locus detects AprilTag and ArUco markers using a Rust core with zero-copy Python bindings. It implements sub-pixel corner refinement, releases the GIL during detection, and returns results as vectorized NumPy arrays.

[!WARNING] Experimental Status: API is subject to breaking changes. Not recommended for production safety-critical systems.

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

Profiles are selected by name; the three shipped profiles are authored as JSON files and embedded in the wheel.

profile ICRA 2020 Recall Corner RMSE Primary Characteristics
"standard" 96.2% 0.315 px Production default; balanced recall/precision.
"grid" 91.4% 0.458 px 4-connectivity for touching tags (checkerboards).
"high_accuracy" 46.3%* 0.16 px EdLines + GN optimizer; prioritized for metrology.

*high_accuracy is optimized for high-resolution near-field images (Hugging Face Hub datasets).

Comparison (ICRA 2020 Forward - 50 images)

Detector Recall RMSE
Locus (Standard) 96.2% 0.315 px
AprilTag 3 (UMich) 62.3% 0.22 px
OpenCV 33.2% 0.92 px

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, PoseEstimationMode

# 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
    pose_estimation_mode=PoseEstimationMode.Accurate
)

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["decoder"]["decode_mode"] = "Soft"
base["quad"]["upscale_factor"] = 2

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


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.4.0.tar.gz (297.1 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.4.0-cp310-abi3-manylinux_2_28_x86_64.whl (619.5 kB view details)

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

locus_tag-0.4.0-cp310-abi3-manylinux_2_28_aarch64.whl (574.5 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ ARM64

File details

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

File metadata

  • Download URL: locus_tag-0.4.0.tar.gz
  • Upload date:
  • Size: 297.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for locus_tag-0.4.0.tar.gz
Algorithm Hash digest
SHA256 ec9c0fb69b760f722aea382373dc25a83f17b11717e4932e4fa9075e9b73d2a7
MD5 d8b214b33e478dce981250f053a25bc2
BLAKE2b-256 90a645e92ad062dfb0ef22f6c6bcca3e2f583ba28bb70c80344fc470bb42dbc4

See more details on using hashes here.

File details

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

File metadata

  • Download URL: locus_tag-0.4.0-cp310-abi3-manylinux_2_28_x86_64.whl
  • Upload date:
  • Size: 619.5 kB
  • Tags: CPython 3.10+, manylinux: glibc 2.28+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for locus_tag-0.4.0-cp310-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 42f8df7c201fa77892a82d19f474d8c7b6d7599f5183a7b58a70d76c9db78f57
MD5 3ad437b62126a236026a748acef14e9e
BLAKE2b-256 3c19ce87bb2e8a8562af69b85e4b96fac5028b39b5bceb01e8e707b0b9d4c534

See more details on using hashes here.

File details

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

File metadata

  • Download URL: locus_tag-0.4.0-cp310-abi3-manylinux_2_28_aarch64.whl
  • Upload date:
  • Size: 574.5 kB
  • Tags: CPython 3.10+, manylinux: glibc 2.28+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for locus_tag-0.4.0-cp310-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 be29b4267bf13b8c92c76bce9d4ad078fbdfd6d7f88931c26889d594743f83b8
MD5 4b6f80808af6e6fbc56adf16ba646197
BLAKE2b-256 b015aa1e41534baaa4aecbd4211728f0e708dee6720388cfa6806b3d4add3ffe

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page