noise.py 11 KB

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