Quick Reference

This page provides a comprehensive overview of the main entry points and all their parameters.

Entry Points

BlobBoards has two main entry points:

FunctionPurposeOutput
blob_patternGenerate blob patterns for training/simulation(pattern, blobs, config)
blob_boardGenerate printable calibration boardsBoardBundle

blob_pattern - Pattern Generation

Generate multi-scale blob patterns in pixel/logical units.

Signatures

# From dimensionsblob_pattern(width, height; kwargs...)blob_pattern(Size2(width=W, height=H); kwargs...)# With explicit pixel typeblob_pattern(Gray{N0f8}, Size2(width=W, height=H); kwargs...)# From config objectblob_pattern(config::PatternConfig; dir=nothing)

All Keyword Arguments

ParameterTypeDefaultDescription
blob_sizesTuple(8px, nothing)(min, max) disc diameters (2·cutoff·σ) in logical units (px; a bare number is px). max = nothing → largest disc = 20% of the short side; 0.2short_side → a fraction of the short side. Default min = 2·cutoff·2px, also the floor
seedIntegerrandomRandom seed for reproducibility (UInt64)
scales_per_octaveInt3Number of scales per doubling of size
αFloat641.2Scale sampling bias (higher = more small blobs)
cutoffFloat642.0Gaussian truncation radius in σ — use the default 2
max_trialsInt5000Max placement attempts per blob
raster_alignedBooltrueSnap blob centers to pixel centers
polaritySymbol:darkBlob polarity (:dark or :light)
dirStringnothingOutput directory (saves PNG + JSON if provided)

Stored Configuration (PatternConfig)

The returned PatternConfig (and the pattern_config block of a v2 JSON file) stores the blob sizes as σ in logical units (a disc's diameter is 2·cutoff·σ):

FieldTypeDescription
min_scaleLogicalCountSmallest σ (px) — the bottom rung of the scale ladder
max_scaleLogicalCountLargest σ (px) — the top of the scale ladder, exactly as requested

PatternConfig(; pattern_resolution, min_scale, max_scale, …) takes these storage-level σ values directly (max_scale = nothing applies the default rule).

Examples

using BlobBoardsusing VisualGeometryCore: px# Basic usagepattern, blobs, config = blob_pattern(800, 600; blob_sizes=(12px, nothing), seed=0x1234)# Denser scale samplingpattern, blobs, config = blob_pattern(800, 600;    blob_sizes = (12px, nothing),    scales_per_octave = 4,    seed = 0x1234)# Save to diskpattern, blobs, config = blob_pattern(800, 600;    blob_sizes = (12px, nothing),    dir = "./output")

blob_board - Board Generation

Generate printable calibration boards with borders, rulers, and metadata.

Signatures

# From paper size nameblob_board(paper_size::String, print_density; kwargs...)# From explicit dimensionsblob_board(width, height, print_density; kwargs...)blob_board(Size2(width=W, height=H), print_density; kwargs...)# From JSON (reconstruction, as printed: format / pdf_standard / id_label# default to the JSON's `render` block; a keyword overrides it)blob_board(json_string; dir=nothing, format=nothing, pdf_standard=nothing, id_label=nothing)

Keyword Arguments

Every keyword — output (dir, format, pdf_standard, icc_profile, id_label), pattern (blob_sizes, seed, polarity, …), board and frame (board_size, frame_width, frame_style, frame_padding) and ruler ticks — with its default and valid values is listed in the blob_board reference.

Examples

using BlobBoards      # re-exports the units: mm, inch, px, dpi, …using CairoMakie      # loads the board-authoring extension# Basic A4 boardbundle = blob_board("A4", 300dpi; dir="./output")# Custom size with parametersbundle = blob_board(200mm, 280mm, 300dpi;    blob_sizes = (3.2mm, nothing),    frame_width = 25mm,    seed = 0x1234,    dir = "./output")# Saddle frame with paddingbundle = blob_board("A4", 300dpi;    blob_sizes = (4.0mm, nothing),    frame_style = :saddle,    frame_padding = 2mm,    dir = "./output")# Blank frame (corners only)bundle = blob_board("A4", 300dpi;    blob_sizes = (4.0mm, nothing),    frame_style = :none,    dir = "./output")# High-resolution for printingbundle = blob_board("A3", 600dpi;    blob_sizes = (2.0mm, nothing),    format = "pdf",    icc_profile = :linear,    dir = "./output")# PNG for digital usebundle = blob_board("A4", 300dpi;    format = "png",    dir = "./output")

Available Paper Sizes

CategorySizes
ISO A-seriesA0, A1, A2, A3, A4, A5
ANSIANSI A, ANSI B, ANSI C, ANSI D, ANSI E, ANSI E1
CommonLetter, US Letter, Legal, Tabloid, Ledger

Blob and Saddle Point Extraction

blobs - Unified Extraction

Extract blobs with specified reference frame and units:

bundle, image = load("blob_board.json")# Pixel units (default) in pattern frameb = blobs(bundle, :pattern)# Physical unitsb = blobs(bundle, :pattern; units=mm)b = blobs(bundle, :canvas; units=inch)# From PatternBundle (no reference frame needed)b = blobs(pattern_bundle)

saddle_points (Boards with :saddle frame only)

Extract checkerboard saddle points:

sp = saddle_points(bundle, :pattern)              # Pixel unitssp = saddle_points(bundle, :pattern; units=mm)     # Physical units

World Coordinates (Boards Only)

Extract blobs in 3D calibration coordinates:

b = blobs(bundle, :world)# Returns: Vector{Disc} with centered, y-up coordinates in unitless mm

File I/O

Loading

bundle, image = load("blob_board.json")   # From JSONbundle, image = load("blob_board.pdf")    # From PDFbundle, image = load("blob_pattern.png")  # From PNG

Saving

# Boards (automatic during blob_board if dir provided)save(figure, bundle; dir="./output", format="pdf")# Patterns (automatic during blob_pattern if dir provided)save(pattern, bundle; dir="./output")

Training Pipeline

build_tracks_for_sequences - Track Generation

Detect the boards in every media item under a directory and accumulate their patch tracks into one .tracks file:

out = build_tracks_for_sequences(board_dir, model_path, video_dir;    n_frames = 100,            # or stride=5    output_dir = "./output",   # writes <output_name>_<patch_type>_s<scale>.tracks    iou_threshold = 0.6,    patch_type = :logpolar,    scale = 32,    blur_sigma_max = 0,        # augmentations; 0 disables)

See Board Training Tracks for the full guide. The older build_tracks, which chained correspondences from relative .npy homographies, was removed in 2026-08.

Loading Tracks

.tracks is plain HDF5 (see examples/training/TRACKS_FORMAT.md); read it with HDF5.jl, h5py, or the Python helper blobboards.load_tracks.

Critical Unit Distinction

Pattern functions take blob_sizes in logical units (px):

blob_pattern(800, 600; blob_sizes=(12px, nothing))  # px = pixels

Board functions take blob_sizes in physical units (mm, inch):

blob_board("A4", 300dpi; blob_sizes=(4.0mm, nothing))  # mm = millimeters

The conversion happens automatically based on print_density; both are stored as σ in px (min_scale/max_scale).

The Board JSON

Every board is saved as a print file plus a JSON sidecar, blob_board_<uid>_<hash>.json:

{
  "schema": "blobboards/board/v3",
  "preamble": {
    "board_config":   { canvas_size, board_size, print_density, frame_width,
                        frame_padding, frame_style,
                        ruler_spec: { major_tick: { spacing, width },
                                      minor_tick: { spacing, width } } },
    "pattern_config": { pattern_resolution, min_scale, max_scale,   (σ, px)
                        seed, pixel_type, scales_per_octave, max_trials,
                        alpha, cutoff, raster_aligned, polarity }
  },
  "blobs":         { "unit": "px", "centers": […], "sigmas": […] },
  "saddle_points": [ … ],                  (frame_style = "saddle"; else [])
  "hashes":        { "config": "<sha256 of the canonical preamble>" },
  "render":        { "format": "pdf", "pdf_standard": "x4", "icc_profile": null,
                     "id_label": true }
}

Lengths are { "value": …, "unit": "mm" | "px" | "dpi" }; a tick's width is its full drawn length across the frame band.

  • Identity is hashes.config, the SHA-256 of the canonical preamble; the file name and the printed uid are its first characters. It is stored, never recomputed on load.
  • Blob sizes are stored only as σ in pattern pixels (min_scale, max_scale); blob_sizes and its units are an input convenience and are not recorded, so every spelling of one board mints one identity. The physical side lives in board_config (print_density, sizes in mm).
  • render records how the print file was made. It is not part of the identity: the same board with or without its id label has one hash. blob_board(json) and the gallery's regeneration render as recorded; a file without the block renders as PDF/X-4 with no label.
  • Older schemas still load. v1 files (with max_diameter_fraction) have the fraction converted to the largest σ it produced, so v1 boards re-place bit-identically. v1 and v2 rulers carry a ruler_spec.width and half-length tick widths; the reader drops the one and doubles the others, which is the ruler those boards were drawn with. Their stored hashes.config stays their identity.