Skip to main content

Synthetic dataset generator for camera + laser-stripe calibration.

Project description

synthcal

CI PyPI

Synthetic dataset generator for camera + laser-stripe calibration.

Install

pip install synthcal
# Optional (recommended for faster Gaussian blur):
pip install "synthcal[scipy]"

Quickstart

Initialize an example config:

synthcal init-config config.yaml

Preview one frame/camera:

synthcal preview config.yaml --frame 0 --cam cam00

Generate a dataset:

synthcal generate config.yaml out_dataset/

python -m synthcal ... is also supported.

Scope

This repository focuses on:

  • Generating datasets of static robot poses for an eye-in-hand multi-camera rig.
  • For each frame and camera, producing paired outputs from the same pose:
    1. target.png: chessboard under normal illumination
    2. stripe.png: black background with only a laser stripe (when laser is enabled)
    3. corners_px.npy (float32, N x 2) + corners_visible.npy (bool, N)
    4. stripe_centerline_px.npy (float32, M x 2) + stripe_centerline_visible.npy (bool, M)

Units: millimeters (mm) everywhere for geometry. Pixel coordinates are in pixels.

Camera model: OpenCV-style intrinsics K + distortion dist = (k1, k2, k3, p1, p2) (no OpenCV dependency).

Examples

See examples/minimal_no_laser.yaml, examples/minimal_with_laser.yaml, and examples/multicam_medium.yaml.

Camera model

Projection uses the standard pinhole model with distortion applied in normalized coordinates (x, y):

r2 = x^2 + y^2
radial = 1 + k1*r2 + k2*r2^2 + k3*r2^3
x_tan = 2*p1*x*y + p2*(r2 + 2*x^2)
y_tan = p1*(r2 + 2*y^2) + 2*p2*x*y
xd = x*radial + x_tan
yd = y*radial + y_tan

Undistortion is implemented as a simple fixed-point iteration starting from (xu, yu) = (xd, yd) and repeatedly subtracting the forward-model error until convergence (works well for small/moderate distortion and points near the principal point).

Outputs

The dataset layout is described in manifest.yaml (schema v1). Outputs include:

  • config.yaml (the normalized config used to generate)
  • manifest.yaml (stable schema v1; also includes version: 1)
  • per-frame T_base_tcp.npy (identity for all frames unless scenario pose sampling is enabled)
  • per-frame/per-camera *_target.png + *_corners_*.npy
  • when laser is enabled: per-frame/per-camera *_stripe.png + *_stripe_centerline_*.npy
  • placeholder rig/camera YAML files (rig/)

Effects

Rendered images can be post-processed to add simple realism:

  • blur_sigma_px: Gaussian defocus blur sigma in pixels
  • noise_sigma: zero-mean Gaussian read noise sigma in intensity units (0..255)

Order of operations: blur → noise → clamp → quantize to uint8. Blur uses SciPy (scipy.ndimage.gaussian_filter) when available; otherwise synthcal falls back to a deterministic NumPy implementation (slower).

Determinism: noise is seeded from the global dataset seed and a stable per-output key (frame_index, camera_name, modality) so re-generating with the same config+seed produces identical images. Effects are applied to both *_target.png and *_stripe.png (when present).

Scenario

Optional scenario pose sampling can generate a different T_base_tcp per frame while enforcing in-view constraints (all corners inside the image with a margin). Presets easy|medium|hard provide reasonable default ranges; all randomness is derived from the global seed.

Laser

Laser output is optional. When enabled, synthcal models the laser as a single infinite plane in the TCP frame: n·X + d = 0 (X in mm). The stripe is rendered only where the laser plane intersects the target plane (Z=0 in target frame). If the planes are nearly parallel, synthcal outputs a black stripe image and empty centerline arrays for that (frame, camera).

Reproducibility

  • seed is the single global seed recorded in config.yaml and manifest.yaml.
  • Noise/effects use deterministic per-output RNG streams derived from (seed, frame_index, camera_name, modality).
  • Scenario pose sampling uses a deterministic per-frame stream derived from (seed, frame_index, "__scenario__", "pose").

Public API

Supported library entry points live in src/synthcal/api.py:

from synthcal import generate_dataset, render_frame_preview

CLI

The CLI provides:

  • synthcal init-config
  • synthcal preview
  • synthcal generate

Preview options:

  • --no-effects: show the raw render (before blur/noise/quantize)
  • --all-cams: show a grid for all cameras
  • --show-stripe: with --all-cams, also show a stripe grid when laser is enabled

Coordinate conventions

  • Frames (v0): world == base (eye-in-hand only).
  • T_tcp_cam maps TCP-frame points into the camera frame.
  • T_cam_target maps target-frame points into the camera frame: X_cam = T_cam_target @ [X_target, 1].
  • The chessboard target lies in plane Z=0 in the target frame, with outer corner at (0,0,0).
  • Inner corners are ordered row-major (rows first, then cols), matching OpenCV’s convention.

Docs

  • docs/config_reference.md
  • docs/manifest_reference.md

Extending synthcal

Targets, sensors, sampling, and effects are implemented in src/synthcal/. Only the functions in src/synthcal/api.py are intended to be stable for external users.

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

synthcal-0.1.0.tar.gz (43.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

synthcal-0.1.0-py3-none-any.whl (46.3 kB view details)

Uploaded Python 3

File details

Details for the file synthcal-0.1.0.tar.gz.

File metadata

  • Download URL: synthcal-0.1.0.tar.gz
  • Upload date:
  • Size: 43.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for synthcal-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3aa67b7b831822680c7c22e84c338326c782ea5497f7aeda5d8cb7b7048c9de6
MD5 10ca9d4e53fdbfad7321463b12fa189d
BLAKE2b-256 820992a8c2af3a77774e68cad5d211b12e1a7593794d2fc74c7a27f9dbe7ab48

See more details on using hashes here.

Provenance

The following attestation bundles were made for synthcal-0.1.0.tar.gz:

Publisher: publish.yml on VitalyVorobyev/calib-synth

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file synthcal-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: synthcal-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 46.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for synthcal-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8a51f9403814d569d8fe863678f23c14bfe9a1b2c7bea442e603f6d2c8975700
MD5 bda60ea0d5dea9243f0d502cbe462ac0
BLAKE2b-256 bb01792b9edc7ff8da37e1a3c23a748e0f0c69c92b3e705f8acc48e06114099d

See more details on using hashes here.

Provenance

The following attestation bundles were made for synthcal-0.1.0-py3-none-any.whl:

Publisher: publish.yml on VitalyVorobyev/calib-synth

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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