noise.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. import numpy as np
  2. import random
  3. from ipfml import processing
  4. def _normalise(x):
  5. if isinstance(x, np.ndarray):
  6. return np.array(list(map(_normalise, x)))
  7. if x > 255:
  8. return 255
  9. if x < 0:
  10. return 0
  11. return x
  12. def _global_noise_filter(image, generator, updator, identical=False):
  13. """White noise filter to apply on image
  14. Args:
  15. image: image used as input (2D or 3D image representation)
  16. generator: lambda function used to generate random numpy array with specific distribution
  17. updator: lambda function used to update pixel value
  18. identical: keep or not identical noise distribution for each canal if RGB Image (default False)
  19. Returns:
  20. 2D Numpy array with specified noise applied
  21. Example:
  22. >>> from ipfml.filters.noise import _global_noise_filter as gf
  23. >>> import numpy as np
  24. >>> image = np.random.uniform(0, 255, 10000).reshape((100, 100))
  25. >>> generator = lambda h, w: np.random.uniform(-0.5, 0.5, (h, w))
  26. >>> n = 10
  27. >>> k = 0.2
  28. >>> updator = lambda x, noise: x + n * k * noise
  29. >>> noisy_image = gf(image, generator, updator)
  30. >>> noisy_image.shape
  31. (100, 100)
  32. """
  33. image_array = np.asarray(image)
  34. nb_chanel = 1
  35. if image_array.ndim != 3:
  36. height, width = image_array.shape
  37. else:
  38. height, width, nb_chanel = image_array.shape
  39. if nb_chanel == 1 or identical:
  40. noise_filter = generator(height, width)
  41. # final output numpy array
  42. output_array = []
  43. # check number of chanel
  44. if nb_chanel == 1:
  45. noisy_image = np.array(list(map(updator, image_array, noise_filter)))
  46. # normalise values
  47. return np.array(list(map(_normalise, noisy_image)), 'uint8')
  48. else:
  49. # final output numpy array
  50. output_array = []
  51. for chanel in range(0, nb_chanel):
  52. # getting flatten information from image and noise
  53. image_array_chanel = image_array[:, :, chanel]
  54. # redefine noise if necessary
  55. if not identical:
  56. noise_filter = generator(height, width)
  57. # compute new pixel value
  58. # x + n * k * white_noise_filter[i] as example
  59. noisy_image = np.array(
  60. list(map(updator, image_array_chanel, noise_filter)))
  61. # normalise values
  62. noisy_image = np.array(list(map(_normalise, noisy_image)), 'uint8')
  63. # in order to concatenate output array
  64. noisy_image = noisy_image[:, :, np.newaxis]
  65. # append new chanel
  66. output_array.append(noisy_image)
  67. # concatenate RGB image
  68. output_array = np.concatenate(output_array, axis=2)
  69. return output_array
  70. def white_noise(image,
  71. n,
  72. identical=False,
  73. distribution_interval=(-0.5, 0.5),
  74. k=0.2):
  75. """White noise filter to apply on image
  76. Args:
  77. image: image used as input (2D or 3D image representation)
  78. n: used to set importance of noise [1, 999]
  79. identical: keep or not identical noise distribution for each canal if RGB Image (default False)
  80. distribution_interval: set the distribution interval of normal law distribution (default (-0.5, 0.5))
  81. k: variable that specifies the amount of noise to be taken into account in the output image (default 0.2)
  82. Returns:
  83. 2D Numpy array with white noise applied
  84. Example:
  85. >>> from ipfml.filters.noise import white_noise
  86. >>> import numpy as np
  87. >>> image = np.random.uniform(0, 255, 10000).reshape((100, 100))
  88. >>> noisy_image = white_noise(image, 10)
  89. >>> noisy_image.shape
  90. (100, 100)
  91. """
  92. a, b = distribution_interval
  93. generator = lambda h, w: np.random.uniform(a, b, (h, w))
  94. updator = lambda x, noise: x + n * k * noise
  95. return _global_noise_filter(image, generator, updator, identical)
  96. def gaussian_noise(image,
  97. n,
  98. identical=False,
  99. distribution_interval=(0, 1),
  100. k=0.1):
  101. """Gaussian noise filter to apply on image
  102. Args:
  103. image: image used as input (2D or 3D image representation)
  104. n: used to set importance of noise [1, 999]
  105. identical: keep or not identical noise distribution for each canal if RGB Image (default False)
  106. distribution_interval: set the distribution interval of normal law distribution (default (0, 1))
  107. k: variable that specifies the amount of noise to be taken into account in the output image (default 0.1)
  108. Returns:
  109. 2D Numpy array with gaussian noise applied
  110. Example:
  111. >>> from ipfml.filters.noise import gaussian_noise
  112. >>> import numpy as np
  113. >>> image = np.random.uniform(0, 255, 10000).reshape((100, 100))
  114. >>> noisy_image = gaussian_noise(image, 10)
  115. >>> noisy_image.shape
  116. (100, 100)
  117. """
  118. a, b = distribution_interval
  119. generator = lambda h, w: np.random.normal(a, b, (h, w))
  120. updator = lambda x, noise: x + n * k * noise
  121. return _global_noise_filter(image, generator, updator, identical)
  122. def laplace_noise(image,
  123. n,
  124. identical=False,
  125. distribution_interval=(0, 1),
  126. k=0.1):
  127. """Laplace noise filter to apply on image
  128. Args:
  129. image: image used as input (2D or 3D image representation)
  130. n: used to set importance of noise [1, 999]
  131. identical: keep or not identical noise distribution for each canal if RGB Image (default False)
  132. distribution_interval: set the distribution interval of normal law distribution (default (0, 1))
  133. k: variable that specifies the amount of noise to be taken into account in the output image (default 0.1)
  134. Returns:
  135. 2D Numpay array with Laplace noise applied
  136. Example:
  137. >>> from ipfml.filters.noise import laplace_noise
  138. >>> import numpy as np
  139. >>> image = np.random.uniform(0, 255, 10000).reshape((100, 100))
  140. >>> noisy_image = laplace_noise(image, 10)
  141. >>> noisy_image.shape
  142. (100, 100)
  143. """
  144. a, b = distribution_interval
  145. generator = lambda h, w: np.random.laplace(a, b, (h, w))
  146. updator = lambda x, noise: x + n * k * noise
  147. return _global_noise_filter(image, generator, updator, identical)
  148. def cauchy_noise(image,
  149. n,
  150. identical=False,
  151. distribution_interval=(0, 1),
  152. k=0.0002):
  153. """Cauchy noise filter to apply on image
  154. Args:
  155. image: image used as input (2D or 3D image representation)
  156. n: used to set importance of noise [1, 999]
  157. identical: keep or not identical noise distribution for each canal if RGB Image (default False)
  158. distribution_interval: set the distribution interval of normal law distribution (default (0, 1))
  159. k: variable that specifies the amount of noise to be taken into account in the output image (default 0.0002)
  160. Returns:
  161. 2D Numpy array with Cauchy noise applied
  162. Example:
  163. >>> from ipfml.filters.noise import cauchy_noise
  164. >>> import numpy as np
  165. >>> image = np.random.uniform(0, 255, 10000).reshape((100, 100))
  166. >>> noisy_image = cauchy_noise(image, 10)
  167. >>> noisy_image.shape
  168. (100, 100)
  169. """
  170. a, b = distribution_interval
  171. generator = lambda h, w: np.random.standard_cauchy((h, w))
  172. updator = lambda x, noise: x + n * k * noise
  173. return _global_noise_filter(image, generator, updator, identical)
  174. def log_normal_noise(image,
  175. n,
  176. identical=False,
  177. distribution_interval=(0, 1),
  178. k=0.05):
  179. """Log-normal noise filter to apply on image
  180. Args:
  181. image: image used as input (2D or 3D image representation)
  182. n: used to set importance of noise [1, 999]
  183. identical: keep or not identical noise distribution for each canal if RGB Image (default False)
  184. distribution_interval: set the distribution interval of normal law distribution (default (0, 1))
  185. k: variable that specifies the amount of noise to be taken into account in the output image (default 0.05)
  186. Returns:
  187. 2D Numpy array with Log-normal noise applied
  188. Example:
  189. >>> from ipfml.filters.noise import log_normal_noise
  190. >>> import numpy as np
  191. >>> image = np.random.uniform(0, 255, 10000).reshape((100, 100))
  192. >>> noisy_image = log_normal_noise(image, 10)
  193. >>> noisy_image.shape
  194. (100, 100)
  195. """
  196. a, b = distribution_interval
  197. generator = lambda h, w: np.random.lognormal(a, b, (h, w))
  198. updator = lambda x, noise: x + n * k * noise
  199. return _global_noise_filter(image, generator, updator, identical)
  200. def mut_white_noise(image,
  201. n,
  202. identical=False,
  203. distribution_interval=(0, 1),
  204. k=0.002):
  205. """Multiplied White noise filter to apply on image
  206. Args:
  207. image: image used as input (2D or 3D image representation)
  208. n: used to set importance of noise [1, 999]
  209. identical: keep or not identical noise distribution for each canal if RGB Image (default False)
  210. distribution_interval: set the distribution interval of normal law distribution (default (0, 1))
  211. k: variable that specifies the amount of noise to be taken into account in the output image (default 0.002)
  212. Returns:
  213. 2D Numpy array with multiplied white noise applied
  214. Example:
  215. >>> from ipfml.filters.noise import mut_white_noise
  216. >>> import numpy as np
  217. >>> image = np.random.uniform(0, 255, 10000).reshape((100, 100))
  218. >>> noisy_image = mut_white_noise(image, 10)
  219. >>> noisy_image.shape
  220. (100, 100)
  221. """
  222. min_value = 1 - (k/2);
  223. max_value = 1 + (k/2);
  224. a, b = distribution_interval
  225. generator = lambda h, w: min_value + (np.random.uniform(a, b, (h, w)) * (max_value - min_value))
  226. updator = lambda x, noise: x * pow(noise, n)
  227. return _global_noise_filter(image, generator, updator, identical)
  228. def salt_pepper_noise(image, n, identical=False, p=0.1, k=0.5):
  229. """Pepper salt noise filter to apply on image
  230. Args:
  231. image: image used as input (2D or 3D image representation)
  232. n: used to set importance of noise [1, 999]
  233. identical: keep or not identical noise distribution for each canal if RGB Image (default False)
  234. p: probability to increase pixel value otherwise decrease it
  235. k: variable that specifies the amount of noise to be taken into account in the output image (default 0.5)
  236. Returns:
  237. 2D Numpy array with salt and pepper noise applied
  238. Example:
  239. >>> from ipfml.filters.noise import salt_pepper_noise
  240. >>> import numpy as np
  241. >>> image = np.random.uniform(0, 255, 10000).reshape((100, 100))
  242. >>> noisy_image = salt_pepper_noise(image, 10)
  243. >>> noisy_image.shape
  244. (100, 100)
  245. """
  246. def _generator(h, w):
  247. x = w * h
  248. nb_elem = int(p * x)
  249. elements = np.full(x, 0)
  250. elements[0:nb_elem] = 1
  251. np.random.shuffle(elements)
  252. return elements.reshape(h, w)
  253. # here noise variable is boolean to update or not pixel value
  254. def _updator(x, noise):
  255. # apply specific changes to each value of 1D array
  256. if isinstance(x, np.ndarray):
  257. return np.array(list(map(_updator, x, noise)))
  258. # probabilty to increase or decrease pixel value
  259. rand = random.uniform(0, 1)
  260. if noise:
  261. if rand > 0.5:
  262. return x + n * k
  263. else:
  264. return x - n * k
  265. else:
  266. return x
  267. return _global_noise_filter(image, _generator, _updator, identical)