calibration_views — OPTICS imaging_sim op

Data kinds: tabletable

Call: import lensimage; lensimage.calibration_views(system, image_size=(1024, 1024), pixel_pitch_um=5.5, target=(9, 7, 5.0), poses=None, distance_mm=None, noise_px=0.0, seed=0, order=2) (or opsoptics.get("calibration_views"))

Usage

Synthetic camera-calibration views of a planar target through the designed lens (`table`).

A chessboard-like grid of *target* = (cols, rows, pitch_mm) corner points

on the plane z = 0 is placed at each of *poses* — ``(rx_deg, ry_deg,

rz_deg, tx_mm, ty_mm, tz_mm)`` in the camera frame (camera at the origin

looking along +z; default: five poses, frontal and ±20° about x and y, at

*distance_mm* — default the distance at which the target spans 60 % of

the sensor width) — projected by a pinhole of the prescription's EFL and

then displaced by the lens's real radial distortion (the polynomial

:func:distortion_map fits from traced chief rays), and expressed as

`(row, col)` pixels on an *image_size* sensor of *pixel_pitch_um*.

Optional Gaussian corner-detection noise *noise_px* (deterministic for

*seed*).

Returns `object_points (N,2) mm on the target plane, image_points`

(a list of (N,2) `(row, col)` arrays — exactly what

`calib.camera_calibration consumes), K_true` (fx = fy = EFL/pitch

px, cx, cy at the sensor centre), the distortion polynomial, the poses,

and per view the fraction of points that landed on the sensor. Views with

fewer than four visible points, a target behind the camera, or an afocal

prescription are `ValueError`.

The point of the op is the closed loop: feed the output to

`calib.camera_calibration` and compare the recovered intrinsics with

`K_true` — for a distortion-free lens (the paraboloid) Zhang's method

returns the EFL to 1e-6, and the singlet's barrel distortion shows up as a

focal-length bias and a non-zero reprojection RMS, so the calibration

module is checked end to end against a lens whose truth is known, and a

real chart can be judged against the same numbers.

Family-wide input contract (fail-closed)

Every optics op validates its input before computing (nothing slips through silently):

Units are baked into the argument name_mm / _um / _deg / _mrad. Confusing mm with µm does not crash; it yields a plausible-looking wrong answer, so the name prevents it. Nothing here guesses the unit from the magnitude.

• **Strings raise ValueError** — float('50') succeeds, so an unparsed configuration value would slip through as a length (measured: thin_lens('50', '200') returned a plausible 66.667 mm). bool is refused too, as the implicit promotion True == 1.

• **complex / masked arrays raise ValueError (real-valued slots only; silently dropping the imaginary part or peeling off the mask is refused). NaN/Inf raises ValueError on every input.**

Division by zero and its relatives are refused by name: focal length 0, radius of curvature 0, refractive index <= 0, a fully opaque aperture (all zeros, so the normalisation is 0/0), a PSF whose sum is <= 0, a Stokes vector with S0 = 0, and an object sitting at the front focal point (the image is at infinity).

Only two ops return a non-finite value, and both state it as a contract: depth_of_field returns far_mm = inf beyond the hyperfocal distance (that is what the hyperfocal distance means), and gaussian_beam returns wavefront_radius_mm = inf at the waist (the radius of curvature of a plane wavefront). Both also return a finite companion (far_is_infinite / curvature_per_mm). **Any other silent NaN/Inf is detected internally and raises ValueError** — "float64 overflowed" and "the answer is infinite" are different claims, so the first is never returned wearing the face of the second.

Size caps: generated grids are capped by optics.MAX_GRID (4096); supplied fields/PSFs/apertures by optics.MAX_FIELD_ELEMENTS (2^24); ABCD element chains by optics.MAX_SYSTEM_ELEMENTS (1024); Zernike by MAX_ZERNIKE_TERMS (512) / MAX_ZERNIKE_ORDER (40) / MAX_ZERNIKE_BASIS (2^25). This closes, fail-closed, the paths where a small argument triggers a huge internal allocation (measured: n_max=40 × 4096² needs 108 GB).

Physically impossible states are refused too: a Stokes vector with degree of polarisation > 1, negative transmittance, negative intensity, and invalid Zernike indices such as n-|m| odd.

Detailed usage guide

optics_imaging family guide

Background guides (the physics and conventions behind this op)

mv_cables — ケーブル(規格・速度・給電・ロボットケーブル)

mv_cameras — 産業用カメラメーカー(センサとの紐付け・ラインスキャン / TDI)

mv_frame_grabbers — フレームグラバーボード(光学系ではないが、撮れるかを決める)

mv_image_sensors — 産業用イメージセンサ(現行品中心)

mv_standards — カメラインターフェースの規格と団体

virtual_machine_vision — 仮想マシンビジョン — パラメータの洗い出しとオブジェクト模型

References (sample data, literature)

• Sample-data catalog (download URLs / licences) — 2-D uses skimage.data (BSD/public domain) plus synthetic images; 3-D lists download URLs for real data sources (Stanford, PDS, …).

• Operator provenance and references — the sources of the research/methods this op family came from.

• The canonical algorithm (author, year) and its uses are named in the family usage guide above.

Runnable examples (verified samples that actually call this op)

lens_calibration_loop_demopy -3.11 examples/lens_calibration_loop_demo.py

Ops the type connects to (they accept table as input)

abcd_matrix · wavefront_stats · paraxial_trace · seidel_coefficients · spot_stats · tolerance_analysis · wavefront_from_opd · spot_diagram

Same category (imaging_sim)

psf_from_opd · distortion_map · render_through_lens · defect_dataset


*Provenance: lensimage.py — OPTICS operator registry. This per-op note is generated by tools/opdocs.py md (do not hand-edit).*

© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.