CLI Guide
The ringgrid command-line tool provides access to the ring marker detection pipeline
from the terminal. It is built from the ringgrid-cli crate.
Installation
Install from the workspace:
cargo install ringgrid-cli
Or build from source:
cargo build --release -p ringgrid-cli
The binary is named ringgrid.
Commands
ringgrid gen-target – Generate canonical target JSON + printable SVG/PNG
This command generates:
board_spec.json<basename>.svg<basename>.png
from direct board geometry arguments.
It is the Rust CLI equivalent of tools/gen_target.py and uses the same practical
geometry/print options. For the same geometry, DPI, margin, and scale-bar setting,
the generated artifacts are equivalent to the Python script and the Rust API writers.
Geometry and output flags:
| Flag | Default | Description |
|---|---|---|
--pitch_mm <mm> | required | Marker center spacing in mm. |
--rows <n> | required | Number of hex lattice rows. |
--long_row_cols <n> | required | Number of markers in long rows. |
--marker_outer_radius_mm <mm> | required | Outer ring radius in mm. |
--marker_inner_radius_mm <mm> | required | Inner ring radius in mm. |
--name <string> | auto | Optional board name. Omitted uses deterministic geometry-derived naming. |
--out_dir <path> | tools/out/target | Output directory for board_spec.json, SVG, and PNG. |
--basename <string> | target_print | Base filename for SVG and PNG outputs. |
--dpi <f> | 300.0 | PNG raster DPI (also embedded in PNG metadata). |
--margin_mm <mm> | 0.0 | Extra white border around the board in SVG/PNG outputs. |
--no-scale-bar | false | Omit the default scale bar from SVG/PNG outputs. |
The Rust CLI accepts the underscore flag names above for parity with tools/gen_target.py.
Hyphenated aliases such as --pitch-mm, --long-row-cols, and --margin-mm
are also accepted.
Example:
ringgrid gen-target \
--out_dir tools/out/target_faststart \
--pitch_mm 8 \
--rows 15 \
--long_row_cols 14 \
--marker_outer_radius_mm 4.8 \
--marker_inner_radius_mm 3.2 \
--name ringgrid_200mm_hex \
--dpi 600 \
--margin_mm 5
Generated files:
tools/out/target_faststart/board_spec.jsontools/out/target_faststart/target_print.svgtools/out/target_faststart/target_print.png
ringgrid detect – Detect markers in an image
This is the primary command. It loads an image, runs the detection pipeline, and writes results as JSON.
Required arguments:
| Flag | Description |
|---|---|
--image <path> | Path to the input image file. |
--out <path> | Path to write detection results (JSON). |
Output and diagnostics:
| Flag | Default | Description |
|---|---|---|
--include-proposals | false | Add pass-1 proposal diagnostics to the output JSON as top-level proposal_frame, proposal_count, and proposals fields. |
Board target:
| Flag | Default | Description |
|---|---|---|
--target <path> | built-in board | Path to a board layout JSON file. When omitted, uses the built-in default 203-marker hex board. |
Marker scale:
| Flag | Default | Description |
|---|---|---|
--marker-diameter <px> | – | Fixed marker outer diameter in pixels (legacy mode). Overrides min/max range. |
--marker-diameter-min <px> | unset | Minimum marker outer diameter for scale search. |
--marker-diameter-max <px> | unset | Maximum marker outer diameter for scale search. |
When --marker-diameter is set, it locks the detector to a single scale instead of
searching a range. This is a legacy compatibility path; prefer the min/max range for
new workflows.
When both min/max are omitted, the detector uses the library default prior
(14-66 px).
If only one bound is provided, the missing side uses the legacy compatibility
fallback (20 for min, 56 for max).
RANSAC homography:
| Flag | Default | Description |
|---|---|---|
--ransac-thresh-px <px> | 5.0 | Inlier threshold in pixels. |
--ransac-iters <n> | 2000 | Maximum iterations. |
--no-global-filter | false | Disable the global homography filter entirely. |
Homography-guided completion:
| Flag | Default | Description |
|---|---|---|
--no-complete | false | Disable completion (fitting at H-projected missing IDs). |
--complete-reproj-gate <px> | 3.0 | Reprojection error gate for accepting completed markers. |
--complete-min-conf <f> | 0.45 | Minimum fit confidence in [0, 1] for completed markers. |
--complete-roi-radius <px> | auto | ROI radius for edge sampling during completion. Defaults to a value derived from the nominal marker diameter. |
Center refinement (projective center):
| Flag | Default | Description |
|---|---|---|
--circle-refine-method <m> | projective-center | Center correction method: none or projective-center. |
--proj-center-max-shift-px <px> | auto | Maximum allowed correction shift. Defaults to a value derived from nominal marker diameter. |
--proj-center-max-residual <f> | 0.25 | Reject corrections with residual above this. |
--proj-center-min-eig-sep <f> | 1e-6 | Reject corrections with eigenvalue separation below this. |
Self-undistort:
| Flag | Default | Description |
|---|---|---|
--self-undistort | false | Estimate a 1-parameter division-model distortion from detected markers, then re-run detection. |
--self-undistort-lambda-min <f> | -8e-7 | Lambda search lower bound. |
--self-undistort-lambda-max <f> | 8e-7 | Lambda search upper bound. |
--self-undistort-min-markers <n> | 6 | Minimum number of markers with inner+outer edge points required for estimation. |
Camera intrinsics:
You can provide an external camera model either inline via --cam-* or from a
JSON file via --calibration <file.json>.
| Flag | Default | Description |
|---|---|---|
--calibration <file.json> | – | Load a Brown-Conrady CameraModel from JSON. Accepts either direct { "intrinsics": ..., "distortion": ... } or wrapped { "camera": { ... } } shapes. |
--cam-fx <f> | – | Focal length x (pixels). |
--cam-fy <f> | – | Focal length y (pixels). |
--cam-cx <f> | – | Principal point x (pixels). |
--cam-cy <f> | – | Principal point y (pixels). |
--cam-k1 <f> | 0.0 | Radial distortion k1. |
--cam-k2 <f> | 0.0 | Radial distortion k2. |
--cam-p1 <f> | 0.0 | Tangential distortion p1. |
--cam-p2 <f> | 0.0 | Tangential distortion p2. |
--cam-k3 <f> | 0.0 | Radial distortion k3. |
For inline parameters, all four intrinsic parameters (fx, fy, cx, cy)
must be provided together. The distortion coefficients are optional and default
to zero.
--calibration and inline --cam-* parameters are mutually exclusive.
Any external camera model and --self-undistort are also mutually exclusive.
Providing both will produce an error.
When a camera model is provided, the detector runs a two-pass pipeline: pass 1 without distortion mapping to find initial markers, then pass 2 with the camera model applied.
Usage Examples
Basic detection with default settings:
ringgrid detect --image photo.png --out result.json
Specifying the expected marker size range:
ringgrid detect \
--image photo.png \
--out result.json \
--marker-diameter-min 20 \
--marker-diameter-max 56
Using a custom board specification:
ringgrid detect \
--target board_spec.json \
--image photo.png \
--out result.json
With camera intrinsics and distortion:
ringgrid detect \
--image photo.png \
--out result.json \
--cam-fx 900 --cam-fy 900 --cam-cx 640 --cam-cy 480 \
--cam-k1 -0.15 --cam-k2 0.05
With a calibration JSON file:
ringgrid detect \
--image photo.png \
--out result.json \
--calibration camera_model.json
With self-undistort estimation:
ringgrid detect \
--image photo.png \
--out result.json \
--self-undistort
Disabling completion and global filter (raw fit-decode output only):
ringgrid detect \
--image photo.png \
--out result.json \
--no-global-filter \
--no-complete
Adaptive Scale Status
Adaptive multi-scale entry points are currently exposed via Rust and Python APIs:
Detector::detect_adaptiveDetector::detect_adaptive_with_hintDetector::detect_multiscale
Python bindings expose the same concepts on ringgrid.Detector:
detect_adaptive(image, nominal_diameter_px=None)(canonical)detect_adaptive_with_hint(image, nominal_diameter_px=...)(compatibility alias)detect_multiscale(image, tiers)
CLI ringgrid detect uses the regular config-driven detect flow.
ringgrid codebook-info – Print codebook statistics
Prints information about the embedded 16-bit codebook profiles. The output shows
the shipped default base profile plus the opt-in extended profile.
ringgrid detect continues to use base unless a config file sets
decode.codebook_profile to extended.
ringgrid codebook-info
Example output:
ringgrid embedded codebook profiles
default profile: base
base:
bits per codeword: 16
number of codewords: 893
min cyclic Hamming: 2
generator seed: 1
first codeword: 0x035D
last codeword: 0x0E63
extended:
bits per codeword: 16
number of codewords: 2180
min cyclic Hamming: 1
generator seed: 1
first codeword: 0x035D
last codeword: 0x2CD3
ringgrid board-info – Print default board specification
Prints summary information about the built-in default board layout: marker count, pitch, rows, columns, and spatial extent.
ringgrid board-info
ringgrid decode-test – Decode a 16-bit word
Tests a hex word against the selected embedded codebook profile and prints the best match with confidence metrics. Useful for debugging code sampling issues.
ringgrid decode-test --word 0x035D
# or:
ringgrid decode-test --word 0x0001 --profile extended
Example output:
Input word: 0x035D (binary: 0000001101011101)
Profile: base
Best match:
id: 0
codeword: 0x035D
rotation: 0 sectors
distance: 0 bits
margin: 2 bits
confidence: 1.000
Logging
ringgrid uses the tracing crate for structured logging. Control verbosity with the
RUST_LOG environment variable:
# Default level (info) -- shows summary statistics
ringgrid detect --image photo.png --out result.json
# Debug level -- shows per-stage diagnostics
RUST_LOG=debug ringgrid detect --image photo.png --out result.json
# Trace level -- shows detailed per-marker information
RUST_LOG=trace ringgrid detect --image photo.png --out result.json
At the default info level, the detector logs:
- Image dimensions
- Board layout loaded (name, marker count)
- Number of detected markers (total and with decoded IDs)
- Homography statistics (inlier count, mean and p95 reprojection error)
- Self-undistort results when enabled (lambda, objective improvement, marker count)
- Output file path
Output Format
ringgrid detect writes the serialized DetectionResult fields at the top
level:
detected_markerscenter_framehomography_frameimage_size- optional
homography,ransac, andself_undistort
The CLI may add extra top-level fields:
camerawhen a camera model was suppliedproposal_frame,proposal_count, andproposalswhen--include-proposalsis enabled
The full file shape, nested marker fields, and frame semantics are documented in Output Format.
Source Files
- CLI implementation:
crates/ringgrid-cli/src/main.rs