123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 |
- """
- Noise filters to apply on images
- """
- # main imports
- import numpy as np
- import random
- def _normalise(x):
- if isinstance(x, np.ndarray):
- return np.array(list(map(_normalise, x)))
- if x > 255:
- return 255
- if x < 0:
- return 0
- return x
- def _global_noise_filter(image, generator, updator, identical=False):
- """White noise filter to apply on image
- Args:
- image: image used as input (2D or 3D image representation)
- generator: lambda function used to generate random numpy array with specific distribution
- updator: lambda function used to update pixel value
- identical: keep or not identical noise distribution for each canal if RGB Image (default False)
- Returns:
- 2D Numpy array with specified noise applied
- Example:
- >>> from ipfml.filters.noise import _global_noise_filter as gf
- >>> import numpy as np
- >>> image = np.random.uniform(0, 255, 10000).reshape((100, 100))
- >>> generator = lambda h, w: np.random.uniform(-0.5, 0.5, (h, w))
- >>> n = 10
- >>> k = 0.2
- >>> updator = lambda x, noise: x + n * k * noise
- >>> noisy_image = gf(image, generator, updator)
- >>> noisy_image.shape
- (100, 100)
- """
- image_array = np.asarray(image)
- nb_chanel = 1
- if image_array.ndim != 3:
- height, width = image_array.shape
- else:
- height, width, nb_chanel = image_array.shape
- if nb_chanel == 1 or identical:
- noise_filter = generator(height, width)
- # final output numpy array
- output_array = []
- # check number of chanel
- if nb_chanel == 1:
- noisy_image = np.array(list(map(updator, image_array, noise_filter)))
- # normalise values
- return np.array(list(map(_normalise, noisy_image)), 'uint8')
- else:
- # final output numpy array
- output_array = []
- for chanel in range(0, nb_chanel):
- # getting flatten information from image and noise
- image_array_chanel = image_array[:, :, chanel]
- # redefine noise if necessary
- if not identical:
- noise_filter = generator(height, width)
- # compute new pixel value
- # x + n * k * white_noise_filter[i] as example
- noisy_image = np.array(
- list(map(updator, image_array_chanel, noise_filter)))
- # normalise values
- noisy_image = np.array(list(map(_normalise, noisy_image)), 'uint8')
- # in order to concatenate output array
- noisy_image = noisy_image[:, :, np.newaxis]
- # append new chanel
- output_array.append(noisy_image)
- # concatenate RGB image
- output_array = np.concatenate(output_array, axis=2)
- return output_array
- def white_noise(image,
- n,
- identical=False,
- distribution_interval=(-0.5, 0.5),
- k=0.2):
- """White noise filter to apply on image
- Args:
- image: image used as input (2D or 3D image representation)
- n: used to set importance of noise [1, 999]
- identical: keep or not identical noise distribution for each canal if RGB Image (default False)
- distribution_interval: set the distribution interval of normal law distribution (default (-0.5, 0.5))
- k: variable that specifies the amount of noise to be taken into account in the output image (default 0.2)
- Returns:
- 2D Numpy array with white noise applied
- Example:
- >>> from ipfml.filters.noise import white_noise
- >>> import numpy as np
- >>> image = np.random.uniform(0, 255, 10000).reshape((100, 100))
- >>> noisy_image = white_noise(image, 10)
- >>> noisy_image.shape
- (100, 100)
- """
- a, b = distribution_interval
- generator = lambda h, w: np.random.uniform(a, b, (h, w))
- updator = lambda x, noise: x + n * k * noise
- return _global_noise_filter(image, generator, updator, identical)
- def gaussian_noise(image,
- n,
- identical=False,
- distribution_interval=(0, 1),
- k=0.1):
- """Gaussian noise filter to apply on image
- Args:
- image: image used as input (2D or 3D image representation)
- n: used to set importance of noise [1, 999]
- identical: keep or not identical noise distribution for each canal if RGB Image (default False)
- distribution_interval: set the distribution interval of normal law distribution (default (0, 1))
- k: variable that specifies the amount of noise to be taken into account in the output image (default 0.1)
- Returns:
- 2D Numpy array with gaussian noise applied
- Example:
- >>> from ipfml.filters.noise import gaussian_noise
- >>> import numpy as np
- >>> image = np.random.uniform(0, 255, 10000).reshape((100, 100))
- >>> noisy_image = gaussian_noise(image, 10)
- >>> noisy_image.shape
- (100, 100)
- """
- a, b = distribution_interval
- generator = lambda h, w: np.random.normal(a, b, (h, w))
- updator = lambda x, noise: x + n * k * noise
- return _global_noise_filter(image, generator, updator, identical)
- def laplace_noise(image,
- n,
- identical=False,
- distribution_interval=(0, 1),
- k=0.1):
- """Laplace noise filter to apply on image
- Args:
- image: image used as input (2D or 3D image representation)
- n: used to set importance of noise [1, 999]
- identical: keep or not identical noise distribution for each canal if RGB Image (default False)
- distribution_interval: set the distribution interval of normal law distribution (default (0, 1))
- k: variable that specifies the amount of noise to be taken into account in the output image (default 0.1)
- Returns:
- 2D Numpay array with Laplace noise applied
- Example:
- >>> from ipfml.filters.noise import laplace_noise
- >>> import numpy as np
- >>> image = np.random.uniform(0, 255, 10000).reshape((100, 100))
- >>> noisy_image = laplace_noise(image, 10)
- >>> noisy_image.shape
- (100, 100)
- """
- a, b = distribution_interval
- generator = lambda h, w: np.random.laplace(a, b, (h, w))
- updator = lambda x, noise: x + n * k * noise
- return _global_noise_filter(image, generator, updator, identical)
- def cauchy_noise(image,
- n,
- identical=False,
- distribution_interval=(0, 1),
- k=0.0002):
- """Cauchy noise filter to apply on image
- Args:
- image: image used as input (2D or 3D image representation)
- n: used to set importance of noise [1, 999]
- identical: keep or not identical noise distribution for each canal if RGB Image (default False)
- distribution_interval: set the distribution interval of normal law distribution (default (0, 1))
- k: variable that specifies the amount of noise to be taken into account in the output image (default 0.0002)
- Returns:
- 2D Numpy array with Cauchy noise applied
- Example:
- >>> from ipfml.filters.noise import cauchy_noise
- >>> import numpy as np
- >>> image = np.random.uniform(0, 255, 10000).reshape((100, 100))
- >>> noisy_image = cauchy_noise(image, 10)
- >>> noisy_image.shape
- (100, 100)
- """
- a, b = distribution_interval
- generator = lambda h, w: np.random.standard_cauchy((h, w))
- updator = lambda x, noise: x + n * k * noise
- return _global_noise_filter(image, generator, updator, identical)
- def log_normal_noise(image,
- n,
- identical=False,
- distribution_interval=(0, 1),
- k=0.05):
- """Log-normal noise filter to apply on image
- Args:
- image: image used as input (2D or 3D image representation)
- n: used to set importance of noise [1, 999]
- identical: keep or not identical noise distribution for each canal if RGB Image (default False)
- distribution_interval: set the distribution interval of normal law distribution (default (0, 1))
- k: variable that specifies the amount of noise to be taken into account in the output image (default 0.05)
- Returns:
- 2D Numpy array with Log-normal noise applied
- Example:
- >>> from ipfml.filters.noise import log_normal_noise
- >>> import numpy as np
- >>> image = np.random.uniform(0, 255, 10000).reshape((100, 100))
- >>> noisy_image = log_normal_noise(image, 10)
- >>> noisy_image.shape
- (100, 100)
- """
- a, b = distribution_interval
- generator = lambda h, w: np.random.lognormal(a, b, (h, w))
- updator = lambda x, noise: x + n * k * noise
- return _global_noise_filter(image, generator, updator, identical)
- def mut_white_noise(image,
- n,
- identical=False,
- distribution_interval=(0, 1),
- k=0.002):
- """Multiplied White noise filter to apply on image
- Args:
- image: image used as input (2D or 3D image representation)
- n: used to set importance of noise [1, 999]
- identical: keep or not identical noise distribution for each canal if RGB Image (default False)
- distribution_interval: set the distribution interval of normal law distribution (default (0, 1))
- k: variable that specifies the amount of noise to be taken into account in the output image (default 0.002)
- Returns:
- 2D Numpy array with multiplied white noise applied
- Example:
- >>> from ipfml.filters.noise import mut_white_noise
- >>> import numpy as np
- >>> image = np.random.uniform(0, 255, 10000).reshape((100, 100))
- >>> noisy_image = mut_white_noise(image, 10)
- >>> noisy_image.shape
- (100, 100)
- """
- min_value = 1 - (k / 2)
- max_value = 1 + (k / 2)
- a, b = distribution_interval
- generator = lambda h, w: min_value + (np.random.uniform(a, b, (h, w)) * (max_value - min_value))
- updator = lambda x, noise: x * pow(noise, n)
- return _global_noise_filter(image, generator, updator, identical)
- def salt_pepper_noise(image, n, identical=False, p=0.1, k=0.5):
- """Pepper salt noise filter to apply on image
- Args:
- image: image used as input (2D or 3D image representation)
- n: used to set importance of noise [1, 999]
- identical: keep or not identical noise distribution for each canal if RGB Image (default False)
- p: probability to increase pixel value otherwise decrease it
- k: variable that specifies the amount of noise to be taken into account in the output image (default 0.5)
- Returns:
- 2D Numpy array with salt and pepper noise applied
- Example:
- >>> from ipfml.filters.noise import salt_pepper_noise
- >>> import numpy as np
- >>> image = np.random.uniform(0, 255, 10000).reshape((100, 100))
- >>> noisy_image = salt_pepper_noise(image, 10)
- >>> noisy_image.shape
- (100, 100)
- """
- def _generator(h, w):
- x = w * h
- nb_elem = int(p * x)
- elements = np.full(x, 0)
- elements[0:nb_elem] = 1
- np.random.shuffle(elements)
- return elements.reshape(h, w)
- image_array = np.array(image)
- if image_array.ndim == 3:
- height, width, _ = image_array.shape
- else:
- height, width = image_array.shape
- # need same random variable for each pixel value if identical
- if identical:
- gen = np.random.uniform(0, 1, height * width)
- for i in range(2):
- gen = np.insert(gen, 0, gen)
- gen = iter(gen)
- # here noise variable is boolean to update or not pixel value
- def _updator(x, noise):
- # apply specific changes to each value of 1D array
- if isinstance(x, np.ndarray):
- return np.array(list(map(_updator, x, noise)))
- # probabilty to increase or decrease pixel value
- if identical:
- rand = next(gen)
- else:
- rand = random.uniform(0, 1)
- if noise:
- if rand > 0.5:
- return x + n * k
- else:
- return x - n * k
- else:
- return x
- return _global_noise_filter(image, _generator, _updator, identical)
|