movement.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. """
  2. All movements that can be applied on image such as rotations, fusions, flips
  3. """
  4. # main imports
  5. import numpy as np
  6. # image processing imports
  7. from PIL import Image
  8. from skimage import transform as sk_transform
  9. # ipfml imports
  10. from ipfml.exceptions import NumpyShapeComparisonException
  11. def fusion_images(images, pil=True):
  12. '''Fusion array of images into single image
  13. Args:
  14. images: array of images (PIL Image or Numpy array)
  15. pil: block type returned as PIL Image (default True)
  16. Returns:
  17. merged image from array of images
  18. Raises:
  19. ValueError: if `images` is not an array or is empty
  20. NumpyShapeComparisonException: if `images` array contains images with different shapes
  21. Example:
  22. >>> import numpy as np
  23. >>> from ipfml.processing import movement
  24. >>> image_values_1 = np.random.randint(255, size=(800, 800, 3))
  25. >>> image_values_2 = np.random.randint(255, size=(800, 800, 3))
  26. >>> merged_image = movement.fusion_images([image_values_1, image_values_2], pil=False)
  27. >>> merged_image.shape
  28. (800, 800, 3)
  29. '''
  30. mode = 'RGB'
  31. dim = 1
  32. if len(images) == 0:
  33. raise ValueError('Empty array of images provided...')
  34. # convert image in numpy array (perhaps not necessary)
  35. images = [np.asarray(img) for img in images]
  36. image_array = images[0]
  37. if image_array.ndim != 3:
  38. mode = 'L'
  39. width, height = image_array.shape
  40. else:
  41. width, height, dim = image_array.shape
  42. # raise exception if all images do not have same shape
  43. if not np.array([image_array.shape == a.shape for a in images]).all():
  44. raise NumpyShapeComparisonException()
  45. if dim == 1:
  46. image_mean = np.empty([width, height])
  47. else:
  48. image_mean = np.empty([width, height, dim])
  49. nb_images = len(images)
  50. # construction of mean image from rotation
  51. for i in range(width):
  52. for j in range(height):
  53. if dim == 1:
  54. grey_value = 0
  55. # for each image we merge pixel values
  56. for img in images:
  57. grey_value += img[i][j]
  58. image_mean[i][j] = grey_value / nb_images
  59. else:
  60. for k in range(dim):
  61. canal_value = 0
  62. # for each image we merge pixel values
  63. for img in images:
  64. canal_value += img[i][j][k]
  65. image_mean[i][j][k] = canal_value / nb_images
  66. image_mean = np.array(image_mean, 'uint8')
  67. if pil:
  68. return Image.fromarray(image_mean, mode)
  69. else:
  70. return image_mean
  71. def rotate_image(image, angle=90, pil=True):
  72. """Rotate image using specific angle
  73. Args:
  74. image: PIL Image or Numpy array
  75. angle: Angle value of the rotation
  76. pil: block type returned as PIL Image (default True)
  77. Returns:
  78. Image with rotation applied
  79. Example:
  80. >>> from PIL import Image
  81. >>> import numpy as np
  82. >>> from ipfml.processing import movement
  83. >>> image_values = Image.open('./images/test_img.png')
  84. >>> rotated_image = movement.rotate_image(image_values, 90, pil=False)
  85. >>> rotated_image.shape
  86. (200, 200, 3)
  87. """
  88. mode = 'RGB'
  89. image_array = np.asarray(image)
  90. if image_array.ndim != 3:
  91. mode = 'L'
  92. rotated_image = np.array(
  93. sk_transform.rotate(image_array, angle) * 255, 'uint8')
  94. if pil:
  95. return Image.fromarray(rotated_image, mode)
  96. else:
  97. return rotated_image