resize.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import cv2
  2. import khandy
  3. import numpy as np
  4. interp_codes = {
  5. 'nearest': cv2.INTER_NEAREST,
  6. 'bilinear': cv2.INTER_LINEAR,
  7. 'bicubic': cv2.INTER_CUBIC,
  8. 'area': cv2.INTER_AREA,
  9. 'lanczos': cv2.INTER_LANCZOS4
  10. }
  11. def scale_image(image, x_scale, y_scale, interpolation='bilinear'):
  12. """Scale image.
  13. Reference:
  14. mmcv.imrescale
  15. """
  16. assert khandy.is_numpy_image(image)
  17. src_height, src_width = image.shape[:2]
  18. dst_width = int(round(x_scale * src_width))
  19. dst_height = int(round(y_scale * src_height))
  20. resized_image = cv2.resize(image, (dst_width, dst_height),
  21. interpolation=interp_codes[interpolation])
  22. return resized_image
  23. def resize_image(image, dst_width, dst_height, return_scale=False, interpolation='bilinear'):
  24. """Resize image to a given size.
  25. Args:
  26. image (ndarray): The input image.
  27. dst_width (int): Target width.
  28. dst_height (int): Target height.
  29. return_scale (bool): Whether to return `x_scale` and `y_scale`.
  30. interpolation (str): Interpolation method, accepted values are
  31. "nearest", "bilinear", "bicubic", "area", "lanczos".
  32. Returns:
  33. tuple or ndarray: (`resized_image`, `x_scale`, `y_scale`) or `resized_image`.
  34. Reference:
  35. mmcv.imresize
  36. """
  37. assert khandy.is_numpy_image(image)
  38. resized_image = cv2.resize(image, (dst_width, dst_height),
  39. interpolation=interp_codes[interpolation])
  40. if not return_scale:
  41. return resized_image
  42. else:
  43. src_height, src_width = image.shape[:2]
  44. x_scale = dst_width / src_width
  45. y_scale = dst_height / src_height
  46. return resized_image, x_scale, y_scale
  47. def resize_image_short(image, dst_size, return_scale=False, interpolation='bilinear'):
  48. """Resize an image so that the length of shorter side is dst_size while
  49. preserving the original aspect ratio.
  50. References:
  51. `resize_min` in `https://github.com/pjreddie/darknet/blob/master/src/image.c`
  52. """
  53. assert khandy.is_numpy_image(image)
  54. src_height, src_width = image.shape[:2]
  55. scale = max(dst_size / src_width, dst_size / src_height)
  56. dst_width = int(round(scale * src_width))
  57. dst_height = int(round(scale * src_height))
  58. resized_image = cv2.resize(image, (dst_width, dst_height),
  59. interpolation=interp_codes[interpolation])
  60. if not return_scale:
  61. return resized_image
  62. else:
  63. return resized_image, scale
  64. def resize_image_long(image, dst_size, return_scale=False, interpolation='bilinear'):
  65. """Resize an image so that the length of longer side is dst_size while
  66. preserving the original aspect ratio.
  67. References:
  68. `resize_max` in `https://github.com/pjreddie/darknet/blob/master/src/image.c`
  69. """
  70. assert khandy.is_numpy_image(image)
  71. src_height, src_width = image.shape[:2]
  72. scale = min(dst_size / src_width, dst_size / src_height)
  73. dst_width = int(round(scale * src_width))
  74. dst_height = int(round(scale * src_height))
  75. resized_image = cv2.resize(image, (dst_width, dst_height),
  76. interpolation=interp_codes[interpolation])
  77. if not return_scale:
  78. return resized_image
  79. else:
  80. return resized_image, scale
  81. def letterbox_resize_image(image, dst_width, dst_height, border_value=0,
  82. return_scale=False, interpolation='bilinear'):
  83. """Resize an image preserving the original aspect ratio using padding.
  84. References:
  85. `letterbox_image` in `https://github.com/pjreddie/darknet/blob/master/src/image.c`
  86. """
  87. assert khandy.is_numpy_image(image)
  88. src_height, src_width = image.shape[:2]
  89. scale = min(dst_width / src_width, dst_height / src_height)
  90. resize_w = int(round(scale * src_width))
  91. resize_h = int(round(scale * src_height))
  92. resized_image = cv2.resize(image, (resize_w, resize_h),
  93. interpolation=interp_codes[interpolation])
  94. padded_shape = list(resized_image.shape)
  95. padded_shape[0] = dst_height
  96. padded_shape[1] = dst_width
  97. padded_image = np.full(padded_shape, border_value, image.dtype)
  98. dw = (dst_width - resize_w) // 2
  99. dh = (dst_height - resize_h) // 2
  100. padded_image[dh: resize_h + dh, dw: resize_w + dw, ...] = resized_image
  101. if not return_scale:
  102. return padded_image
  103. else:
  104. return padded_image, scale, dw, dh
  105. def resize_image_to_range(image, min_length, max_length, return_scale=False, interpolation='bilinear'):
  106. """Resizes an image so its dimensions are within the provided value.
  107. Rescale the shortest side of the image up to `min_length` pixels
  108. while keeping the largest side below `max_length` pixels without
  109. changing the aspect ratio. Often used in object detection (e.g. RCNN and SSH.)
  110. The output size can be described by two cases:
  111. 1. If the image can be rescaled so its shortest side is equal to the
  112. `min_length` without the other side exceeding `max_length`, then do so.
  113. 2. Otherwise, resize so the longest side is equal to `max_length`.
  114. Returns:
  115. resized_image: resized image so that
  116. min(dst_height, dst_width) == min_length or
  117. max(dst_height, dst_width) == max_length.
  118. References:
  119. `resize_to_range` in `models-master/research/object_detection/core/preprocessor.py`
  120. `prep_im_for_blob` in `py-faster-rcnn-master/lib/utils/blob.py`
  121. mmcv.imrescale
  122. """
  123. assert khandy.is_numpy_image(image)
  124. assert min_length < max_length
  125. src_height, src_width = image.shape[:2]
  126. min_side_length = min(src_width, src_height)
  127. max_side_length = max(src_width, src_height)
  128. scale = min_length / min_side_length
  129. if round(scale * max_side_length) > max_length:
  130. scale = max_length / max_side_length
  131. dst_width = int(round(scale * src_width))
  132. dst_height = int(round(scale * src_height))
  133. resized_image = cv2.resize(image, (dst_width, dst_height),
  134. interpolation=interp_codes[interpolation])
  135. if not return_scale:
  136. return resized_image
  137. else:
  138. return resized_image, scale