albumentations.augmentations.pixel.noise


Add uniform, Gaussian, Laplace, or beta-distributed noise in constant, per-pixel, channel-shared, or randomly localized rectangular patch modes.

AdditiveNoiseclass

AdditiveNoise(
    noise_type: 'uniform' | 'gaussian' | 'laplace' | 'beta' = uniform,
    spatial_mode: 'constant' | 'per_pixel' | 'shared' | 'patch' = constant,
    noise_params: dict[str, Any] | None,
    p: float = 0.5,
    patch_count_range: tuple[int, int] = (1, 1),
    patch_height_range: tuple[float, float] = (0.1, 1.0),
    patch_width_range: tuple[float, float] = (0.1, 1.0),
    per_channel: bool = False
)

Add uniform, Gaussian, Laplace, or beta-distributed noise in constant, per-pixel, channel-shared, or randomly localized rectangular patch modes. Noise can be constant per channel, independent per pixel and channel, shared across channels, or localized inside one or more randomly sampled rectangular patches. Patch-localized noise is useful when spatially restricted corruption should improve robustness without perturbing the complete image.

Parameters

NameTypeDefaultDescription
noise_type
One of:
  • 'uniform'
  • 'gaussian'
  • 'laplace'
  • 'beta'
uniformNoise distribution. Default: "uniform".
spatial_mode
One of:
  • 'constant'
  • 'per_pixel'
  • 'shared'
  • 'patch'
constantSpatial sampling mode. Default: "constant". - `"constant"` samples one value per channel. - `"per_pixel"` samples each pixel and channel independently. - `"shared"` samples one spatial map and shares it across channels. - `"patch"` samples noise only inside random rectangular patches.
noise_params
One of:
  • dict[str, Any]
  • None
-Parameters for the chosen noise distribution. Must match the noise_type: uniform: ranges: list[tuple[float, float]] List of (min, max) ranges for each channel. Each range must be in [-1, 1]. If only one range is provided, it will be used for all channels. [(-0.2, 0.2)] # Same range for all channels [(-0.2, 0.2), (-0.1, 0.1), (-0.1, 0.1)] # Different ranges for RGB gaussian: mean_range: tuple[float, float], default (0.0, 0.0) Range for sampling mean value, in [-1, 1] std_range: tuple[float, float], default (0.1, 0.1) Range for sampling standard deviation, in [0, 1] laplace: mean_range: tuple[float, float], default (0.0, 0.0) Range for sampling location parameter, in [-1, 1] scale_range: tuple[float, float], default (0.1, 0.1) Range for sampling scale parameter, in [0, 1] beta: alpha_range: tuple[float, float], default (0.5, 1.5) Value < 1 = U-shaped, Value > 1 = Bell-shaped Range for sampling first shape parameter, in (0, inf) beta_range: tuple[float, float], default (0.5, 1.5) Value < 1 = U-shaped, Value > 1 = Bell-shaped Range for sampling second shape parameter, in (0, inf) scale_range: tuple[float, float], default (0.1, 0.3) Smaller scale for subtler noise Range for sampling output scale, in [0, 1]
pfloat0.5Probability of applying the transform. Default: 0.5.
patch_count_rangetuple[int, int](1, 1)Inclusive range for the number of patches when `spatial_mode="patch"`. Default: (1, 1).
patch_height_rangetuple[float, float](0.1, 1.0)Patch height as a fraction of image height. Values must be in `(0, 1]`. Default: (0.1, 1.0).
patch_width_rangetuple[float, float](0.1, 1.0)Patch width as a fraction of image width. Values must be in `(0, 1]`. Default: (0.1, 1.0).
per_channelboolFalseWhen `spatial_mode="patch"`, whether to sample independent noise for every channel. If False, the same noise is shared across channels. Default: False.

Examples

>>> import numpy as np
>>> import albumentations as A
>>> image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
>>> transform = A.Compose(
...     [
...         A.AdditiveNoise(
...             noise_type="gaussian",
...             spatial_mode="patch",
...             noise_params={"mean_range": (0.0, 0.0), "std_range": (0.05, 0.15)},
...             patch_count_range=(1, 3),
...             patch_height_range=(0.1, 0.4),
...             patch_width_range=(0.1, 0.4),
...             p=1.0,
...         ),
...     ],
...     seed=137,
... )
>>> noisy_image = transform(image=image)["image"]

Notes

- Patch positions and sizes are shared across channels. `per_channel` controls only the sampled noise values. - Overlapping patches are processed in order, and later patch noise replaces earlier noise in the overlap. - Image batches and volume slices receive the same sampled patch program, matching the existing batch behavior. - All noise is generated in normalized units and scaled by the image dtype maximum.

References

  • [{'description': 'Patch Gaussian', 'source': 'Improving Generalization of Convolutional Neural Networks without Encouraging Invariance: https://openreview.net/forum?id=HkxWXkStDB'}]

FilmGrainclass

FilmGrain(
    intensity_range: tuple[float, float] = (0.1, 0.3),
    grain_size_range: tuple[int, int] = (1, 3),
    p: float = 0.5
)

Analog film grain: luminance-dependent, spatially correlated noise. Distinct from i.i.d. GaussNoise or ShotNoise. Use for vintage or film-like augmentation. Unlike GaussNoise or ShotNoise, film grain is: - Luminance-dependent: darker areas show more visible grain - Spatially correlated: grain is clumped, not i.i.d. per-pixel - Optionally chromatic: separate grain patterns per channel

Parameters

NameTypeDefaultDescription
intensity_rangetuple[float, float](0.1, 0.3)Range for grain intensity. Higher values give more prominent grain. Default: (0.1, 0.3).
grain_size_rangetuple[int, int](1, 3)Grain resolution as divisor of image size. 1 = full resolution (fine); larger = coarser, more clumped. Default: (1, 3).
pfloat0.5Probability of applying the transform. Default: 0.5.

Examples

>>> import numpy as np
>>> import albumentations as A
>>> image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
>>>
>>> transform = A.FilmGrain(intensity_range=(0.1, 0.3), grain_size_range=(1, 3), p=1.0)
>>> result = transform(image=image)["image"]

Notes

- Grain is generated at lower resolution and upscaled → spatial correlation (clumping) like real film. - Visibility modulated by inverse luminance; darker regions show more grain (silver halide-like behavior).

GaussNoiseclass

GaussNoise(
    std_range: tuple[float, float] = (0.2, 0.44),
    mean_range: tuple[float, float] = (0.0, 0.0),
    per_channel: bool = False,
    p: float = 0.5
)

Add Gaussian (normal) noise to the image. i.i.d. per pixel (or per block if scaled). Use for robustness to sensor or transmission noise. Noise standard deviation and mean are sampled from configurable ranges and scaled to image dtype (255 for uint8, 1.0 for float32). Optional per-channel sampling and lower-resolution noise for speed.

Parameters

NameTypeDefaultDescription
std_rangetuple[float, float](0.2, 0.44)Range for noise standard deviation as a fraction of the max value (255 for uint8, 1.0 for float32). In [0, 1]. Default: (0.2, 0.44).
mean_rangetuple[float, float](0.0, 0.0)Range for noise mean as a fraction of max. In [-1, 1]. Default: (0.0, 0.0).
per_channelboolFalseIf True, sample noise per channel; else same noise for all. Default: False.
pfloat0.5Probability of applying the transform. Default: 0.5.

Examples

>>> import numpy as np
>>> import albumentations as A
>>> image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
>>>
>>> transform = A.GaussNoise(std_range=(0.1, 0.2), p=1.0)
>>> noisy_image = transform(image=image)["image"]

Notes

- std_range and mean_range are in [0, 1] / [-1, 1]; scaled by 255 (uint8) or used directly (float32). - per_channel=False: faster, same noise on all channels (grayscale-like on RGB). - per_channel=True: different noise per channel (colored noise).

ISONoiseclass

ISONoise(
    color_shift_range: tuple[float, float] = (0.01, 0.05),
    intensity_range: tuple[float, float] = (0.1, 0.5),
    p: float = 0.5
)

Add camera-sensor-like noise scaling with intensity (high ISO), useful for low-light or camera noise simulation. See `color_shift_range` and `intensity_range`. This transform adds random noise to an image, mimicking the effect of using high ISO settings in digital photography. It simulates two main components of ISO noise: 1. Color noise: random shifts in color hue 2. Luminance noise: random variations in pixel intensity

Parameters

NameTypeDefaultDescription
color_shift_rangetuple[float, float](0.01, 0.05)Range for changing color hue. Values should be in the range [0, 1], where 1 represents a full 360° hue rotation. Default: (0.01, 0.05)
intensity_rangetuple[float, float](0.1, 0.5)Range for the noise intensity. Higher values increase the strength of both color and luminance noise. Default: (0.1, 0.5)
pfloat0.5Probability of applying the transform. Default: 0.5

Examples

>>> import numpy as np
>>> import albumentations as A
>>> image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
>>> transform = A.ISONoise(color_shift_range=(0.01, 0.05), intensity_range=(0.1, 0.5), p=0.5)
>>> result = transform(image=image)
>>> noisy_image = result["image"]

Notes

- This transform only works with RGB images. It will raise a TypeError if applied to non-RGB images. - The color shift is applied in the HSV color space, affecting the hue channel. - Luminance noise is added to all channels independently. - This transform can be useful for data augmentation in low-light scenarios or when training models to be robust against noisy inputs.

References

  • [{'description': 'ISO noise in digital photography', 'source': 'https://en.wikipedia.org/wiki/Image_noise#In_digital_cameras'}]

KSpaceSpikeNoiseclass

KSpaceSpikeNoise(
    num_spikes_range: tuple[int, int] = (1, 5),
    intensity_range: tuple[float, float] = (0.1, 0.5),
    per_channel: bool = False,
    p: float = 0.5
)

Inject point spikes into the MRI k-space spectrum and reconstruct the image or volume, producing structured stripes typical of acquisition failures. K-space spike artifacts arise from isolated high-energy points in the Fourier representation of MRI data (e.g. scanner spikes, radio-frequency interference). Each sampled spike adds a real amplitude at its frequency and at the conjugate mirror, keeping the spectrum Hermitian so the reconstruction is real.

Parameters

NameTypeDefaultDescription
num_spikes_rangetuple[int, int](1, 5)Inclusive range for the number of spikes sampled per invocation. Zero spikes is an exact identity. Default: (1, 5).
intensity_rangetuple[float, float](0.1, 0.5)Range for the spike amplitude as a fraction of the spectrum maximum magnitude. Zero is an exact identity. Default: (0.1, 0.5).
per_channelboolFalseIf True, sample independent spike locations and amplitudes for each channel. If False, share one set of spikes across all channels. Default: False.
pfloat0.5Probability of applying the transform. Default: 0.5.

Examples

>>> import numpy as np
>>> import albumentations as A
>>> image = np.random.randint(0, 256, (128, 128, 3), dtype=np.uint8)
>>> transform = A.Compose(
...     [A.KSpaceSpikeNoise(num_spikes_range=(2, 4), intensity_range=(0.1, 0.3), p=1.0)],
...     seed=137,
... )
>>> spiked = transform(image=image)["image"]

Notes

- The Fourier transform is computed over spatial axes only; batch and channel dimensions are excluded. Spikes are injected into one transform-domain representation and a single inverse transform reconstructs the output. - Each spike injects a real amplitude `intensity * max|F|` at the sampled bin and at its conjugate mirror, so the half-spectrum stays Hermitian and the reconstruction is real without discarding imaginary parts. Self-conjugate bins (DC and the Nyquist bin of even axes) are injected once. - Spikes are uniform over the full frequency grid, including DC. A spike at DC shifts the global mean rather than creating stripes; this is intentional and documented. - A spike of relative amplitude `i` turns a flat field of value `c` into a cosine pattern of amplitude `2 * i * c` along the spike's frequency direction. - One spike realization is sampled per transform invocation and reused across all channels (shared mode), all images in a batch, and the whole volume as a single 3D transform. - uint8 inputs are processed as float32 in [0, 1] and converted back with rounding, so outputs stay within [0, 255]; float32 outputs are clipped to [0, 1]. - This differs from image-space impulse noise (SaltAndPepper), which replaces individual pixels, and from RingingOvershoot, which convolves in the image domain.

References

  • [{'description': 'TorchIO RandomSpike', 'source': 'https://docs.torchio.org/2.0/reference/transforms/spike/'}, {'description': 'TorchIO paper', 'source': 'https://www.sciencedirect.com/science/article/pii/S0169260721003102'}]

MultiplicativeNoiseclass

MultiplicativeNoise(
    multiplier: tuple[float, float] = (0.9, 1.1),
    per_channel: bool = False,
    elementwise: bool = False,
    p: float = 0.5
)

Multiply image by random per-pixel or per-channel factor. multiplier_range controls strength. Simulates illumination or gain variation; preserves zeros. This transform multiplies each pixel in the image by a random value or array of values, effectively creating a noise pattern that scales with the image intensity.

Parameters

NameTypeDefaultDescription
multipliertuple[float, float](0.9, 1.1)The range for the random multiplier. Defines the range from which the multiplier is sampled. Default: (0.9, 1.1)
per_channelboolFalseIf True, use a different random multiplier for each channel. If False, use the same multiplier for all channels. Setting this to False is slightly faster. Default: False
elementwiseboolFalseIf True, generates a unique multiplier for each pixel. If False, generates a single multiplier (or one per channel if per_channel=True). Default: False
pfloat0.5Probability of applying the transform. Default: 0.5

Examples

>>> import numpy as np
>>> import albumentations as A
>>> image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
>>> transform = A.MultiplicativeNoise(multiplier=(0.9, 1.1), per_channel=True, p=1.0)
>>> result = transform(image=image)
>>> noisy_image = result["image"]

Notes

- When elementwise=False and per_channel=False, a single multiplier is applied to the entire image. - When elementwise=False and per_channel=True, each channel gets a different multiplier. - When elementwise=True and per_channel=False, each pixel gets the same multiplier across all channels. - When elementwise=True and per_channel=True, each pixel in each channel gets a unique multiplier. - Setting per_channel=False is slightly faster, especially for larger images. - This transform can be used to simulate various lighting conditions or to create noise that scales with image intensity.

References

  • [{'description': 'Multiplicative noise', 'source': 'https://en.wikipedia.org/wiki/Multiplicative_noise'}]

RicianNoiseclass

RicianNoise(
    std_range: tuple[float, float] = (0.05, 0.15),
    per_channel: bool = False,
    p: float = 0.5
)

Simulate MRI magnitude reconstruction with Gaussian real and imaginary components, yielding Rician noise and a positive low-signal noise floor. The transform computes sqrt((signal + n_real)^2 + n_imag^2). Unlike additive Gaussian noise, this model remains biased upward at low signal-to-noise ratios, matching magnitude MRI reconstruction.

Parameters

NameTypeDefaultDescription
std_rangetuple[float, float](0.05, 0.15)Nondecreasing range in [0, 1] for the Gaussian component standard deviation as a fraction of the dtype range. Default: (0.05, 0.15).
per_channelboolFalseIf True, sample independent real and imaginary fields for each channel. If False, share one pair of fields across channels. Default: False.
pfloat0.5Probability of applying the transform. Default: 0.5.

Examples

>>> import albumentations as A
>>> import numpy as np
>>> image = np.random.default_rng(137).integers(0, 256, (100, 100, 3), dtype=np.uint8)
>>> transform = A.RicianNoise(std_range=(0.05, 0.15), p=1.0)
>>> noisy_image = transform(image=image)["image"]

Notes

- Volumes receive one independently sampled full-depth field rather than a slice-wise image batch. - A sampled standard deviation of zero is an exact identity.

References

  • [{'description': 'Gudbjartsson & Patz (1995)', 'source': 'https://doi.org/10.1002/mrm.1910340618'}]

SaltAndPepperclass

SaltAndPepper(
    amount_range: tuple[float, float] = (0.01, 0.06),
    salt_vs_pepper_range: tuple[float, float] = (0.4, 0.6),
    p: float = 0.5
)

Apply salt-and-pepper (impulse) noise: randomly set pixels to min or max with density and ratio controlled by `amount_range` and `salt_vs_pepper_range`. Salt and pepper noise is a form of impulse noise that randomly sets pixels to either maximum value (salt) or minimum value (pepper). The amount and proportion of salt vs pepper can be controlled. The same noise mask is applied to all channels of the image to preserve color consistency.

Parameters

NameTypeDefaultDescription
amount_rangetuple[float, float](0.01, 0.06)Range for total amount of noise (both salt and pepper). Values between 0 and 1. For example: - 0.05 means 5% of all pixels will be replaced with noise - (0.01, 0.06) will sample amount uniformly from 1% to 6% Default: (0.01, 0.06)
salt_vs_pepper_rangetuple[float, float](0.4, 0.6)Range for ratio of salt (white) vs pepper (black) noise. Values between 0 and 1. For example: - 0.5 means equal amounts of salt and pepper - 0.7 means 70% of noisy pixels will be salt, 30% pepper - (0.4, 0.6) will sample ratio uniformly from 40% to 60% Default: (0.4, 0.6)
pfloat0.5Probability of applying the transform. Default: 0.5.

Examples

>>> import albumentations as A
>>> import numpy as np

# Apply salt and pepper noise with default parameters
>>> transform = A.SaltAndPepper(p=1.0)
>>> noisy_image = transform(image=image)["image"]

# Heavy noise with more salt than pepper
>>> transform = A.SaltAndPepper(
...     amount_range=(0.1, 0.2),         # 10-20% of pixels will be noisy
...     salt_vs_pepper_range=(0.7, 0.9), # 70-90% of noise will be salt
...     p=1.0
... )
>>> noisy_image = transform(image=image)["image"]

Notes

- Salt noise sets pixels to maximum value (255 for uint8, 1.0 for float32) - Pepper noise sets pixels to 0 - The noise mask is generated once and applied to all channels to maintain color consistency (i.e., if a pixel is set to salt, all its color channels will be set to maximum value) - The exact number of affected pixels matches the specified amount as masks are generated without overlap

References

  • [{'description': 'Digital Image Processing', 'source': 'Rafael C. Gonzalez and Richard E. Woods, 4th Edition, Chapter 5: Image Restoration and Reconstruction.'}, {'description': 'Fundamentals of Digital Image Processing', 'source': 'A. K. Jain, Chapter 7: Image Degradation and Restoration.'}, {'description': 'Salt and pepper noise', 'source': 'https://en.wikipedia.org/wiki/Salt-and-pepper_noise'}]

ShotNoiseclass

ShotNoise(
    scale_range: tuple[float, float] = (0.1, 0.3),
    p: float = 0.5
)

Shot noise (Poisson) in linear light space. Sensor-realistic; use for low-light or photon-limited imaging and camera simulation. Simulates photon-counting: convert to linear space (gamma removed), treat pixel values as expected photon counts, sample from Poisson, convert back. Variance equals mean in linear space; brighter regions have more absolute noise, less relative.

Parameters

NameTypeDefaultDescription
scale_rangetuple[float, float](0.1, 0.3)Reciprocal of photons per unit intensity. Higher = more noise. e.g. 0.1 ≈ low, 1.0 ≈ moderate, 10.0 ≈ high. Default: (0.1, 0.3).
pfloat0.5Probability of applying the transform. Default: 0.5.

Examples

>>> import numpy as np
>>> import albumentations as A
>>> image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
>>>
>>> transform = A.ShotNoise(scale_range=(0.1, 1.0), p=1.0)
>>> noisy_image = transform(image=image)["image"]

Notes

- Pipeline: linear space (gamma = 2.2), Poisson sample, back to display space. - Preserves mean intensity. Per-pixel, per-channel independent.

References

  • [{'description': 'Shot noise', 'source': 'https://en.wikipedia.org/wiki/Shot_noise'}, {'description': 'Original paper', 'source': 'https://doi.org/10.1002/andp.19183622304 (Schottky, 1918)'}, {'description': 'Poisson process', 'source': 'https://en.wikipedia.org/wiki/Poisson_point_process'}, {'description': 'Gamma correction', 'source': 'https://en.wikipedia.org/wiki/Gamma_correction'}]

StochasticConvolutionclass

StochasticConvolution(
    kernel_range: tuple[int, int] = (3, 7),
    strength_range: tuple[float, float] = (0.0, 1.0),
    per_channel: bool = False,
    border_mode: 0 | 1 | 2 | 4 = 4,
    p: float = 0.5
)

Apply a stochastic identity-centered convolution kernel with configurable spectral strength and channel sharing for images and volumes. The kernel is a discrete impulse plus a zero-mean Gaussian field. `kernel_range` controls the odd side length `K` (the spectral resolution in PRIME), while `strength_range` controls the perturbation energy. The random field is scaled by `strength / K` so the expected perturbation energy remains comparable across kernel sizes.

Parameters

NameTypeDefaultDescription
kernel_rangetuple[int, int](3, 7)Inclusive odd range for the square kernel side length. Values must be greater than or equal to 3. Default: (3, 7).
strength_rangetuple[float, float](0.0, 1.0)Non-negative range for the random field strength. Zero is an exact identity. Default: (0.0, 1.0).
per_channelboolFalseIf True, sample an independent kernel for each channel. If False, share one kernel across all channels. Default: False.
border_mode
One of:
  • 0
  • 1
  • 2
  • 4
4OpenCV border policy. Supported values are constant, replicate, reflect, and reflect-101; wrap is rejected because it is not supported by the convolution backend. Default: `cv2.BORDER_REFLECT_101`.
pfloat0.5Probability of applying the transform. Default: 0.5.

Examples

>>> import numpy as np
>>> import albumentations as A
>>> import cv2
>>> image = np.random.default_rng(137).random((128, 128, 3), dtype=np.float32)
>>> transform = A.Compose(
...     [
...         A.StochasticConvolution(
...             kernel_range=(3, 7),
...             strength_range=(0.05, 0.25),
...             border_mode=cv2.BORDER_REFLECT_101,
...             p=1.0,
...         ),
...     ],
...     seed=137,
... )
>>> transformed = transform(image=image)["image"]

Use `per_channel=True` for independent spectral perturbations, or `strength_range=(0.0, 0.0)` for an
exact identity while keeping the transform in a pipeline.

Notes

- The random weights are not normalized or mean-subtracted. They may be signed, and the realized DC gain is the sampled kernel sum (with expected gain 1). - `cv2.BORDER_CONSTANT` uses zero padding, matching the PRIME reference implementation. The default reflect-101 border is the project-wide image-friendly choice. - One kernel realization is sampled per transform invocation and reused for every image in a batch and every depth slice in a volume. - Applied configuration records the sampled scalar values for the range fields and remains runnable after JSON transport. The in-memory replay path retains the realized kernel through transform parameters.

References

  • [{'description': 'PRIME issue', 'source': 'https://github.com/albumentations-team/AlbumentationsX/issues/330'}, {'description': 'PRIME randomized-filter construction', 'source': 'https://github.com/amodas/PRIME-augmentations/blob/main/utils/rand_filter.py'}]