processing.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. from PIL import Image
  2. from matplotlib import cm
  3. import random
  4. from skimage import color
  5. import numpy as np
  6. import ipfml.metrics as metrics
  7. import cv2
  8. from scipy import signal
  9. def get_LAB_L_SVD(image):
  10. """Returns Singular values from LAB L Image information
  11. Args:
  12. image: PIL Image or Numpy array
  13. Returns:
  14. U, s, V information obtained from SVD compression using Lab
  15. Usage:
  16. >>> from PIL import Image
  17. >>> from ipfml import processing
  18. >>> img = Image.open('./images/test_img.png')
  19. >>> U, s, V = processing.get_LAB_L_SVD(img)
  20. >>> U.shape
  21. (200, 200)
  22. >>> len(s)
  23. 200
  24. >>> V.shape
  25. (200, 200)
  26. """
  27. L = metrics.get_LAB_L(image)
  28. return metrics.get_SVD(L)
  29. def get_LAB_L_SVD_s(image):
  30. """Returns s (Singular values) SVD from L of LAB Image information
  31. Args:
  32. image: PIL Image or Numpy array
  33. Returns:
  34. vector of singular values
  35. Usage:
  36. >>> from PIL import Image
  37. >>> from ipfml import processing
  38. >>> img = Image.open('./images/test_img.png')
  39. >>> s = processing.get_LAB_L_SVD_s(img)
  40. >>> len(s)
  41. 200
  42. """
  43. L = metrics.get_LAB_L(image)
  44. return metrics.get_SVD_s(L)
  45. def get_LAB_L_SVD_U(image):
  46. """Returns U SVD from L of LAB Image information
  47. Args:
  48. image: PIL Image or Numpy array
  49. Returns:
  50. U matrix of SVD compression
  51. Usage:
  52. >>> from PIL import Image
  53. >>> from ipfml import processing
  54. >>> img = Image.open('./images/test_img.png')
  55. >>> U = processing.get_LAB_L_SVD_U(img)
  56. >>> U.shape
  57. (200, 200)
  58. """
  59. L = metrics.get_LAB_L(image)
  60. return metrics.get_SVD_U(L)
  61. def get_LAB_L_SVD_V(image):
  62. """Returns V SVD from L of LAB Image information
  63. Args:
  64. image: PIL Image or Numpy array
  65. Returns:
  66. V matrix of SVD compression
  67. Usage:
  68. >>> from PIL import Image
  69. >>> from ipfml import processing
  70. >>> img = Image.open('./images/test_img.png')
  71. >>> V = processing.get_LAB_L_SVD_V(img)
  72. >>> V.shape
  73. (200, 200)
  74. """
  75. L = metrics.get_LAB_L(image)
  76. return metrics.get_SVD_V(L)
  77. def divide_in_blocks(image, block_size, pil=True):
  78. '''Divide image into equal size blocks
  79. Args:
  80. image: PIL Image or Numpy array
  81. block: tuple (width, height) representing the size of each dimension of the block
  82. pil: block type returned (default True)
  83. Returns:
  84. list containing all 2D Numpy blocks (in RGB or not)
  85. Usage:
  86. >>> import Numpy as np
  87. >>> from PIL import Image
  88. >>> from ipfml import processing
  89. >>> from ipfml import metrics
  90. >>> image_values = np.random.randint(255, size=(800, 800, 3))
  91. >>> blocks = divide_in_blocks(image_values, (20, 20))
  92. >>> len(blocks)
  93. 1600
  94. >>> blocks[0].width
  95. 20
  96. >>> blocks[0].height
  97. 20
  98. >>> img_l = Image.open('./images/test_img.png')
  99. >>> L = metrics.get_LAB_L(img_l)
  100. >>> blocks_L = divide_in_blocks(L, (100, 100))
  101. >>> len(blocks_L)
  102. 4
  103. >>> blocks_L[0].width
  104. 100
  105. '''
  106. blocks = []
  107. mode = 'RGB'
  108. # convert in Numpy array
  109. image_array = np.array(image)
  110. # check dimension of input image
  111. if image_array.ndim != 3:
  112. mode = 'L'
  113. image_width, image_height = image_array.shape
  114. else:
  115. image_width, image_height, _ = image_array.shape
  116. # check size compatibility
  117. width, height = block_size
  118. if (image_width % width != 0):
  119. raise "Width size issue, block size not compatible"
  120. if (image_height % height != 0):
  121. raise "Height size issue, block size not compatible"
  122. nb_block_width = image_width / width
  123. nb_block_height = image_height / height
  124. for i in range(int(nb_block_width)):
  125. begin_x = i * width
  126. for j in range(int(nb_block_height)):
  127. begin_y = j * height
  128. # getting sub block information
  129. current_block = image_array[begin_x:(begin_x + width), begin_y:(
  130. begin_y + height)]
  131. if pil:
  132. blocks.append(
  133. Image.fromarray(current_block.astype('uint8'), mode))
  134. else:
  135. blocks.append(current_block)
  136. return blocks
  137. def normalize_arr(arr):
  138. '''Normalize data of 1D array shape
  139. Args:
  140. arr: array data of 1D shape
  141. Returns:
  142. Normalized 1D array
  143. Usage:
  144. >>> from ipfml import processing
  145. >>> import Numpy as np
  146. >>> arr = np.arange(11)
  147. >>> arr_normalized = processing.normalize_arr(arr)
  148. >>> arr_normalized[1]
  149. 0.1
  150. '''
  151. output_arr = []
  152. max_value = max(arr)
  153. min_value = min(arr)
  154. for v in arr:
  155. output_arr.append((v - min_value) / (max_value - min_value))
  156. return output_arr
  157. def normalize_arr_with_range(arr, min, max):
  158. '''Normalize data of 1D array shape
  159. Args:
  160. arr: array data of 1D shape
  161. Returns:
  162. Normalized 1D Numpy array
  163. Usage:
  164. >>> from ipfml import processing
  165. >>> import Numpy as np
  166. >>> arr = np.arange(11)
  167. >>> arr_normalized = processing.normalize_arr_with_range(arr, 0, 20)
  168. >>> arr_normalized[1]
  169. 0.05
  170. '''
  171. output_arr = []
  172. for v in arr:
  173. output_arr.append((v - min) / (max - min))
  174. return output_arr
  175. def normalize_2D_arr(arr):
  176. """Return array normalize from its min and max values
  177. Args:
  178. arr: 2D Numpy array
  179. Returns:
  180. Normalized 2D Numpy array
  181. Usage:
  182. >>> from PIL import Image
  183. >>> from ipfml import processing
  184. >>> img = Image.open('./images/test_img.png')
  185. >>> img_mscn = processing.rgb_to_mscn(img)
  186. >>> img_normalized = processing.normalize_2D_arr(img_mscn)
  187. >>> img_normalized.shape
  188. (200, 200)
  189. """
  190. # getting min and max value from 2D array
  191. max_value = arr.max(axis=1).max()
  192. min_value = arr.min(axis=1).min()
  193. # normalize each row
  194. output_array = []
  195. width, height = arr.shape
  196. for row_index in range(0, height):
  197. values = arr[row_index, :]
  198. output_array.append(
  199. normalize_arr_with_range(values, min_value, max_value))
  200. return np.asarray(output_array)
  201. def rgb_to_mscn(image):
  202. """Convert RGB Image into Mean Subtracted Contrast Normalized (MSCN)
  203. Args:
  204. image: 3D RGB image Numpy array or PIL RGB image
  205. Returns:
  206. 2D Numpy array with MSCN information
  207. Usage:
  208. >>> from PIL import Image
  209. >>> from ipfml import processing
  210. >>> img = Image.open('./images/test_img.png')
  211. >>> img_mscn = processing.rgb_to_mscn(img)
  212. >>> img_mscn.shape
  213. (200, 200)
  214. """
  215. # check if PIL image or not
  216. img_arr = np.array(image)
  217. # convert rgb image to gray
  218. im = np.array(color.rgb2gray(img_arr) * 255, 'uint8')
  219. return metrics.gray_to_mscn(im)
  220. def rgb_to_grey_low_bits(image, nb_bits=4):
  221. """Convert RGB Image into grey image using only 4 low bits values
  222. Args:
  223. image: 3D RGB image Numpy array or PIL RGB image
  224. nb_bits: optional parameter which indicates the number of bits to keep (default 4)
  225. Returns:
  226. 2D Numpy array with low bits information kept
  227. Usage:
  228. >>> from PIL import Image
  229. >>> from ipfml import processing
  230. >>> img = Image.open('./images/test_img.png')
  231. >>> low_bits_grey_img = processing.rgb_to_grey_low_bits(img, 5)
  232. >>> low_bits_grey_img.shape
  233. (200, 200)
  234. """
  235. img_arr = np.array(image)
  236. grey_block = np.array(color.rgb2gray(img_arr) * 255, 'uint8')
  237. return metrics.get_low_bits_img(grey_block, nb_bits)
  238. def rgb_to_LAB_L_low_bits(image, nb_bits=4):
  239. """Convert RGB Image into Lab L channel image using only 4 low bits values
  240. Args:
  241. image: 3D RGB image Numpy array or PIL RGB image
  242. nb_bits: optional parameter which indicates the number of bits to keep (default 4)
  243. Returns:
  244. 2D Numpy array with low bits information kept
  245. Usage:
  246. >>> from PIL import Image
  247. >>> from ipfml import processing
  248. >>> img = Image.open('./images/test_img.png')
  249. >>> low_bits_Lab_l_img = processing.rgb_to_LAB_L_low_bits(img, 5)
  250. >>> low_bits_Lab_l_img.shape
  251. (200, 200)
  252. """
  253. L_block = np.asarray(metrics.get_LAB_L(image), 'uint8')
  254. return metrics.get_low_bits_img(L_block, nb_bits)
  255. def rgb_to_LAB_L_bits(image, interval):
  256. """Returns only bits from LAB L canal specified into the interval
  257. Args:
  258. image: image to convert using this interval of bits value to keep
  259. interval: (begin, end) of bits values
  260. Returns:
  261. 2D Numpy array with reduced values
  262. >>> from PIL import Image
  263. >>> from ipfml import processing
  264. >>> img = Image.open('./images/test_img.png')
  265. >>> bits_Lab_l_img = processing.rgb_to_LAB_L_bits(img, (2, 6))
  266. >>> bits_Lab_l_img.shape
  267. (200, 200)
  268. """
  269. L_block = np.asarray(metrics.get_LAB_L(image), 'uint8')
  270. return metrics.get_bits_img(L_block, interval)