Transformation.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. # main imports
  2. import os
  3. import numpy as np
  4. # image processing imports
  5. from ipfml.processing import transform, compression
  6. from ipfml.processing import reconstruction
  7. from ipfml.filters import convolution, kernels
  8. from ipfml import utils
  9. import cv2
  10. from skimage.restoration import denoise_nl_means, estimate_sigma
  11. from PIL import Image
  12. # modules imports
  13. from ..utils import data as functions
  14. def _compute_relative_error(ref_sv, k_sv):
  15. ref = np.sqrt(np.sum(np.square(ref_sv)))
  16. k = np.sqrt(np.sum(np.square(k_sv)))
  17. return k / ref
  18. def _find_n_components(block, e=0.1):
  19. s = transform.get_LAB_L_SVD_s(block)
  20. errors = []
  21. found = False
  22. k_components = None
  23. for i in range(len(s)):
  24. #Ak = reconstruction.svd(img, [0, i])
  25. #error = compute_relative_error_matrix(A, Ak)
  26. error = _compute_relative_error(s, s[i:])
  27. errors.append(error)
  28. if error < e and not found:
  29. k_components = (i + 1)
  30. found = True
  31. return (k_components, errors)
  32. # Transformation class to store transformation method of image and get usefull information
  33. class Transformation():
  34. def __init__(self, _transformation, _param, _size):
  35. self.transformation = _transformation
  36. self.param = _param
  37. self.size = _size
  38. def getTransformedImage(self, img):
  39. if self.transformation == 'svd_reconstruction':
  40. begin, end = list(map(int, self.param.split(',')))
  41. h, w = list(map(int, self.size.split(',')))
  42. img_reconstructed = reconstruction.svd(img, [begin, end])
  43. data_array = np.array(img_reconstructed, 'uint8')
  44. img_array = Image.fromarray(data_array)
  45. img_array.thumbnail((h, w))
  46. data = np.array(img_array)
  47. if self.transformation == 'svd_reconstruction_dyn':
  48. epsilon, end = list(map(float, self.param.split(',')))
  49. h, w = list(map(int, self.size.split(',')))
  50. k, _ = _find_n_components(img, e=epsilon)
  51. img_reconstructed = reconstruction.svd(img, [k, int(end)])
  52. data_array = np.array(img_reconstructed, 'uint8')
  53. img_array = Image.fromarray(data_array)
  54. img_array.thumbnail((h, w))
  55. data = np.array(img_array)
  56. if self.transformation == 'ipca_reconstruction':
  57. n_components, batch_size = list(map(int, self.param.split(',')))
  58. h, w = list(map(int, self.size.split(',')))
  59. img_reconstructed = reconstruction.ipca(img, n_components, batch_size)
  60. data_array = np.array(img_reconstructed, 'uint8')
  61. img_array = Image.fromarray(data_array)
  62. img_array.thumbnail((h, w))
  63. data = np.array(img_array)
  64. if self.transformation == 'fast_ica_reconstruction':
  65. n_components = self.param
  66. h, w = list(map(int, self.size.split(',')))
  67. img_reconstructed = reconstruction.fast_ica(img, n_components)
  68. data_array = np.array(img_reconstructed, 'uint8')
  69. img_array = Image.fromarray(data_array)
  70. img_array.thumbnail((h, w))
  71. data = np.array(img_array)
  72. if self.transformation == 'sobel_based_filter':
  73. k_size, p_limit = list(map(int, self.param.split(',')))
  74. h, w = list(map(int, self.size.split(',')))
  75. lab_img = transform.get_LAB_L(img)
  76. weight, height = lab_img.shape
  77. sobelx = cv2.Sobel(lab_img, cv2.CV_64F, 1, 0, ksize=k_size)
  78. sobely = cv2.Sobel(lab_img, cv2.CV_64F, 0, 1,ksize=k_size)
  79. sobel_mag = np.array(np.hypot(sobelx, sobely), 'uint8') # magnitude
  80. sobel_mag_limit = functions.remove_pixel(sobel_mag, p_limit)
  81. # use distribution value of pixel to fill `0` values
  82. sobel_mag_limit_without_0 = [x for x in sobel_mag_limit.reshape((weight*height)) if x != 0]
  83. distribution = functions.distribution_from_data(sobel_mag_limit_without_0)
  84. min_value = int(min(sobel_mag_limit_without_0))
  85. l = lambda: functions.get_random_value(distribution) + min_value
  86. img_reconstructed = functions.fill_image_with_rand_value(sobel_mag_limit, l, 0)
  87. img_reconstructed_norm = utils.normalize_2D_arr(img_reconstructed)
  88. img_reconstructed_norm = np.array(img_reconstructed_norm*255, 'uint8')
  89. sobel_reconstructed = Image.fromarray(img_reconstructed_norm)
  90. sobel_reconstructed.thumbnail((h, w))
  91. data = np.array(sobel_reconstructed)
  92. if self.transformation == 'nl_mean_noise_mask':
  93. patch_size, patch_distance = list(map(int, self.param.split(',')))
  94. h, w = list(map(int, self.size.split(',')))
  95. img = np.array(img)
  96. sigma_est = np.mean(estimate_sigma(img, multichannel=True))
  97. patch_kw = dict(patch_size=patch_size, # 5x5 patches
  98. patch_distance=patch_distance, # 13x13 search area
  99. multichannel=True)
  100. # slow algorithm
  101. denoise = denoise_nl_means(img, h=0.8 * sigma_est, sigma=sigma_est,
  102. fast_mode=False,
  103. **patch_kw)
  104. denoise = np.array(denoise, 'uint8')
  105. noise_mask = np.abs(denoise - img)
  106. data_array = np.array(noise_mask, 'uint8')
  107. img_array = Image.fromarray(data_array)
  108. img_array.thumbnail((h, w))
  109. data = np.array(img_array)
  110. if self.transformation == 'static':
  111. # static content, we keep input as it is
  112. data = img
  113. return data
  114. def getTransformationPath(self):
  115. path = self.transformation
  116. if self.transformation == 'svd_reconstruction':
  117. begin, end = list(map(int, self.param.split(',')))
  118. w, h = list(map(int, self.size.split(',')))
  119. path = os.path.join(path, str(begin) + '_' + str(end) + '_S_' + str(w) + '_' + str(h))
  120. if self.transformation == 'svd_reconstruction_dyn':
  121. epsilon, end = list(map(float, self.param.split(',')))
  122. w, h = list(map(int, self.size.split(',')))
  123. path = os.path.join(path, str(epsilon) + '_' + str(int(end)) + '_S_' + str(w) + '_' + str(h))
  124. if self.transformation == 'ipca_reconstruction':
  125. n_components, batch_size = list(map(int, self.param.split(',')))
  126. w, h = list(map(int, self.size.split(',')))
  127. path = os.path.join(path, 'N' + str(n_components) + '_' + str(batch_size) + '_S_' + str(w) + '_' + str(h))
  128. if self.transformation == 'fast_ica_reconstruction':
  129. n_components = self.param
  130. w, h = list(map(int, self.size.split(',')))
  131. path = os.path.join(path, 'N' + str(n_components) + '_S_' + str(w) + '_' + str(h))
  132. if self.transformation == 'min_diff_filter':
  133. w_size, h_size, stride = list(map(int, self.param.split(',')))
  134. w, h = list(map(int, self.size.split(',')))
  135. path = os.path.join(path, 'W_' + str(w_size) + '_' + str(h_size) + '_Stride_' + str(stride) + '_S_' + str(w) + '_' + str(h))
  136. if self.transformation == 'sobel_based_filter':
  137. k_size, p_limit = list(map(int, self.param.split(',')))
  138. h, w = list(map(int, self.size.split(',')))
  139. path = os.path.join(path, 'K_' + str(k_size) + '_L' + str(p_limit) + '_S_' + str(w) + '_' + str(h))
  140. if self.transformation == 'nl_mean_noise_mask':
  141. patch_size, patch_distance = list(map(int, self.param.split(',')))
  142. h, w = list(map(int, self.size.split(',')))
  143. path = os.path.join(path, 'S' + str(patch_size) + '_D' + str(patch_distance) + '_S_' + str(w) + '_' + str(h))
  144. if self.transformation == 'static':
  145. # param contains image name to find for each scene
  146. path = self.param
  147. return path
  148. def getName(self):
  149. return self.transformation
  150. def getParam(self):
  151. return self.param
  152. def __str__( self ):
  153. return self.transformation + ' transformation with parameter : ' + self.param