operators.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. """
  2. # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. """
  16. from __future__ import absolute_import
  17. from __future__ import division
  18. from __future__ import print_function
  19. from __future__ import unicode_literals
  20. import sys
  21. import six
  22. import cv2
  23. import numpy as np
  24. class DecodeImage(object):
  25. """ decode image """
  26. def __init__(self, img_mode='RGB', channel_first=False, **kwargs):
  27. self.img_mode = img_mode
  28. self.channel_first = channel_first
  29. def __call__(self, data):
  30. img = data['image']
  31. if len(img) == 0:
  32. return None
  33. if six.PY2:
  34. assert type(img) is str and len(
  35. img) > 0, "invalid input 'img' in DecodeImage"
  36. else:
  37. assert type(img) is bytes and len(
  38. img) > 0, "invalid input 'img' in DecodeImage"
  39. img = np.frombuffer(img, dtype='uint8')
  40. img = cv2.imdecode(img, 1)
  41. if img is None:
  42. return None
  43. if self.img_mode == 'GRAY':
  44. img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
  45. elif self.img_mode == 'RGB':
  46. assert img.shape[2] == 3, 'invalid shape of image[%s]' % (img.shape)
  47. img = img[:, :, ::-1]
  48. if self.channel_first:
  49. img = img.transpose((2, 0, 1))
  50. data['image'] = img
  51. return data
  52. class NormalizeImage(object):
  53. """ normalize image such as substract mean, divide std
  54. """
  55. def __init__(self, scale=None, mean=None, std=None, order='chw', **kwargs):
  56. if isinstance(scale, str):
  57. scale = eval(scale)
  58. self.scale = np.float32(scale if scale is not None else 1.0 / 255.0)
  59. mean = mean if mean is not None else [0.485, 0.456, 0.406]
  60. std = std if std is not None else [0.229, 0.224, 0.225]
  61. shape = (3, 1, 1) if order == 'chw' else (1, 1, 3)
  62. self.mean = np.array(mean).reshape(shape).astype('float32')
  63. self.std = np.array(std).reshape(shape).astype('float32')
  64. def __call__(self, data):
  65. img = data['image']
  66. from PIL import Image
  67. if isinstance(img, Image.Image):
  68. img = np.array(img)
  69. assert isinstance(img,
  70. np.ndarray), "invalid input 'img' in NormalizeImage"
  71. data['image'] = (
  72. img.astype('float32') * self.scale - self.mean) / self.std
  73. return data
  74. class ToCHWImage(object):
  75. """ convert hwc image to chw image
  76. """
  77. def __init__(self, **kwargs):
  78. pass
  79. def __call__(self, data):
  80. img = data['image']
  81. from PIL import Image
  82. if isinstance(img, Image.Image):
  83. img = np.array(img)
  84. data['image'] = img.transpose((2, 0, 1))
  85. return data
  86. class KeepKeys(object):
  87. def __init__(self, keep_keys, **kwargs):
  88. self.keep_keys = keep_keys
  89. def __call__(self, data):
  90. data_list = []
  91. for key in self.keep_keys:
  92. data_list.append(data[key])
  93. return data_list
  94. class DetResizeForTest(object):
  95. def __init__(self, **kwargs):
  96. super(DetResizeForTest, self).__init__()
  97. self.resize_type = 0
  98. if 'image_shape' in kwargs:
  99. self.image_shape = kwargs['image_shape']
  100. self.resize_type = 1
  101. elif 'limit_side_len' in kwargs:
  102. self.limit_side_len = kwargs['limit_side_len']
  103. self.limit_type = kwargs.get('limit_type', 'min')
  104. elif 'resize_long' in kwargs:
  105. self.resize_type = 2
  106. self.resize_long = kwargs.get('resize_long', 960)
  107. else:
  108. self.limit_side_len = 736
  109. self.limit_type = 'min'
  110. def __call__(self, data):
  111. img = data['image']
  112. src_h, src_w, _ = img.shape
  113. if self.resize_type == 0:
  114. # img, shape = self.resize_image_type0(img)
  115. img, [ratio_h, ratio_w] = self.resize_image_type0(img)
  116. elif self.resize_type == 2:
  117. img, [ratio_h, ratio_w] = self.resize_image_type2(img)
  118. else:
  119. # img, shape = self.resize_image_type1(img)
  120. img, [ratio_h, ratio_w] = self.resize_image_type1(img)
  121. data['image'] = img
  122. data['shape'] = np.array([src_h, src_w, ratio_h, ratio_w])
  123. return data
  124. def resize_image_type1(self, img):
  125. resize_h, resize_w = self.image_shape
  126. ori_h, ori_w = img.shape[:2] # (h, w, c)
  127. ratio_h = float(resize_h) / ori_h
  128. ratio_w = float(resize_w) / ori_w
  129. img = cv2.resize(img, (int(resize_w), int(resize_h)))
  130. # return img, np.array([ori_h, ori_w])
  131. return img, [ratio_h, ratio_w]
  132. def resize_image_type0(self, img):
  133. """
  134. resize image to a size multiple of 32 which is required by the network
  135. args:
  136. img(array): array with shape [h, w, c]
  137. return(tuple):
  138. img, (ratio_h, ratio_w)
  139. """
  140. limit_side_len = self.limit_side_len
  141. h, w, _ = img.shape
  142. # limit the max side
  143. if self.limit_type == 'max':
  144. if max(h, w) > limit_side_len:
  145. if h > w:
  146. ratio = float(limit_side_len) / h
  147. else:
  148. ratio = float(limit_side_len) / w
  149. else:
  150. ratio = 1.
  151. else:
  152. if min(h, w) < limit_side_len:
  153. if h < w:
  154. ratio = float(limit_side_len) / h
  155. else:
  156. ratio = float(limit_side_len) / w
  157. else:
  158. ratio = 1.
  159. resize_h = int(h * ratio)
  160. resize_w = int(w * ratio)
  161. resize_h = int(round(resize_h / 32) * 32)
  162. resize_w = int(round(resize_w / 32) * 32)
  163. try:
  164. if int(resize_w) <= 0 or int(resize_h) <= 0:
  165. return None, (None, None)
  166. img = cv2.resize(img, (int(resize_w), int(resize_h)))
  167. except:
  168. print(img.shape, resize_w, resize_h)
  169. sys.exit(0)
  170. ratio_h = resize_h / float(h)
  171. ratio_w = resize_w / float(w)
  172. # return img, np.array([h, w])
  173. return img, [ratio_h, ratio_w]
  174. def resize_image_type2(self, img):
  175. h, w, _ = img.shape
  176. resize_w = w
  177. resize_h = h
  178. # Fix the longer side
  179. if resize_h > resize_w:
  180. ratio = float(self.resize_long) / resize_h
  181. else:
  182. ratio = float(self.resize_long) / resize_w
  183. resize_h = int(resize_h * ratio)
  184. resize_w = int(resize_w * ratio)
  185. max_stride = 128
  186. resize_h = (resize_h + max_stride - 1) // max_stride * max_stride
  187. resize_w = (resize_w + max_stride - 1) // max_stride * max_stride
  188. img = cv2.resize(img, (int(resize_w), int(resize_h)))
  189. ratio_h = resize_h / float(h)
  190. ratio_w = resize_w / float(w)
  191. return img, [ratio_h, ratio_w]