Skip to content
PreciSim
physics

Noise

Shot noise, read noise, dark current, bad pixels — and how each one limits calibration accuracy.

Three terms

Every pixel of the virtual camera gets:

DN = DN_ideal + n_shot + n_read + n_dark

n_shot ~ Poisson(e_signal)                signal dependent, larger in bright areas
n_read ~ N(0, σ_read²)                    signal independent, dominant in the dark
n_dark ~ Poisson(i_dark · t_exp)          proportional to exposure time

Defaults, modelled on a common industrial CMOS:

Parameter Value Note
σ_read 2.3 e⁻ Read noise
i_dark 12 e⁻/s Dark current at room temperature
e_full 10500 e⁻ Full well
QE 0.62 @ 530 nm Quantum efficiency
bits 8 or 12 Selectable

Signal-to-noise ratio

SNR = e_signal / sqrt(e_signal + σ_read² + i_dark·t_exp)

Once the signal is strong, SNR ≈ sqrt(e_signal)double the brightness and SNR improves by only 1.41×. That answers a question we get often: why cranking exposure barely helped.

How noise limits calibration

This is the part that matters.

Circle centre extraction

A centre is derived from subpixel edge positions, each jittering by σ_edge. For a circle with N edge points:

σ_centre ≈ σ_edge / sqrt(N)

So bigger circles give steadier centres. This is why calibration target circles should not be small: a 10 px circle and a 30 px circle differ by about 1.7× in centre precision.

Pixel size

Pixel size is solved from distances between centres, and least squares averages some of the centre error away:

σ_scale / scale ≈ σ_centre / (D · sqrt(M))

where D is the acquisition span in pixels and M the number of poses.

Two practical conclusions:

  1. Span matters more than pose count. Nine poses across 50 mm beat fifty poses across 5 mm, by a lot.
  2. Going from 9 to 36 poses improves precision 2×; going from 5 mm to 50 mm of span improves it 10×.

Beginners almost always do the opposite — a dense cluster in the centre of the field, followed by surprise that it is not accurate.

Focus

See Optics and defocus.

Bad pixels

Generated at a configured rate (0.001 % by default), in two kinds:

  • hot: stuck at a high value;
  • dead: stuck at zero.

Positions are fixed for the lifetime of a virtual machine, as on a real sensor. That makes bad pixel compensation genuinely testable: get the map right and changing exposure will not make them reappear.

Configuration

Devices → Virtual devices → Camera → Noise:

"noise": {
  "enabled": true,
  "readNoiseE": 2.3,
  "darkCurrentEPerS": 12,
  "fullWellE": 10500,
  "qe": 0.62,
  "badPixelRatio": 1e-5,
  "seed": 20260921
}

With seed fixed, noise is reproducible — the same input gives the same image. That is what makes an assertion like "centre error < 0.05 px" meaningful in an automated test. Set seed to null for fresh randomness each run, which feels more like real hardware and suits teaching.

Last updated: Sep 21, 2026
Was this page helpful?