common.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. # Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from typing import Dict, List, Tuple
  15. import numpy as np
  16. from .....utils.deps import class_requires_deps, is_dep_available
  17. if is_dep_available("opencv-contrib-python"):
  18. import cv2
  19. @class_requires_deps("opencv-contrib-python")
  20. class LetterResize(object):
  21. def __init__(
  22. self,
  23. scale=[640, 640],
  24. pad_val=144,
  25. use_mini_pad=False,
  26. stretch_only=False,
  27. allow_scale_up=False,
  28. ):
  29. super(LetterResize, self).__init__()
  30. self.scale = scale
  31. self.pad_val = pad_val
  32. self.use_mini_pad = use_mini_pad
  33. self.stretch_only = stretch_only
  34. self.allow_scale_up = allow_scale_up
  35. def _resize_img(self, image: np.ndarray) -> Dict:
  36. scale = self.scale
  37. image_shape = image.shape[:2]
  38. ratio = min(scale[0] / image_shape[0], scale[1] / image_shape[1])
  39. if not self.allow_scale_up:
  40. ratio = min(ratio, 1.0)
  41. ratio = [ratio, ratio]
  42. no_pad_shape = (
  43. int(round(image_shape[0] * ratio[0])),
  44. int(round(image_shape[1] * ratio[1])),
  45. )
  46. padding_h, padding_w = [scale[0] - no_pad_shape[0], scale[1] - no_pad_shape[1]]
  47. if self.use_mini_pad:
  48. padding_w, padding_h = np.mod(padding_w, 32), np.mod(padding_h, 32)
  49. elif self.stretch_only:
  50. padding_h, padding_w = 0.0, 0.0
  51. no_pad_shape = (scale[0], scale[1])
  52. ratio = [scale[0] / image_shape[0], scale[1] / image_shape[1]]
  53. if image_shape != no_pad_shape:
  54. image = cv2.resize(
  55. image,
  56. (no_pad_shape[1], no_pad_shape[0]),
  57. interpolation=cv2.INTER_LINEAR,
  58. )
  59. scale_factor = (
  60. no_pad_shape[1] / image_shape[1],
  61. no_pad_shape[0] / image_shape[0],
  62. )
  63. top_padding, left_padding = int(round(padding_h // 2 - 0.1)), int(
  64. round(padding_w // 2 - 0.1)
  65. )
  66. bottom_padding = padding_h - top_padding
  67. right_padding = padding_w - left_padding
  68. padding_list = [top_padding, bottom_padding, left_padding, right_padding]
  69. if (
  70. top_padding != 0
  71. or bottom_padding != 0
  72. or left_padding != 0
  73. or right_padding != 0
  74. ):
  75. pad_val = self.pad_val
  76. if isinstance(pad_val, int) and image.ndim == 3:
  77. pad_val = tuple(pad_val for _ in range(image.shape[2]))
  78. top, bottom, left, right = padding_list
  79. image = cv2.copyMakeBorder(
  80. image, top, bottom, left, right, cv2.BORDER_CONSTANT, value=pad_val
  81. )
  82. result = dict()
  83. result["image"] = image
  84. result["scale_factor"] = np.array(scale_factor, dtype=np.float32)
  85. result["pad_param"] = np.array(padding_list, dtype=np.float32)
  86. return result
  87. def __call__(self, images: List[np.ndarray]) -> List[Dict]:
  88. if not isinstance(images, (List, Tuple)):
  89. images = [images]
  90. rst_images = [self._resize_img(image) for image in images]
  91. return rst_images