<a id="easyimage-noise-reduction"></a>

# Noise Reduction and Estimation

Noise can degrade the visual quality of images, and certain processing operations (thresholding, high-pass filtering) will be influenced by it in a non-acceptable way. Acquired images are always noisy (this is best observed on live images where the pixel values fluctuate around the true intensity). When acquired with 8 bits of accuracy, the noise level typically amounts to about 3 to 5 gray-level values. One distinguishes several forms of noise:

<a id="easyimage-noise-reduction-types"></a>

## Noise Types

- **Additive noise**<br />
  \\\\
  Noise is added to the signal and does **not** depend on image brightness: $I_{noisy} = I + n$
- **Multiplicative noise**<br />
  \\\\
  Noise strength **scales with local intensity** (brighter areas get more noise): $I_{noisy} = I \times (1 + n)$ (or $I_{noisy} = I \times n$)
- **Uniform noise**<br />
  \\\\
  Noise values are drawn from a **bounded uniform range** (often centered at 0), e.g. `n ~ U(-a, a)`. Looks like **fine grain/haze** because many pixels are perturbed slightly (“blends” into the image).
- **Impulse (salt-and-pepper) noise**
  A small fraction of pixels is replaced by **extreme values** (min/max), producing isolated black/white specks.

<a id="easyimage-noise-reduction-spatial"></a>

## Spatial Noise Reduction

This method is used when there is only one image. Reduces uniform and impulse noise, but blurs edges. Cannot distinguish noise from actual signal changes, so always spoils part of the signal. Uses the correlation between neighboring pixel values to perform convolution or median filtering:

* **Convolution** replaces the value at each pixel by a combination of its neighbors, leading to a localized averaging. Linear filtering is recommended to reduce uniform noise. As explained before, it tends to blur edges. See the [linear filtering operations](linear_filtering.html.md), especially the low-pass filtering.

![](assets/images/easyimage/noise_reduction/noisy_input.webp)![](assets/images/easyimage/noise_reduction/lowpass_output.webp)![](assets/images/easyimage/noise_reduction/lowpass_graph.webp)
* **Median filtering** replaces each pixel by the median value in the pixel neighborhood (for example: 5-th largest value in a 3x3 neighborhood). This reduces impulse noise and keeps sharpness.
  * [`EasyImage::Median`](../../../doxygen_cpp/classeVision_1_1EasyImage.html#af5779432e45e2124fe02abd7a7cc0dce) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyImage.html#a31fed78390e85ab08e732068ed0e0714) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyImage.html#a8aa88f40a2da316f54fef3c515a4f2f3)
  * [`EasyImage::BiLevelMedian`](../../../doxygen_cpp/classeVision_1_1EasyImage.html#ac3f43a4f8399072c795f937f6bdd3064) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyImage.html#a373a01e4637a50e8003ae4d253306bd1) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyImage.html#ae1c399097ac689c8feda6e3c59de1a1d)

![](assets/images/easyimage/noise_reduction/noisy_input.webp)![](assets/images/easyimage/noise_reduction/median_output.webp)![](assets/images/easyimage/noise_reduction/median_graph.webp)

<a id="easyimage-noise-reduction-temporal"></a>

## Temporal Noise Reduction

This method is used when they are several images. Temporal noise reduction is achieved by combining the successive values of individual pixels across time. **EasyImage** implements recursive averaging and moving averaging.

**EasyImage** provides three ways to minimize noise by means of several images:

* **Temporal average**: just accumulates N images and average them; using standard arithmetic operations, as illustrated below. Creates a denoised image after N acquisitions using average values. Noise varies from frame to frame while the signal remains unchanged, so if several images of the same (still) scene are available, noise can be separated from the signal. The disadvantage of producing one denoised image after N acquisitions only, is the image acquisition is effectly delayed and renders the refresh rate three times slower.
  ![image](assets/images/easyimage/17644.webp)
* **Temporal moving average**: accumulates the last N images and updates the denoised image each time a new one is acquired, in such a way that the computation time does not depend on N. The whole process is handled by [`EMovingAverage`](../../../doxygen_cpp/classeVision_1_1EMovingAverage.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMovingAverage.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMovingAverage.html).
  ![image](assets/images/easyimage/17645.webp)
* **Temporal recursive average**: combines a noisy image with the previously denoised image using [`EasyImage::RecursiveAverage`](../../../doxygen_cpp/classeVision_1_1EasyImage.html#a6fa21bcc4e69362d4783a3a1c3760ea3) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyImage.html#a605ca77f9688330baf5d75098f2e0f32) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyImage.html#a8da446df8c256d9b792f9465479ece2c).
  ![image](assets/images/easyimage/17646.webp)

<a id="easyimage-noise-reduction-recursive"></a>

### Recursive Averaging

This is a well known process for noise reduction by temporal integration. The principle is to continuously update a noise-free image by blending it, using a linear combination, with the raw, noisy, live image stream. Algorithmically, this amounts to the following:

$$
Dst_N = a \times Src + (1 - a) \times Dst_{N-1}
$$

where $a$ is a mixture coefficient. The value of this coefficient can be adjusted so that a controlled noise reduction ratio is achieved.

This procedure is effective when applied to still images, but generates a trailing effect on moving objects. The larger the noise reduction ratio, the heavier the trailing effect is. To work around this, a non-linearity can be introduced in the blending process: small gray-level value variations between successive images are usually noise, while large variations correspond to changes in the image.

[`EasyImage::RecursiveAverage`](../../../doxygen_cpp/classeVision_1_1EasyImage.html#a6fa21bcc4e69362d4783a3a1c3760ea3) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyImage.html#a605ca77f9688330baf5d75098f2e0f32) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyImage.html#a8da446df8c256d9b792f9465479ece2c) uses this observation and applies stronger noise reduction to small variations and conversely. This reduces noise in still areas and trailing in moving areas.

For optimal performance, the non-linearity must be precomputed once for all using function [`EasyImage::SetRecursiveAverageLUT`](../../../doxygen_cpp/classeVision_1_1EasyImage.html#ad1945a53c397eb84a583eaad63b975ae) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyImage.html#a9f55d1b5b16260c4cd0efebf5bddf038) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyImage.html#a49fb1ca51befb1c6580c6eb990a57261).

#### WARNING
Before the first call to the [`EasyImage::RecursiveAverage`](../../../doxygen_cpp/classeVision_1_1EasyImage.html#a6fa21bcc4e69362d4783a3a1c3760ea3) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyImage.html#a605ca77f9688330baf5d75098f2e0f32) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyImage.html#a8da446df8c256d9b792f9465479ece2c) method, the 16-bit work image must be cleared (all pixel values set to zero) using [`EasyImage::Copy()`](../../../doxygen_cpp/classeVision_1_1EasyImage.html#a9c428b9ad7dbe8199187da8b65cc9607) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyImage.html#a0c14aaef6449b5d314243fed7c31b77c) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyImage.html#a27e4c4305837a95925d0b06bd4d75c56) .

<a id="easyimage-noise-reduction-estimation"></a>

## Noise Estimation (Of an Image Compared to a Reference Image)

* To estimate the amount of noise, two or more successive images are required. In the simplest mode, two noisy images are compared. Other modes are available: if a noise-free image is available, it is compared to the noisy one; a noise-free image can also be built by temporal averaging.
  * [`EasyImage::RmsNoise`](../../../doxygen_cpp/classeVision_1_1EasyImage.html#a38f2c3b62f75f40be4f56ab96d9b8d5c) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyImage.html#a4894e4c83419fd727d673e220f9cc27c) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyImage.html#aab35de4bdeb0926e46e2d3bbe5af6762) computes the root-mean-square amplitude of noise, by comparing a given image to a reference image. This function supports flexible mask and an input mask argument. The reference image can be noiseless (obtained by suppressing the source of noise), or affected by a noise of the same distribution as the given image.
  * [`EasyImage::SignalNoiseRatio`](../../../doxygen_cpp/classeVision_1_1EasyImage.html#aa2c8d950cfac7850e725cb6bbf29cc06) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyImage.html#ab9f02d0d1e2463973f1232d0952cbd2a) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyImage.html#a9b3db59da1522cee11850d828819987a) computes the signal-to-noise ratio, in dB, by comparing a given image to a reference image. This function supports flexible mask and an input mask argument. The reference image can be noiseless (obtained by suppressing the source of noise) or be affected by a noise of the same distribution as the given image.
* **Signal amplitude** is the sum of the squared pixel gray-level values.
* **Noise amplitude** is the sum of the squared difference between the pixel gray-level values of the given image and the reference.

<a id="easyimage-noise-reduction-quick-links"></a>

## See Also

Easy to understand, ready to copy code snippets.

Convolution-based low-pass filters for reducing uniform noise.

Morphological operations and median filtering for removing impulse noise.

Segment images into foreground and background after denoising.
