crop_or_pad.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import numbers
  2. import numpy as np
  3. def crop_or_pad(image, x_min, y_min, x_max, y_max, border_value=0):
  4. """
  5. See Also:
  6. translate_image
  7. References:
  8. tf.image.resize_image_with_crop_or_pad
  9. """
  10. assert image.ndim in [2, 3]
  11. assert isinstance(x_min, numbers.Integral) and isinstance(y_min, numbers.Integral)
  12. assert isinstance(x_max, numbers.Integral) and isinstance(y_max, numbers.Integral)
  13. assert (x_min <= x_max) and (y_min <= y_max)
  14. src_height, src_width = image.shape[:2]
  15. dst_height, dst_width = y_max - y_min + 1, x_max - x_min + 1
  16. channels = 1 if image.ndim == 2 else image.shape[2]
  17. if image.ndim == 2:
  18. dst_image_shape = (dst_height, dst_width)
  19. else:
  20. dst_image_shape = (dst_height, dst_width, channels)
  21. if isinstance(border_value, numbers.Real):
  22. dst_image = np.full(dst_image_shape, border_value, dtype=image.dtype)
  23. elif isinstance(border_value, tuple):
  24. assert len(border_value) == channels, \
  25. 'Expected the num of elements in tuple equals the channels' \
  26. 'of input image. Found {} vs {}'.format(
  27. len(border_value), channels)
  28. if channels == 1:
  29. dst_image = np.full(dst_image_shape, border_value[0], dtype=image.dtype)
  30. else:
  31. border_value = np.asarray(border_value, dtype=image.dtype)
  32. dst_image = np.empty(dst_image_shape, dtype=image.dtype)
  33. dst_image[:] = border_value
  34. else:
  35. raise ValueError(
  36. 'Invalid type {} for `border_value`.'.format(type(border_value)))
  37. src_x_begin = max(x_min, 0)
  38. src_x_end = min(x_max + 1, src_width)
  39. dst_x_begin = src_x_begin - x_min
  40. dst_x_end = src_x_end - x_min
  41. src_y_begin = max(y_min, 0)
  42. src_y_end = min(y_max + 1, src_height)
  43. dst_y_begin = src_y_begin - y_min
  44. dst_y_end = src_y_end - y_min
  45. if (src_x_begin >= src_x_end) or (src_y_begin >= src_y_end):
  46. return dst_image
  47. dst_image[dst_y_begin: dst_y_end, dst_x_begin: dst_x_end, ...] = \
  48. image[src_y_begin: src_y_end, src_x_begin: src_x_end, ...]
  49. return dst_image
  50. def center_crop(image, dst_width, dst_height):
  51. assert image.ndim in [2, 3]
  52. assert isinstance(dst_width, numbers.Integral) and isinstance(dst_height, numbers.Integral)
  53. assert (image.shape[0] >= dst_height) and (image.shape[1] >= dst_width)
  54. crop_top = (image.shape[0] - dst_height) // 2
  55. crop_left = (image.shape[1] - dst_width) // 2
  56. dst_image = image[crop_top: dst_height + crop_top,
  57. crop_left: dst_width + crop_left, ...]
  58. return dst_image
  59. def crop_or_pad_coords(boxes, image_width, image_height):
  60. """
  61. References:
  62. `mmcv.impad`
  63. `pad` in https://github.com/kpzhang93/MTCNN_face_detection_alignment
  64. `MtcnnDetector.pad` in https://github.com/AITTSMD/MTCNN-Tensorflow
  65. """
  66. x_mins = boxes[:, 0]
  67. y_mins = boxes[:, 1]
  68. x_maxs = boxes[:, 2]
  69. y_maxs = boxes[:, 3]
  70. dst_widths = x_maxs - x_mins + 1
  71. dst_heights = y_maxs - y_mins + 1
  72. src_x_begin = np.maximum(x_mins, 0)
  73. src_x_end = np.minimum(x_maxs + 1, image_width)
  74. dst_x_begin = src_x_begin - x_mins
  75. dst_x_end = src_x_end - x_mins
  76. src_y_begin = np.maximum(y_mins, 0)
  77. src_y_end = np.minimum(y_maxs + 1, image_height)
  78. dst_y_begin = src_y_begin - y_mins
  79. dst_y_end = src_y_end - y_mins
  80. coords = np.stack([dst_y_begin, dst_y_end, dst_x_begin, dst_x_end,
  81. src_y_begin, src_y_end, src_x_begin, src_x_end,
  82. dst_heights, dst_widths], axis=0)
  83. return coords