Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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:

FlagDefaultDescription
--pitch_mm <mm>requiredMarker center spacing in mm.
--rows <n>requiredNumber of hex lattice rows.
--long_row_cols <n>requiredNumber of markers in long rows.
--marker_outer_radius_mm <mm>requiredOuter ring radius in mm.
--marker_inner_radius_mm <mm>requiredInner ring radius in mm.
--name <string>autoOptional board name. Omitted uses deterministic geometry-derived naming.
--out_dir <path>tools/out/targetOutput directory for board_spec.json, SVG, and PNG.
--basename <string>target_printBase filename for SVG and PNG outputs.
--dpi <f>300.0PNG raster DPI (also embedded in PNG metadata).
--margin_mm <mm>0.0Extra white border around the board in SVG/PNG outputs.
--no-scale-barfalseOmit 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.json
  • tools/out/target_faststart/target_print.svg
  • tools/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:

FlagDescription
--image <path>Path to the input image file.
--out <path>Path to write detection results (JSON).

Output and diagnostics:

FlagDefaultDescription
--include-proposalsfalseAdd pass-1 proposal diagnostics to the output JSON as top-level proposal_frame, proposal_count, and proposals fields.

Board target:

FlagDefaultDescription
--target <path>built-in boardPath to a board layout JSON file. When omitted, uses the built-in default 203-marker hex board.

Marker scale:

FlagDefaultDescription
--marker-diameter <px>Fixed marker outer diameter in pixels (legacy mode). Overrides min/max range.
--marker-diameter-min <px>unsetMinimum marker outer diameter for scale search.
--marker-diameter-max <px>unsetMaximum 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:

FlagDefaultDescription
--ransac-thresh-px <px>5.0Inlier threshold in pixels.
--ransac-iters <n>2000Maximum iterations.
--no-global-filterfalseDisable the global homography filter entirely.

Homography-guided completion:

FlagDefaultDescription
--no-completefalseDisable completion (fitting at H-projected missing IDs).
--complete-reproj-gate <px>3.0Reprojection error gate for accepting completed markers.
--complete-min-conf <f>0.45Minimum fit confidence in [0, 1] for completed markers.
--complete-roi-radius <px>autoROI radius for edge sampling during completion. Defaults to a value derived from the nominal marker diameter.

Center refinement (projective center):

FlagDefaultDescription
--circle-refine-method <m>projective-centerCenter correction method: none or projective-center.
--proj-center-max-shift-px <px>autoMaximum allowed correction shift. Defaults to a value derived from nominal marker diameter.
--proj-center-max-residual <f>0.25Reject corrections with residual above this.
--proj-center-min-eig-sep <f>1e-6Reject corrections with eigenvalue separation below this.

Self-undistort:

FlagDefaultDescription
--self-undistortfalseEstimate a 1-parameter division-model distortion from detected markers, then re-run detection.
--self-undistort-lambda-min <f>-8e-7Lambda search lower bound.
--self-undistort-lambda-max <f>8e-7Lambda search upper bound.
--self-undistort-min-markers <n>6Minimum 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>.

FlagDefaultDescription
--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.0Radial distortion k1.
--cam-k2 <f>0.0Radial distortion k2.
--cam-p1 <f>0.0Tangential distortion p1.
--cam-p2 <f>0.0Tangential distortion p2.
--cam-k3 <f>0.0Radial 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_adaptive
  • Detector::detect_adaptive_with_hint
  • Detector::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_markers
  • center_frame
  • homography_frame
  • image_size
  • optional homography, ransac, and self_undistort

The CLI may add extra top-level fields:

  • camera when a camera model was supplied
  • proposal_frame, proposal_count, and proposals when --include-proposals is 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