operators.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. import numpy as np
  2. import cv2
  3. import sys
  4. import math
  5. class NormalizeImage(object):
  6. """ normalize image such as substract mean, divide std
  7. """
  8. def __init__(self, scale=None, mean=None, std=None, order='chw', **kwargs):
  9. if isinstance(scale, str):
  10. scale = eval(scale)
  11. self.scale = np.float32(scale if scale is not None else 1.0 / 255.0)
  12. mean = mean if mean is not None else [0.485, 0.456, 0.406]
  13. std = std if std is not None else [0.229, 0.224, 0.225]
  14. shape = (3, 1, 1) if order == 'chw' else (1, 1, 3)
  15. self.mean = np.array(mean).reshape(shape).astype('float32')
  16. self.std = np.array(std).reshape(shape).astype('float32')
  17. def __call__(self, data):
  18. img = data['image']
  19. from PIL import Image
  20. if isinstance(img, Image.Image):
  21. img = np.array(img)
  22. assert isinstance(img,
  23. np.ndarray), "invalid input 'img' in NormalizeImage"
  24. data['image'] = (
  25. img.astype('float32') * self.scale - self.mean) / self.std
  26. return data
  27. class DetResizeForTest(object):
  28. def __init__(self, **kwargs):
  29. super(DetResizeForTest, self).__init__()
  30. self.resize_type = 0
  31. self.keep_ratio = False
  32. if 'image_shape' in kwargs:
  33. self.image_shape = kwargs['image_shape']
  34. self.resize_type = 1
  35. if 'keep_ratio' in kwargs:
  36. self.keep_ratio = kwargs['keep_ratio']
  37. elif 'limit_side_len' in kwargs:
  38. self.limit_side_len = kwargs['limit_side_len']
  39. self.limit_type = kwargs.get('limit_type', 'min')
  40. elif 'resize_long' in kwargs:
  41. self.resize_type = 2
  42. self.resize_long = kwargs.get('resize_long', 960)
  43. else:
  44. self.limit_side_len = 736
  45. self.limit_type = 'min'
  46. def __call__(self, data):
  47. img = data['image']
  48. src_h, src_w, _ = img.shape
  49. if sum([src_h, src_w]) < 64:
  50. img = self.image_padding(img)
  51. if self.resize_type == 0:
  52. # img, shape = self.resize_image_type0(img)
  53. img, [ratio_h, ratio_w] = self.resize_image_type0(img)
  54. elif self.resize_type == 2:
  55. img, [ratio_h, ratio_w] = self.resize_image_type2(img)
  56. else:
  57. # img, shape = self.resize_image_type1(img)
  58. img, [ratio_h, ratio_w] = self.resize_image_type1(img)
  59. data['image'] = img
  60. data['shape'] = np.array([src_h, src_w, ratio_h, ratio_w])
  61. return data
  62. def image_padding(self, im, value=0):
  63. h, w, c = im.shape
  64. im_pad = np.zeros((max(32, h), max(32, w), c), np.uint8) + value
  65. im_pad[:h, :w, :] = im
  66. return im_pad
  67. def resize_image_type1(self, img):
  68. resize_h, resize_w = self.image_shape
  69. ori_h, ori_w = img.shape[:2] # (h, w, c)
  70. if self.keep_ratio is True:
  71. resize_w = ori_w * resize_h / ori_h
  72. N = math.ceil(resize_w / 32)
  73. resize_w = N * 32
  74. ratio_h = float(resize_h) / ori_h
  75. ratio_w = float(resize_w) / ori_w
  76. img = cv2.resize(img, (int(resize_w), int(resize_h)))
  77. # return img, np.array([ori_h, ori_w])
  78. return img, [ratio_h, ratio_w]
  79. def resize_image_type0(self, img):
  80. """
  81. resize image to a size multiple of 32 which is required by the network
  82. args:
  83. img(array): array with shape [h, w, c]
  84. return(tuple):
  85. img, (ratio_h, ratio_w)
  86. """
  87. limit_side_len = self.limit_side_len
  88. h, w, c = img.shape
  89. # limit the max side
  90. if self.limit_type == 'max':
  91. if max(h, w) > limit_side_len:
  92. if h > w:
  93. ratio = float(limit_side_len) / h
  94. else:
  95. ratio = float(limit_side_len) / w
  96. else:
  97. ratio = 1.
  98. elif self.limit_type == 'min':
  99. if min(h, w) < limit_side_len:
  100. if h < w:
  101. ratio = float(limit_side_len) / h
  102. else:
  103. ratio = float(limit_side_len) / w
  104. else:
  105. ratio = 1.
  106. elif self.limit_type == 'resize_long':
  107. ratio = float(limit_side_len) / max(h, w)
  108. else:
  109. raise Exception('not support limit type, image ')
  110. resize_h = int(h * ratio)
  111. resize_w = int(w * ratio)
  112. resize_h = max(int(round(resize_h / 32) * 32), 32)
  113. resize_w = max(int(round(resize_w / 32) * 32), 32)
  114. try:
  115. if int(resize_w) <= 0 or int(resize_h) <= 0:
  116. return None, (None, None)
  117. img = cv2.resize(img, (int(resize_w), int(resize_h)))
  118. except:
  119. print(img.shape, resize_w, resize_h)
  120. sys.exit(0)
  121. ratio_h = resize_h / float(h)
  122. ratio_w = resize_w / float(w)
  123. return img, [ratio_h, ratio_w]
  124. def resize_image_type2(self, img):
  125. h, w, _ = img.shape
  126. resize_w = w
  127. resize_h = h
  128. if resize_h > resize_w:
  129. ratio = float(self.resize_long) / resize_h
  130. else:
  131. ratio = float(self.resize_long) / resize_w
  132. resize_h = int(resize_h * ratio)
  133. resize_w = int(resize_w * ratio)
  134. max_stride = 128
  135. resize_h = (resize_h + max_stride - 1) // max_stride * max_stride
  136. resize_w = (resize_w + max_stride - 1) // max_stride * max_stride
  137. img = cv2.resize(img, (int(resize_w), int(resize_h)))
  138. ratio_h = resize_h / float(h)
  139. ratio_w = resize_w / float(w)
  140. return img, [ratio_h, ratio_w]
  141. class ToCHWImage(object):
  142. """ convert hwc image to chw image
  143. """
  144. def __init__(self, **kwargs):
  145. pass
  146. def __call__(self, data):
  147. img = data['image']
  148. from PIL import Image
  149. if isinstance(img, Image.Image):
  150. img = np.array(img)
  151. data['image'] = img.transpose((2, 0, 1))
  152. return data
  153. class KeepKeys(object):
  154. def __init__(self, keep_keys, **kwargs):
  155. self.keep_keys = keep_keys
  156. def __call__(self, data):
  157. data_list = []
  158. for key in self.keep_keys:
  159. data_list.append(data[key])
  160. return data_list