System designHow-to

Estimate SNR from a single noisy image without a reference

Estimate SNR from a single noisy image with a flat 64 x 64 patch: its mean is the signal, its variance the noise, and the dB conversion is shown.

LumaSpec Vision11 min read Share on LinkedIn

On this page 10 sections
  1. 01What does SNR actually mean for one image?
  2. 02Where do you find signal and noise in a single frame?
  3. 03How do you compute SNR from one flat patch?
  4. 04What does the calculation look like with real numbers?
  5. 05What if no region of the image is perfectly flat?
  6. 06Should you measure on the blurred input or the filtered output?
  7. 07How much noise can no filter remove?
  8. 08Can one frame separate read noise from fixed-pattern noise?
  9. 09How do you make the measurement repeatable?
  10. 10Questions

You have one blurred, noisy image and a Wiener filter, and you want a signal-to-noise ratio for the image before and after the filter - with no clean reference to subtract. The working method is to find a region where you already know the answer: a flat patch whose true signal is a constant. Its mean is the signal, its variance is the noise, and the ratio follows in one line. This walkthrough gives the formula, a worked example with the arithmetic shown, the shot-noise ceiling no filter can beat, and the settings that make the number repeatable on a line.

What does SNR actually mean for one image?

SNR is the ratio of the power in the wanted signal to the power in the unwanted noise: with a flat patch of mean μ and standard deviation σ, the amplitude form is μ/σ, the power form is μ²/σ², and both convert to the same dB value. The power form answers the P_signal/P_noise question directly. The imaging tradition writes the amplitude ratio of the average signal to the standard deviation (signal-to-noise ratio in imaging), which squares into the power form. Report the power form in dB and nobody has to guess which one you meant.

SNR_power = P_signal / P_noise = mean^2 / variance SNR_dB = 10 · log10(mean^2 / variance) = 20 · log10(mean / std)

Where do you find signal and noise in a single frame?

Take a featureless patch - background, a uniform surface, an out-of-focus wall - of at least 50×50 pixels: there the true signal is a constant, so every deviation from the patch mean is noise, which is the reference you thought you were missing. Machine-vision scenes are full of flat ground: the backdrop behind the part, a machined face, the floor of a tray, a region far out of focus. Rules for choosing one:

  • Stay off edges, lettering, texture and anything with a gradient across it.
  • Exclude saturated pixels: values piled at 0 or at the top of the code range make variance meaningless.
  • Blur does not disqualify a patch. A linear blur maps a constant to the same constant, so a flat region stays flat in a blurred image - the method works directly on the blurred input.
  • Keep the same ROI discipline you use to measure light intensity with an ROI and a reference: fixed coordinates, logged, never chosen after looking at the values.

How do you compute SNR from one flat patch?

You estimate signal power as the square of the patch mean and noise power as the patch variance, so SNR = mean²/variance, and the whole procedure is six steps that run in one short script. Work through them in this order:

  1. Turn every auto mode off - auto exposure, auto gain, auto white balance - and fix the light level. The same settings that stop image brightness drifting over time also make a noise measurement repeatable.
  2. Capture the frame at full bit depth, 12-bit data in a 16-bit buffer, no JPEG compression. The rule that lets you save 12-bit frames as 16-bit PNG or TIFF applies here too: compression changes variance.
  3. Pick the flat 64×64 patch and record its position.
  4. Compute the mean and the population variance over all 4,096 pixels (ddof = 0).
  5. Check the patch histogram: one mode, no pile at either end of the code range.
  6. Divide, take the logarithm, and log the mean, variance, gain and exposure beside the number.
import numpy as np

# img: 2-D uint16 array from the camera, one exposure, auto modes off
x0, y0, size = 512, 384, 64        # int patch corner and side, in pixels
patch = img[y0:y0 + size, x0:x0 + size].astype(np.float64)

mean = float(patch.mean())          # DN
var = float(patch.var())            # DN^2, population variance (ddof=0)
snr_power = mean ** 2 / var
snr_db = 10.0 * np.log10(snr_power)
print(mean, var, snr_power, snr_db)
# 120.0 25.0 576.0 27.60

What does the calculation look like with real numbers?

With a 64×64 patch - 4,096 pixels - at mean 120.0 DN and standard deviation 5.0 DN, the amplitude SNR is 120/5 = 24, the power SNR is 120²/5² = 576, and both forms convert to 27.6 dB. The arithmetic, line by line:

  • Signal power: 120.0² = 14,400 DN².
  • Noise power: 5.0² = 25.0 DN².
  • Power SNR: 14,400 / 25.0 = 576.
  • Decibels: 10 · log10(576) = 27.6 dB, identical to 20 · log10(24).

How tight is that number? The standard deviation estimated from N pixels carries a relative error near 1/√(2N). At N = 4,096 that is 1/90.5 = 1.1%, so σ is uncertain by 5.0 × 0.011 = 0.06 DN and the SNR is good to about ±0.1 dB. Expect that spread from patch to patch, and no more.

Light level moves the answer fast. The same scene at mean 30.0 DN with σ = 4.0 DN gives 30²/16 = 56, or 17.5 dB - ten dB down from the bright case. That gap is why the light setting belongs in the log next to the number.

What if no region of the image is perfectly flat?

Fit the slow structure instead of trusting the raw spread: remove a least-squares plane from the patch and take the variance of the residuals, or use the outlier-tolerant estimator σ ≈ 1.4826 × MAD, the median absolute deviation scaled to a Gaussian. A gradient is the trap here. A patch spanning a uniform 10 DN ramp carries ramp variance 10²/12 = 8.3 DN² on top of the true 25.0 DN²; the raw method would report 33.3 DN² and cost you 1.2 dB. The plane fit removes the ramp and keeps the noise.

Two defensible routes, in order of preference:

  • Plane fit: least squares of a + bx + cy over the patch; the residual variance is the noise. Use it whenever a gradient is plausible - backlight edges, vignetting, a curved surface.
  • MAD: σ ≈ 1.4826 × median(|x − median|). With MAD = 3.4 DN you get σ ≈ 5.0 DN, matching the variance route on a clean patch and ignoring the odd hot pixel.

The same variance-on-a-flat-region math, run as a moving window, is local variance filtering for defect detection: there the excess variance is the defect, here it is the noise.

Should you measure on the blurred input or the filtered output?

Measure SNR on the blurred input X, never on the Wiener output Y alone: deblurring amplifies noise while it restores edges, so one SNR number from Y cannot say how much noise was deleted. You can legitimately measure two numbers - SNR(X) on X's patch and SNR(Y) on the same patch of Y. What does not exist from a single image is a whole-frame "noise removed" figure, because the filter also changed the signal: sharpened edges, flattened texture. A true improvement score needs the clean reference and an RMSE.

What you can state from one image: on a flat patch both the blur and the filter leave a constant alone, so the drop in variance there is noise power genuinely removed in that region. With σ_X = 1.7 DN and σ_Y = 1.1 DN, removed noise power is 1.7² − 1.1² = 2.9 − 1.2 = 1.7 DN².

Remember that X's noise is already blur-shaped. White noise through a normalized 3×3 box kernel comes out at one third of the standard deviation, so a raw σ of 5.0 DN reads 1.7 DN after that blur. The patch on X measures X's own noise; to compare it with camera data-sheet figures, divide out the kernel power Σh² when you know the kernel.

Scoring Y against X with no reference at all - the tools covered in image similarity comparison - tells you how far Y moved from X, not which image is cleaner. Good for catching a filter that did nothing; not an SNR.

How much noise can no filter remove?

Photon shot noise sets the floor: photon arrivals are Poisson, so noise variance equals the collected charge in electrons and the best possible SNR is √N_e - 4,000 e⁻ tops out at 63, or 36.0 dB, whatever filter follows. This is the physics of every camera, not a defect of inexpensive ones (shot noise). The full camera equation:

SNR = (Φ · QE · t) / sqrt(Φ · QE · t + N_d · t + N_r^2)

with Φ the photon flux, QE the quantum efficiency, t the exposure time, N_d the dark current and N_r the read noise. Worked numbers: a patch collecting Φ·QE·t = 4,000 e⁻ with read noise 6 e⁻ and negligible dark gives σ = √4,036 = 63.5 e⁻ and SNR = 4,000/63.5 = 63, which is 36.0 dB. Double the light: 8,000 e⁻, σ = √8,036 = 89.6 e⁻, SNR = 89, which is 39.0 dB. Three dB per doubling of photons, always.

Cross-check the DN measurement against this. At a camera gain of 4.8 e⁻/DN, the 120.0 DN patch is 576 e⁻, and shot noise alone predicts σ = √576/4.8 = 24/4.8 = 5.0 DN - exactly what the patch measured, so that patch was photon-limited. In that regime the power SNR numerically equals the electron count, a quick sanity check on any gain figure you were given.

Can one frame separate read noise from fixed-pattern noise?

One frame cannot: a single capture measures temporal noise and fixed-pattern noise added in power, and pulling them apart needs a second frame of the same static scene. The split, with A and B two frames of the unchanged scene:

sigma_temporal = std(A - B) / sqrt(2) sigma_fixed^2 = Var((A + B) / 2) - sigma_temporal^2 / 2

Numbers: std(A − B) = 7.1 DN gives σ_temporal = 7.1/1.414 = 5.0 DN; Var((A + B)/2) = 14.5 DN² gives σ_fixed² = 14.5 − 12.5 = 2.0 DN², so σ_fixed = 1.4 DN. The single-frame total then checks out: √(25.0 + 2.0) = 5.2 DN.

The difference A − B goes negative, so keep it in a signed 16-bit buffer - the wrap-around that produces impossible negative means in unsigned 8-bit data is the pitfall fixed in SNR calculation from 8-bit camera images.

How do you make the measurement repeatable?

Fix the optics, the light and every camera auto mode before you measure, then record patch position, gain and exposure with the number: the same camera and controller at one setting repeat to about ±1%. For the camera, a mono area scan camera such as the MV-CS200-10UM removes demosaicing and white balance from the list of things that can move the mean:

Area scan camerasHikrobot MV-CS200-10UM 20 MP Area Scan Camera, USB3.0, IMX183, 2nd Gen., MonoMV-CS200-10UM
Sensor format
1"
Lens mount
C-mount
Interface
USB3
Resolution
16-25 MP
$759.00View partBuild a system with it

When the check has to run on the device with no PC, a smart camera such as the LS-SMC-0063, with its own lens and white light source, can hold the patch routine and the pass threshold on board:

Smart cameras & vision sensors1.6 MP smart camera, 60 fps, 16 mm lens, white light (polarized, transparent light) (LS-SMC-0063)LS-SMC-0063
Interface
GigE
Resolution
Up to 3 MP
$1,110.00View part

Hold the light at one commanded level with a light controller such as the LS-CTL-0290, a 24 V constant-voltage unit with 4 channels, and log the level with every capture - the light controller finder lists the strobed and constant-current units when your lights need them:

Light controllersDigital constant-voltage light controller, 60 W, 4 channels (LS-CTL-0290)LS-CTL-0290
Output
Constant voltage 24 V
Channels
4 channels
Control
Digital
$449.00View partBuild a system with it

Before you commission the check, run this list:

  • Flat patch of at least 50×50 pixels, coordinates written down.
  • No pixels at 0 or at the top of the code range.
  • Every auto mode off; gain and exposure logged.
  • The same patch coordinates used on X and on Y.
  • Plane-fit variance whenever a gradient is plausible.
  • A second frame captured when the temporal versus fixed-pattern split matters.
  • Light level commanded and logged, not just observed.

Next step: run the script on one of your own frames, then configure the camera and light together or browse the camera finder for the body that will hold the setting.

Questions

Which SNR formula should I report, mean over std or mean squared over variance?

Report the power form, mean²/variance, because it matches the P_signal/P_noise definition, and give it in dB as 10·log10(mean²/variance). If a colleague used the amplitude form mean/std, the dB value is identical, since 20·log10(mean/std) is the same logarithm; only the plain ratio differs by a square. State which ratio you used and the number is unambiguous.

How small can the flat patch be and still give a good estimate?

The standard deviation of a patch of N pixels carries a relative error near 1/√(2N). At 4,096 pixels (64×64) that is 1.1%, good to about ±0.1 dB; at 625 pixels (25×25) it is 2.8%, about ±0.25 dB. Stay at 50×50 or larger and patch size stops mattering; below that the estimate wanders between patches and the choice of rectangle starts deciding the answer.

The flat patch got quieter after filtering but the edges look worse - did the filter help?

Both observations are real. On a flat patch the filter removed noise power you can count as σ_X² − σ_Y², and in exchange the edges lost detail. A single-image SNR cannot weigh the two against each other over the whole frame; that needs the clean reference and an RMSE. Judge deblurring on your task metric - edge width, read rate, defect recall - never on patch variance alone.

Does making the scene brighter always improve the measured SNR?

Up to saturation, yes, and predictably: photon shot noise variance equals the collected charge, so doubling the photons improves a shot-limited SNR by √2, a 3 dB gain per doubling. A dim light loses twice, less signal and proportionally more read-noise contribution. Measure at the light level the line will actually run at, not at a bench-bright setting, or the number will flatter the set-up.

Can I run this measurement on a color camera image?

Yes, per channel: demosaicing mixes neighbouring pixels, so measure the red, green and blue planes separately, or capture raw Bayer data and use the green plane, which carries twice the samples. White balance and gamma shift each channel mean differently, so switch both off before capturing. For a dedicated noise measurement, a mono camera avoids the whole problem and is the better instrument.