det_transforms.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. # copyright (c) 2021 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. import numpy as np
  15. from .operators import Transform, Compose, ResizeByShort, Resize, RandomHorizontalFlip, Normalize
  16. from .operators import RandomExpand as dy_RandomExpand
  17. from .operators import RandomCrop as dy_RandomCrop
  18. from .functions import is_poly, expand_poly, expand_rle
  19. class Padding(Transform):
  20. """1.将图像的长和宽padding至coarsest_stride的倍数。如输入图像为[300, 640],
  21. `coarest_stride`为32,则由于300不为32的倍数,因此在图像最右和最下使用0值
  22. 进行padding,最终输出图像为[320, 640]。
  23. 2.或者,将图像的长和宽padding到target_size指定的shape,如输入的图像为[300,640],
  24. a. `target_size` = 960,在图像最右和最下使用0值进行padding,最终输出
  25. 图像为[960, 960]。
  26. b. `target_size` = [640, 960],在图像最右和最下使用0值进行padding,最终
  27. 输出图像为[640, 960]。
  28. 1. 如果coarsest_stride为1,target_size为None则直接返回。
  29. 2. 获取图像的高H、宽W。
  30. 3. 计算填充后图像的高H_new、宽W_new。
  31. 4. 构建大小为(H_new, W_new, 3)像素值为0的np.ndarray,
  32. 并将原图的np.ndarray粘贴于左上角。
  33. Args:
  34. coarsest_stride (int): 填充后的图像长、宽为该参数的倍数,默认为1。
  35. target_size (int|list|tuple): 填充后的图像长、宽,默认为None,coarset_stride优先级更高。
  36. Raises:
  37. TypeError: 形参`target_size`数据类型不满足需求。
  38. ValueError: 形参`target_size`为(list|tuple)时,长度不满足需求。
  39. """
  40. def __init__(self, coarsest_stride=1, target_size=None):
  41. if target_size is not None:
  42. if not isinstance(target_size, int):
  43. if not isinstance(target_size, tuple) and not isinstance(
  44. target_size, list):
  45. raise TypeError(
  46. "Padding: Type of target_size must in (int|list|tuple)."
  47. )
  48. elif len(target_size) != 2:
  49. raise ValueError(
  50. "Padding: Length of target_size must equal 2.")
  51. super(Padding, self).__init__()
  52. self.coarsest_stride = coarsest_stride
  53. self.target_size = target_size
  54. def apply_im(self, image, padding_im_h, padding_im_w):
  55. im_h, im_w, im_c = image.shape
  56. padding_im = np.zeros(
  57. (padding_im_h, padding_im_w, im_c), dtype=np.float32)
  58. padding_im[:im_h, :im_w, :] = image
  59. return padding_im
  60. def apply_bbox(self, bbox):
  61. return bbox
  62. def apply_segm(self, segms, im_h, im_w, padding_im_h, padding_im_w):
  63. expanded_segms = []
  64. for segm in segms:
  65. if is_poly(segm):
  66. # Polygon format
  67. expanded_segms.append(
  68. [expand_poly(poly, 0, 0) for poly in segm])
  69. else:
  70. # RLE format
  71. expanded_segms.append(
  72. expand_rle(segm, 0, 0, im_h, im_w, padding_im_h,
  73. padding_im_w))
  74. return expanded_segms
  75. def apply(self, sample):
  76. im_h, im_w, im_c = sample['image'].shape[:]
  77. if isinstance(self.target_size, int):
  78. padding_im_h = self.target_size
  79. padding_im_w = self.target_size
  80. elif isinstance(self.target_size, list) or isinstance(self.target_size,
  81. tuple):
  82. padding_im_w = self.target_size[0]
  83. padding_im_h = self.target_size[1]
  84. elif self.coarsest_stride > 0:
  85. padding_im_h = int(
  86. np.ceil(im_h / self.coarsest_stride) * self.coarsest_stride)
  87. padding_im_w = int(
  88. np.ceil(im_w / self.coarsest_stride) * self.coarsest_stride)
  89. else:
  90. raise ValueError(
  91. "coarsest_stridei(>1) or target_size(list|int) need setting in Padding transform"
  92. )
  93. pad_height = padding_im_h - im_h
  94. pad_width = padding_im_w - im_w
  95. if pad_height < 0 or pad_width < 0:
  96. raise ValueError(
  97. 'the size of image should be less than target_size, but the size of image ({}, {}), is larger than target_size ({}, {})'
  98. .format(im_w, im_h, padding_im_w, padding_im_h))
  99. sample['image'] = self.apply_im(sample['image'], padding_im_h,
  100. padding_im_w)
  101. if 'gt_bbox' in sample and len(sample['gt_bbox']) > 0:
  102. sample['gt_bbox'] = self.apply_bbox(sample['gt_bbox'])
  103. if 'gt_poly' in sample and len(sample['gt_poly']) > 0:
  104. sample['gt_poly'] = self.apply_segm(sample['gt_poly'], im_h, im_w,
  105. padding_im_h, padding_im_w)
  106. return sample
  107. class RandomExpand(dy_RandomExpand):
  108. def __init__(self,
  109. ratio=4.,
  110. prob=0.5,
  111. fill_value=[123.675, 116.28, 103.53]):
  112. super(RandomExpand, self).__init__(
  113. upper_ratio=ratio, prob=prob, im_padding_value=fill_value)
  114. class RandomCrop(dy_RandomCrop):
  115. def __init__(self,
  116. aspect_ratio=[.5, 2.],
  117. thresholds=[.0, .1, .3, .5, .7, .9],
  118. scaling=[.3, 1.],
  119. num_attempts=50,
  120. allow_no_crop=True,
  121. cover_all_box=False):
  122. super(RandomCrop, self).__init__(
  123. crop_size=None,
  124. aspect_ratio=aspect_ratio,
  125. thresholds=thresholds,
  126. scaling=scaling,
  127. num_attempts=num_attempts,
  128. allow_no_crop=allow_no_crop,
  129. cover_all_box=cover_all_box)