image.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. from imageio import imread
  2. from PIL import Image
  3. from os.path import isfile
  4. import copy
  5. import numpy as np
  6. from . import utils
  7. def should_have_parts(func):
  8. def inner(self, *args, **kwargs):
  9. assert self.has_parts, "parts are not present!"
  10. return func(self, *args, **kwargs)
  11. return inner
  12. class ImageWrapper(object):
  13. @staticmethod
  14. def read_image(im_path, mode="RGB"):
  15. # im = imread(im_path, pilmode=mode)
  16. im = Image.open(im_path, mode="r")
  17. return im
  18. def __init__(self, im_path, label, parts=None, mode="RGB"):
  19. self.mode = mode
  20. self.im = im_path
  21. self._im_array = None
  22. self.label = label
  23. self.parts = parts
  24. self.parent = None
  25. self._feature = None
  26. def __del__(self):
  27. self._im.close()
  28. @property
  29. def im(self):
  30. return self._im
  31. @property
  32. def im_array(self):
  33. if self._im_array is None:
  34. self.im = self.im.convert(self.mode)
  35. self._im_array = utils.asarray(self.im)
  36. return self._im_array
  37. @im.setter
  38. def im(self, value):
  39. if isinstance(value, str):
  40. assert isfile(value), "Image \"{}\" does not exist!".format(value)
  41. self._im = ImageWrapper.read_image(value, mode=self.mode)
  42. else:
  43. self._im = value
  44. def as_tuple(self):
  45. return self.im_array, self.parts, self.label
  46. def copy(self):
  47. new = copy.copy(self)
  48. new.parent = self
  49. deepcopies = [
  50. "_feature",
  51. "parts",
  52. ]
  53. for attr_name in deepcopies:
  54. attr_copy = copy.deepcopy(getattr(self, attr_name))
  55. setattr(new, attr_name, attr_copy)
  56. return new
  57. @property
  58. def feature(self):
  59. return self._feature
  60. @feature.setter
  61. def feature(self, im_feature):
  62. self._feature = im_feature
  63. def crop(self, x, y, w, h):
  64. result = self.copy()
  65. # result.im = self.im[y:y+h, x:x+w]
  66. result.im = self.im.crop(x, y, x+w, y+h)
  67. if self.has_parts:
  68. result.parts[:, 1] -= x
  69. result.parts[:, 2] -= y
  70. return result
  71. @should_have_parts
  72. def hide_parts_outside_bb(self, x, y, w, h):
  73. idxs, (xs,ys) = self.visible_part_locs()
  74. f = np.logical_and
  75. mask = f(f(x <= xs, xs <= x+w), f(y <= ys, ys <= y+h))
  76. result = self.copy()
  77. result.parts[:, -1] = mask.astype(self.parts.dtype)
  78. return result
  79. def uniform_parts(self, ratio):
  80. result = self.copy()
  81. result.parts = utils.uniform_parts(self.im, ratio=ratio)
  82. return result
  83. @should_have_parts
  84. def select_parts(self, idxs):
  85. result = self.copy()
  86. result.parts[:, -1] = 0
  87. result.parts[idxs, -1] = 1
  88. return result
  89. @should_have_parts
  90. def select_random_parts(self, rnd, n_parts):
  91. idxs, xy = self.visible_part_locs()
  92. rnd_idxs = utils.random_idxs(idxs, rnd=rnd, n_parts=n_parts)
  93. return self.select_parts(rnd_idxs)
  94. @should_have_parts
  95. def visible_crops(self, ratio):
  96. return utils.visible_crops(self.im, self.parts, ratio=ratio)
  97. @should_have_parts
  98. def visible_part_locs(self):
  99. return utils.visible_part_locs(self.parts)
  100. @should_have_parts
  101. def reveal_visible(self, ratio):
  102. _, xy = self.visible_part_locs()
  103. result = self.copy()
  104. result.im = utils.reveal_parts(self.im, xy, ratio=ratio)
  105. return result
  106. @should_have_parts
  107. def part_crops(self, ratio):
  108. crops = self.visible_crops(ratio)
  109. idxs, _ = self.visible_part_locs()
  110. result = self.copy()
  111. result.im = crops[idxs]
  112. return result
  113. @property
  114. def has_parts(self):
  115. return self.parts is not None