boxes_overlap.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import numpy as np
  2. def paired_intersection(boxes1, boxes2):
  3. """
  4. Args:
  5. boxes1: a numpy array with shape [N, 4] holding N boxes
  6. boxes2: a numpy array with shape [N, 4] holding N boxes
  7. Returns:
  8. a numpy array with shape [N,] representing itemwise intersection area
  9. References:
  10. `core.box_list_ops.matched_intersection` in Tensorflow object detection API
  11. Notes:
  12. can called as itemwise_intersection, matched_intersection, aligned_intersection
  13. """
  14. x_mins1, y_mins1, x_maxs1, y_maxs1 = np.split(boxes1[:,:4], 4, axis=1)
  15. x_mins2, y_mins2, x_maxs2, y_maxs2 = np.split(boxes2[:,:4], 4, axis=1)
  16. max_x_mins = np.maximum(x_mins1, x_mins2)
  17. min_x_maxs = np.minimum(x_maxs1, x_maxs2)
  18. max_y_mins = np.maximum(y_mins1, y_mins2)
  19. min_y_maxs = np.minimum(y_maxs1, y_maxs2)
  20. intersect_widths = np.maximum(0., min_x_maxs - max_x_mins)
  21. intersect_heights = np.maximum(0., min_y_maxs - max_y_mins)
  22. return intersect_widths * intersect_heights
  23. def pairwise_intersection(boxes1, boxes2):
  24. """Compute pairwise intersection areas between boxes.
  25. Args:
  26. boxes1: a numpy array with shape [N, 4] holding N boxes.
  27. boxes2: a numpy array with shape [M, 4] holding M boxes.
  28. Returns:
  29. a numpy array with shape [N, M] representing pairwise intersection area.
  30. References:
  31. `core.box_list_ops.intersection` in Tensorflow object detection API
  32. `utils.box_list_ops.intersection` in Tensorflow object detection API
  33. `core.evaluation.bbox_overlaps.bbox_overlaps` in mmdetection
  34. """
  35. rows = boxes1.shape[0]
  36. cols = boxes2.shape[0]
  37. intersect_areas = np.zeros((rows, cols), dtype=boxes1.dtype)
  38. if rows * cols == 0:
  39. return intersect_areas
  40. swap = False
  41. if boxes1.shape[0] > boxes2.shape[0]:
  42. boxes1, boxes2 = boxes2, boxes1
  43. intersect_areas = np.zeros((cols, rows), dtype=boxes1.dtype)
  44. swap = True
  45. for i in range(boxes1.shape[0]):
  46. x_begin = np.maximum(boxes1[i, 0], boxes2[:, 0])
  47. y_begin = np.maximum(boxes1[i, 1], boxes2[:, 1])
  48. x_end = np.minimum(boxes1[i, 2], boxes2[:, 2])
  49. y_end = np.minimum(boxes1[i, 3], boxes2[:, 3])
  50. x_end -= x_begin
  51. y_end -= y_begin
  52. np.maximum(x_end, 0, x_end)
  53. np.maximum(y_end, 0, y_end)
  54. x_end *= y_end
  55. intersect_areas[i, :] = x_end
  56. if swap:
  57. intersect_areas = intersect_areas.T
  58. return intersect_areas
  59. def pairwise_overlap_ratio(boxes1, boxes2, ratio_type='iou'):
  60. """Compute pairwise overlap ratio between boxes.
  61. Args:
  62. boxes1: a numpy array with shape [N, 4] holding N boxes
  63. boxes2: a numpy array with shape [M, 4] holding M boxes
  64. ratio_type:
  65. iou: Intersection-over-union (iou).
  66. ioa: Intersection-over-area (ioa) between two boxes box1 and box2 is defined as
  67. their intersection area over box2's area. Note that ioa is not symmetric,
  68. that is, IOA(box1, box2) != IOA(box2, box1).
  69. Returns:
  70. a numpy array with shape [N, M] representing pairwise overlap ratio.
  71. References:
  72. `utils.np_box_ops.iou` in Tensorflow object detection API
  73. `utils.np_box_ops.ioa` in Tensorflow object detection API
  74. `core.evaluation.bbox_overlaps.bbox_overlaps` in mmdetection
  75. http://ww2.mathworks.cn/help/vision/ref/bboxoverlapratio.html
  76. """
  77. intersect_area = pairwise_intersection(boxes1, boxes2)
  78. area1 = (boxes1[:, 2] - boxes1[:, 0]) * (boxes1[:, 3] - boxes1[:, 1])
  79. area2 = (boxes2[:, 2] - boxes2[:, 0]) * (boxes2[:, 3] - boxes2[:, 1])
  80. if ratio_type in ['union', 'iou']:
  81. union_area = np.expand_dims(area1, axis=1) - intersect_area
  82. union_area += np.expand_dims(area2, axis=0)
  83. intersect_area /= union_area
  84. elif ratio_type == 'min':
  85. min_area = np.minimum(np.expand_dims(area1, axis=1), np.expand_dims(area2, axis=0))
  86. intersect_area /= min_area
  87. elif ratio_type == 'ioa':
  88. intersect_area /= np.expand_dims(area2, axis=0)
  89. else:
  90. raise ValueError('Unsupported ratio_type. Got {}'.format(ratio_type))
  91. return intersect_area