Concepts¶
The imaging chain¶
flowchart LR
A["Scene radiance<br/>ρ(λ) · E_scene(λ)"] --> B["Optics<br/>PSF, aperture, T_lens(λ)"]
B --> C["Sensor-plane irradiance<br/>E_img(λ), (H, W, λ)"]
C --> D["Sensor<br/>QE, IR-cut, CFA, noise, gain, ADC"]
D --> E["RAW frame<br/>uint16 + metadata"]
E --> F["ISP<br/>linear-space stages"]
F --> G["Tone / OETF<br/>(the only non-linear step)"]
G --> H["Rendered image"]
H --> I["Metrics harness<br/>MTF, SNR, ΔE, acutance"]
The sensor-plane irradiance is the key boundary. A user with an externally
computed spectral cube can bypass the scene and optics helpers and feed a
validated SpectralIrradiance directly into the sensor.
Radiometry and units¶
Scene and image-plane quantities are spectral and carry explicit units. For a Lambertian scene, the image-plane spectral irradiance is
E_img(λ) = ρ(λ) · E_scene(λ) · T_lens(λ) / (4 N²) · cos⁴θ
Photometric normalization is explicit: when an illuminant is given in relative units and a target illuminance in lux, the scene scales the SPD by
E_scene(λ) = lux · SPD(λ) / (K_m · ∫ SPD(λ) · V(λ) dλ), K_m = 683 lm/W
The sensor integrates photons over its spectral responses:
electron_rate = ∫ QE(λ) · T_IR(λ) · T_CFA(λ) · E(λ) · A / (hc/λ) dλ
No stage is allowed to carry hidden unit ambiguity: field names include units, and conversions are explicit functions.
Spectral boundary¶
The sensor accepts irradiance at the sensor plane before its own spectral filters (IR-cut, CFA, microlens). Supplying data that already includes the IR-cut means configuring the sensor to disable it. The sensor never resamples implicitly: spatial and wavelength resampling are explicit helper calls, with energy-conserving averaging/integration and a clear error when the input does not cover the sensor's wavelength range.
Linear-space invariant¶
DPC, BLC, LSC, AWB, demosaic, CCM, denoise, and sharpen all operate in linear float32. The tone curve and output transfer function (sRGB OETF or gamma) are the only non-linear steps in reconstruction. Tests assert the invariant, for example that scaling the linear input scales the pre-tone output.
Determinism¶
Stochastic routines use explicit numpy.random.Generator objects, never a
global RNG. Fixed-pattern maps (defects, DSNU, PRNU, PDAF masks) are generated
from a pattern seed and reused; per-frame noise uses a per-call seed or a
deterministic stream. Within one environment and the same seeds, RAW output is
bit-identical. Across platforms, floating-point reductions may differ, so CI
uses tolerance-based golden tests.
Metrics independence¶
camsim.metrics is a sibling of the simulation packages, not a submodule of the
sensor or ISP. It consumes arrays plus metadata (ChartLayout,
ColorReference) and must not import camsim.sensor, camsim.isp,
camsim.scene, or camsim.optics. An import-independence test enforces this.
Validation approach¶
The pipeline is validated with analytic invariants (units, energy conservation, linearity, noise variance, clipping), EMVA 1288-style sensor characterization, ISO 12233-style e-SFR/MTF, colour and SNR checks, reference-library cross-checks, and datasheet plausibility. Determinism is tested within one environment; cross-platform comparisons use tolerances. The measured values, assumptions, and reproduction commands are indexed on the Validation page.