Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. #
  2. # Copyright 2024 The InfiniFlow 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. import sys
  17. import six
  18. import cv2
  19. import numpy as np
  20. import math
  21. from PIL import Image
  22. class DecodeImage(object):
  23. """ decode image """
  24. def __init__(self,
  25. img_mode='RGB',
  26. channel_first=False,
  27. ignore_orientation=False,
  28. **kwargs):
  29. self.img_mode = img_mode
  30. self.channel_first = channel_first
  31. self.ignore_orientation = ignore_orientation
  32. def __call__(self, data):
  33. img = data['image']
  34. if six.PY2:
  35. assert isinstance(img, str) and len(
  36. img) > 0, "invalid input 'img' in DecodeImage"
  37. else:
  38. assert isinstance(img, bytes) and len(
  39. img) > 0, "invalid input 'img' in DecodeImage"
  40. img = np.frombuffer(img, dtype='uint8')
  41. if self.ignore_orientation:
  42. img = cv2.imdecode(img, cv2.IMREAD_IGNORE_ORIENTATION |
  43. cv2.IMREAD_COLOR)
  44. else:
  45. img = cv2.imdecode(img, 1)
  46. if img is None:
  47. return None
  48. if self.img_mode == 'GRAY':
  49. img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
  50. elif self.img_mode == 'RGB':
  51. assert img.shape[2] == 3, 'invalid shape of image[%s]' % (
  52. img.shape)
  53. img = img[:, :, ::-1]
  54. if self.channel_first:
  55. img = img.transpose((2, 0, 1))
  56. data['image'] = img
  57. return data
  58. class StandardizeImage(object):
  59. """normalize image
  60. Args:
  61. mean (list): im - mean
  62. std (list): im / std
  63. is_scale (bool): whether need im / 255
  64. norm_type (str): type in ['mean_std', 'none']
  65. """
  66. def __init__(self, mean, std, is_scale=True, norm_type='mean_std'):
  67. self.mean = mean
  68. self.std = std
  69. self.is_scale = is_scale
  70. self.norm_type = norm_type
  71. def __call__(self, im, im_info):
  72. """
  73. Args:
  74. im (np.ndarray): image (np.ndarray)
  75. im_info (dict): info of image
  76. Returns:
  77. im (np.ndarray): processed image (np.ndarray)
  78. im_info (dict): info of processed image
  79. """
  80. im = im.astype(np.float32, copy=False)
  81. if self.is_scale:
  82. scale = 1.0 / 255.0
  83. im *= scale
  84. if self.norm_type == 'mean_std':
  85. mean = np.array(self.mean)[np.newaxis, np.newaxis, :]
  86. std = np.array(self.std)[np.newaxis, np.newaxis, :]
  87. im -= mean
  88. im /= std
  89. return im, im_info
  90. class NormalizeImage(object):
  91. """ normalize image such as substract mean, divide std
  92. """
  93. def __init__(self, scale=None, mean=None, std=None, order='chw', **kwargs):
  94. if isinstance(scale, str):
  95. scale = eval(scale)
  96. self.scale = np.float32(scale if scale is not None else 1.0 / 255.0)
  97. mean = mean if mean is not None else [0.485, 0.456, 0.406]
  98. std = std if std is not None else [0.229, 0.224, 0.225]
  99. shape = (3, 1, 1) if order == 'chw' else (1, 1, 3)
  100. self.mean = np.array(mean).reshape(shape).astype('float32')
  101. self.std = np.array(std).reshape(shape).astype('float32')
  102. def __call__(self, data):
  103. img = data['image']
  104. from PIL import Image
  105. if isinstance(img, Image.Image):
  106. img = np.array(img)
  107. assert isinstance(img,
  108. np.ndarray), "invalid input 'img' in NormalizeImage"
  109. data['image'] = (
  110. img.astype('float32') * self.scale - self.mean) / self.std
  111. return data
  112. class ToCHWImage(object):
  113. """ convert hwc image to chw image
  114. """
  115. def __init__(self, **kwargs):
  116. pass
  117. def __call__(self, data):
  118. img = data['image']
  119. from PIL import Image
  120. if isinstance(img, Image.Image):
  121. img = np.array(img)
  122. data['image'] = img.transpose((2, 0, 1))
  123. return data
  124. class Fasttext(object):
  125. def __init__(self, path="None", **kwargs):
  126. import fasttext
  127. self.fast_model = fasttext.load_model(path)
  128. def __call__(self, data):
  129. label = data['label']
  130. fast_label = self.fast_model[label]
  131. data['fast_label'] = fast_label
  132. return data
  133. class KeepKeys(object):
  134. def __init__(self, keep_keys, **kwargs):
  135. self.keep_keys = keep_keys
  136. def __call__(self, data):
  137. data_list = []
  138. for key in self.keep_keys:
  139. data_list.append(data[key])
  140. return data_list
  141. class Pad(object):
  142. def __init__(self, size=None, size_div=32, **kwargs):
  143. if size is not None and not isinstance(size, (int, list, tuple)):
  144. raise TypeError("Type of target_size is invalid. Now is {}".format(
  145. type(size)))
  146. if isinstance(size, int):
  147. size = [size, size]
  148. self.size = size
  149. self.size_div = size_div
  150. def __call__(self, data):
  151. img = data['image']
  152. img_h, img_w = img.shape[0], img.shape[1]
  153. if self.size:
  154. resize_h2, resize_w2 = self.size
  155. assert (
  156. img_h < resize_h2 and img_w < resize_w2
  157. ), '(h, w) of target size should be greater than (img_h, img_w)'
  158. else:
  159. resize_h2 = max(
  160. int(math.ceil(img.shape[0] / self.size_div) * self.size_div),
  161. self.size_div)
  162. resize_w2 = max(
  163. int(math.ceil(img.shape[1] / self.size_div) * self.size_div),
  164. self.size_div)
  165. img = cv2.copyMakeBorder(
  166. img,
  167. 0,
  168. resize_h2 - img_h,
  169. 0,
  170. resize_w2 - img_w,
  171. cv2.BORDER_CONSTANT,
  172. value=0)
  173. data['image'] = img
  174. return data
  175. class LinearResize(object):
  176. """resize image by target_size and max_size
  177. Args:
  178. target_size (int): the target size of image
  179. keep_ratio (bool): whether keep_ratio or not, default true
  180. interp (int): method of resize
  181. """
  182. def __init__(self, target_size, keep_ratio=True, interp=cv2.INTER_LINEAR):
  183. if isinstance(target_size, int):
  184. target_size = [target_size, target_size]
  185. self.target_size = target_size
  186. self.keep_ratio = keep_ratio
  187. self.interp = interp
  188. def __call__(self, im, im_info):
  189. """
  190. Args:
  191. im (np.ndarray): image (np.ndarray)
  192. im_info (dict): info of image
  193. Returns:
  194. im (np.ndarray): processed image (np.ndarray)
  195. im_info (dict): info of processed image
  196. """
  197. assert len(self.target_size) == 2
  198. assert self.target_size[0] > 0 and self.target_size[1] > 0
  199. im_channel = im.shape[2]
  200. im_scale_y, im_scale_x = self.generate_scale(im)
  201. im = cv2.resize(
  202. im,
  203. None,
  204. None,
  205. fx=im_scale_x,
  206. fy=im_scale_y,
  207. interpolation=self.interp)
  208. im_info['im_shape'] = np.array(im.shape[:2]).astype('float32')
  209. im_info['scale_factor'] = np.array(
  210. [im_scale_y, im_scale_x]).astype('float32')
  211. return im, im_info
  212. def generate_scale(self, im):
  213. """
  214. Args:
  215. im (np.ndarray): image (np.ndarray)
  216. Returns:
  217. im_scale_x: the resize ratio of X
  218. im_scale_y: the resize ratio of Y
  219. """
  220. origin_shape = im.shape[:2]
  221. im_c = im.shape[2]
  222. if self.keep_ratio:
  223. im_size_min = np.min(origin_shape)
  224. im_size_max = np.max(origin_shape)
  225. target_size_min = np.min(self.target_size)
  226. target_size_max = np.max(self.target_size)
  227. im_scale = float(target_size_min) / float(im_size_min)
  228. if np.round(im_scale * im_size_max) > target_size_max:
  229. im_scale = float(target_size_max) / float(im_size_max)
  230. im_scale_x = im_scale
  231. im_scale_y = im_scale
  232. else:
  233. resize_h, resize_w = self.target_size
  234. im_scale_y = resize_h / float(origin_shape[0])
  235. im_scale_x = resize_w / float(origin_shape[1])
  236. return im_scale_y, im_scale_x
  237. class Resize(object):
  238. def __init__(self, size=(640, 640), **kwargs):
  239. self.size = size
  240. def resize_image(self, img):
  241. resize_h, resize_w = self.size
  242. ori_h, ori_w = img.shape[:2] # (h, w, c)
  243. ratio_h = float(resize_h) / ori_h
  244. ratio_w = float(resize_w) / ori_w
  245. img = cv2.resize(img, (int(resize_w), int(resize_h)))
  246. return img, [ratio_h, ratio_w]
  247. def __call__(self, data):
  248. img = data['image']
  249. if 'polys' in data:
  250. text_polys = data['polys']
  251. img_resize, [ratio_h, ratio_w] = self.resize_image(img)
  252. if 'polys' in data:
  253. new_boxes = []
  254. for box in text_polys:
  255. new_box = []
  256. for cord in box:
  257. new_box.append([cord[0] * ratio_w, cord[1] * ratio_h])
  258. new_boxes.append(new_box)
  259. data['polys'] = np.array(new_boxes, dtype=np.float32)
  260. data['image'] = img_resize
  261. return data
  262. class DetResizeForTest(object):
  263. def __init__(self, **kwargs):
  264. super(DetResizeForTest, self).__init__()
  265. self.resize_type = 0
  266. self.keep_ratio = False
  267. if 'image_shape' in kwargs:
  268. self.image_shape = kwargs['image_shape']
  269. self.resize_type = 1
  270. if 'keep_ratio' in kwargs:
  271. self.keep_ratio = kwargs['keep_ratio']
  272. elif 'limit_side_len' in kwargs:
  273. self.limit_side_len = kwargs['limit_side_len']
  274. self.limit_type = kwargs.get('limit_type', 'min')
  275. elif 'resize_long' in kwargs:
  276. self.resize_type = 2
  277. self.resize_long = kwargs.get('resize_long', 960)
  278. else:
  279. self.limit_side_len = 736
  280. self.limit_type = 'min'
  281. def __call__(self, data):
  282. img = data['image']
  283. src_h, src_w, _ = img.shape
  284. if sum([src_h, src_w]) < 64:
  285. img = self.image_padding(img)
  286. if self.resize_type == 0:
  287. # img, shape = self.resize_image_type0(img)
  288. img, [ratio_h, ratio_w] = self.resize_image_type0(img)
  289. elif self.resize_type == 2:
  290. img, [ratio_h, ratio_w] = self.resize_image_type2(img)
  291. else:
  292. # img, shape = self.resize_image_type1(img)
  293. img, [ratio_h, ratio_w] = self.resize_image_type1(img)
  294. data['image'] = img
  295. data['shape'] = np.array([src_h, src_w, ratio_h, ratio_w])
  296. return data
  297. def image_padding(self, im, value=0):
  298. h, w, c = im.shape
  299. im_pad = np.zeros((max(32, h), max(32, w), c), np.uint8) + value
  300. im_pad[:h, :w, :] = im
  301. return im_pad
  302. def resize_image_type1(self, img):
  303. resize_h, resize_w = self.image_shape
  304. ori_h, ori_w = img.shape[:2] # (h, w, c)
  305. if self.keep_ratio is True:
  306. resize_w = ori_w * resize_h / ori_h
  307. N = math.ceil(resize_w / 32)
  308. resize_w = N * 32
  309. ratio_h = float(resize_h) / ori_h
  310. ratio_w = float(resize_w) / ori_w
  311. img = cv2.resize(img, (int(resize_w), int(resize_h)))
  312. # return img, np.array([ori_h, ori_w])
  313. return img, [ratio_h, ratio_w]
  314. def resize_image_type0(self, img):
  315. """
  316. resize image to a size multiple of 32 which is required by the network
  317. args:
  318. img(array): array with shape [h, w, c]
  319. return(tuple):
  320. img, (ratio_h, ratio_w)
  321. """
  322. limit_side_len = self.limit_side_len
  323. h, w, c = img.shape
  324. # limit the max side
  325. if self.limit_type == 'max':
  326. if max(h, w) > limit_side_len:
  327. if h > w:
  328. ratio = float(limit_side_len) / h
  329. else:
  330. ratio = float(limit_side_len) / w
  331. else:
  332. ratio = 1.
  333. elif self.limit_type == 'min':
  334. if min(h, w) < limit_side_len:
  335. if h < w:
  336. ratio = float(limit_side_len) / h
  337. else:
  338. ratio = float(limit_side_len) / w
  339. else:
  340. ratio = 1.
  341. elif self.limit_type == 'resize_long':
  342. ratio = float(limit_side_len) / max(h, w)
  343. else:
  344. raise Exception('not support limit type, image ')
  345. resize_h = int(h * ratio)
  346. resize_w = int(w * ratio)
  347. resize_h = max(int(round(resize_h / 32) * 32), 32)
  348. resize_w = max(int(round(resize_w / 32) * 32), 32)
  349. try:
  350. if int(resize_w) <= 0 or int(resize_h) <= 0:
  351. return None, (None, None)
  352. img = cv2.resize(img, (int(resize_w), int(resize_h)))
  353. except BaseException:
  354. print(img.shape, resize_w, resize_h)
  355. sys.exit(0)
  356. ratio_h = resize_h / float(h)
  357. ratio_w = resize_w / float(w)
  358. return img, [ratio_h, ratio_w]
  359. def resize_image_type2(self, img):
  360. h, w, _ = img.shape
  361. resize_w = w
  362. resize_h = h
  363. if resize_h > resize_w:
  364. ratio = float(self.resize_long) / resize_h
  365. else:
  366. ratio = float(self.resize_long) / resize_w
  367. resize_h = int(resize_h * ratio)
  368. resize_w = int(resize_w * ratio)
  369. max_stride = 128
  370. resize_h = (resize_h + max_stride - 1) // max_stride * max_stride
  371. resize_w = (resize_w + max_stride - 1) // max_stride * max_stride
  372. img = cv2.resize(img, (int(resize_w), int(resize_h)))
  373. ratio_h = resize_h / float(h)
  374. ratio_w = resize_w / float(w)
  375. return img, [ratio_h, ratio_w]
  376. class E2EResizeForTest(object):
  377. def __init__(self, **kwargs):
  378. super(E2EResizeForTest, self).__init__()
  379. self.max_side_len = kwargs['max_side_len']
  380. self.valid_set = kwargs['valid_set']
  381. def __call__(self, data):
  382. img = data['image']
  383. src_h, src_w, _ = img.shape
  384. if self.valid_set == 'totaltext':
  385. im_resized, [ratio_h, ratio_w] = self.resize_image_for_totaltext(
  386. img, max_side_len=self.max_side_len)
  387. else:
  388. im_resized, (ratio_h, ratio_w) = self.resize_image(
  389. img, max_side_len=self.max_side_len)
  390. data['image'] = im_resized
  391. data['shape'] = np.array([src_h, src_w, ratio_h, ratio_w])
  392. return data
  393. def resize_image_for_totaltext(self, im, max_side_len=512):
  394. h, w, _ = im.shape
  395. resize_w = w
  396. resize_h = h
  397. ratio = 1.25
  398. if h * ratio > max_side_len:
  399. ratio = float(max_side_len) / resize_h
  400. resize_h = int(resize_h * ratio)
  401. resize_w = int(resize_w * ratio)
  402. max_stride = 128
  403. resize_h = (resize_h + max_stride - 1) // max_stride * max_stride
  404. resize_w = (resize_w + max_stride - 1) // max_stride * max_stride
  405. im = cv2.resize(im, (int(resize_w), int(resize_h)))
  406. ratio_h = resize_h / float(h)
  407. ratio_w = resize_w / float(w)
  408. return im, (ratio_h, ratio_w)
  409. def resize_image(self, im, max_side_len=512):
  410. """
  411. resize image to a size multiple of max_stride which is required by the network
  412. :param im: the resized image
  413. :param max_side_len: limit of max image size to avoid out of memory in gpu
  414. :return: the resized image and the resize ratio
  415. """
  416. h, w, _ = im.shape
  417. resize_w = w
  418. resize_h = h
  419. # Fix the longer side
  420. if resize_h > resize_w:
  421. ratio = float(max_side_len) / resize_h
  422. else:
  423. ratio = float(max_side_len) / resize_w
  424. resize_h = int(resize_h * ratio)
  425. resize_w = int(resize_w * ratio)
  426. max_stride = 128
  427. resize_h = (resize_h + max_stride - 1) // max_stride * max_stride
  428. resize_w = (resize_w + max_stride - 1) // max_stride * max_stride
  429. im = cv2.resize(im, (int(resize_w), int(resize_h)))
  430. ratio_h = resize_h / float(h)
  431. ratio_w = resize_w / float(w)
  432. return im, (ratio_h, ratio_w)
  433. class KieResize(object):
  434. def __init__(self, **kwargs):
  435. super(KieResize, self).__init__()
  436. self.max_side, self.min_side = kwargs['img_scale'][0], kwargs[
  437. 'img_scale'][1]
  438. def __call__(self, data):
  439. img = data['image']
  440. points = data['points']
  441. src_h, src_w, _ = img.shape
  442. im_resized, scale_factor, [ratio_h, ratio_w
  443. ], [new_h, new_w] = self.resize_image(img)
  444. resize_points = self.resize_boxes(img, points, scale_factor)
  445. data['ori_image'] = img
  446. data['ori_boxes'] = points
  447. data['points'] = resize_points
  448. data['image'] = im_resized
  449. data['shape'] = np.array([new_h, new_w])
  450. return data
  451. def resize_image(self, img):
  452. norm_img = np.zeros([1024, 1024, 3], dtype='float32')
  453. scale = [512, 1024]
  454. h, w = img.shape[:2]
  455. max_long_edge = max(scale)
  456. max_short_edge = min(scale)
  457. scale_factor = min(max_long_edge / max(h, w),
  458. max_short_edge / min(h, w))
  459. resize_w, resize_h = int(w * float(scale_factor) + 0.5), int(h * float(
  460. scale_factor) + 0.5)
  461. max_stride = 32
  462. resize_h = (resize_h + max_stride - 1) // max_stride * max_stride
  463. resize_w = (resize_w + max_stride - 1) // max_stride * max_stride
  464. im = cv2.resize(img, (resize_w, resize_h))
  465. new_h, new_w = im.shape[:2]
  466. w_scale = new_w / w
  467. h_scale = new_h / h
  468. scale_factor = np.array(
  469. [w_scale, h_scale, w_scale, h_scale], dtype=np.float32)
  470. norm_img[:new_h, :new_w, :] = im
  471. return norm_img, scale_factor, [h_scale, w_scale], [new_h, new_w]
  472. def resize_boxes(self, im, points, scale_factor):
  473. points = points * scale_factor
  474. img_shape = im.shape[:2]
  475. points[:, 0::2] = np.clip(points[:, 0::2], 0, img_shape[1])
  476. points[:, 1::2] = np.clip(points[:, 1::2], 0, img_shape[0])
  477. return points
  478. class SRResize(object):
  479. def __init__(self,
  480. imgH=32,
  481. imgW=128,
  482. down_sample_scale=4,
  483. keep_ratio=False,
  484. min_ratio=1,
  485. mask=False,
  486. infer_mode=False,
  487. **kwargs):
  488. self.imgH = imgH
  489. self.imgW = imgW
  490. self.keep_ratio = keep_ratio
  491. self.min_ratio = min_ratio
  492. self.down_sample_scale = down_sample_scale
  493. self.mask = mask
  494. self.infer_mode = infer_mode
  495. def __call__(self, data):
  496. imgH = self.imgH
  497. imgW = self.imgW
  498. images_lr = data["image_lr"]
  499. transform2 = ResizeNormalize(
  500. (imgW // self.down_sample_scale, imgH // self.down_sample_scale))
  501. images_lr = transform2(images_lr)
  502. data["img_lr"] = images_lr
  503. if self.infer_mode:
  504. return data
  505. images_HR = data["image_hr"]
  506. label_strs = data["label"]
  507. transform = ResizeNormalize((imgW, imgH))
  508. images_HR = transform(images_HR)
  509. data["img_hr"] = images_HR
  510. return data
  511. class ResizeNormalize(object):
  512. def __init__(self, size, interpolation=Image.BICUBIC):
  513. self.size = size
  514. self.interpolation = interpolation
  515. def __call__(self, img):
  516. img = img.resize(self.size, self.interpolation)
  517. img_numpy = np.array(img).astype("float32")
  518. img_numpy = img_numpy.transpose((2, 0, 1)) / 255
  519. return img_numpy
  520. class GrayImageChannelFormat(object):
  521. """
  522. format gray scale image's channel: (3,h,w) -> (1,h,w)
  523. Args:
  524. inverse: inverse gray image
  525. """
  526. def __init__(self, inverse=False, **kwargs):
  527. self.inverse = inverse
  528. def __call__(self, data):
  529. img = data['image']
  530. img_single_channel = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  531. img_expanded = np.expand_dims(img_single_channel, 0)
  532. if self.inverse:
  533. data['image'] = np.abs(img_expanded - 1)
  534. else:
  535. data['image'] = img_expanded
  536. data['src_image'] = img
  537. return data
  538. class Permute(object):
  539. """permute image
  540. Args:
  541. to_bgr (bool): whether convert RGB to BGR
  542. channel_first (bool): whether convert HWC to CHW
  543. """
  544. def __init__(self, ):
  545. super(Permute, self).__init__()
  546. def __call__(self, im, im_info):
  547. """
  548. Args:
  549. im (np.ndarray): image (np.ndarray)
  550. im_info (dict): info of image
  551. Returns:
  552. im (np.ndarray): processed image (np.ndarray)
  553. im_info (dict): info of processed image
  554. """
  555. im = im.transpose((2, 0, 1)).copy()
  556. return im, im_info
  557. class PadStride(object):
  558. """ padding image for model with FPN, instead PadBatch(pad_to_stride) in original config
  559. Args:
  560. stride (bool): model with FPN need image shape % stride == 0
  561. """
  562. def __init__(self, stride=0):
  563. self.coarsest_stride = stride
  564. def __call__(self, im, im_info):
  565. """
  566. Args:
  567. im (np.ndarray): image (np.ndarray)
  568. im_info (dict): info of image
  569. Returns:
  570. im (np.ndarray): processed image (np.ndarray)
  571. im_info (dict): info of processed image
  572. """
  573. coarsest_stride = self.coarsest_stride
  574. if coarsest_stride <= 0:
  575. return im, im_info
  576. im_c, im_h, im_w = im.shape
  577. pad_h = int(np.ceil(float(im_h) / coarsest_stride) * coarsest_stride)
  578. pad_w = int(np.ceil(float(im_w) / coarsest_stride) * coarsest_stride)
  579. padding_im = np.zeros((im_c, pad_h, pad_w), dtype=np.float32)
  580. padding_im[:, :im_h, :im_w] = im
  581. return padding_im, im_info
  582. def decode_image(im_file, im_info):
  583. """read rgb image
  584. Args:
  585. im_file (str|np.ndarray): input can be image path or np.ndarray
  586. im_info (dict): info of image
  587. Returns:
  588. im (np.ndarray): processed image (np.ndarray)
  589. im_info (dict): info of processed image
  590. """
  591. if isinstance(im_file, str):
  592. with open(im_file, 'rb') as f:
  593. im_read = f.read()
  594. data = np.frombuffer(im_read, dtype='uint8')
  595. im = cv2.imdecode(data, 1) # BGR mode, but need RGB mode
  596. im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
  597. else:
  598. im = im_file
  599. im_info['im_shape'] = np.array(im.shape[:2], dtype=np.float32)
  600. im_info['scale_factor'] = np.array([1., 1.], dtype=np.float32)
  601. return im, im_info
  602. def preprocess(im, preprocess_ops):
  603. # process image by preprocess_ops
  604. im_info = {
  605. 'scale_factor': np.array(
  606. [1., 1.], dtype=np.float32),
  607. 'im_shape': None,
  608. }
  609. im, im_info = decode_image(im, im_info)
  610. for operator in preprocess_ops:
  611. im, im_info = operator(im, im_info)
  612. return im, im_info