poly_nms.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import numpy as np
  2. from shapely.geometry import Polygon
  3. def points2polygon(points):
  4. """Convert k points to 1 polygon.
  5. Args:
  6. points (ndarray or list): A ndarray or a list of shape (2k)
  7. that indicates k points.
  8. Returns:
  9. polygon (Polygon): A polygon object.
  10. """
  11. if isinstance(points, list):
  12. points = np.array(points)
  13. assert isinstance(points, np.ndarray)
  14. assert (points.size % 2 == 0) and (points.size >= 8)
  15. point_mat = points.reshape([-1, 2])
  16. return Polygon(point_mat)
  17. def poly_intersection(poly_det, poly_gt, buffer=0.0001):
  18. """Calculate the intersection area between two polygon.
  19. Args:
  20. poly_det (Polygon): A polygon predicted by detector.
  21. poly_gt (Polygon): A gt polygon.
  22. Returns:
  23. intersection_area (float): The intersection area between two polygons.
  24. """
  25. assert isinstance(poly_det, Polygon)
  26. assert isinstance(poly_gt, Polygon)
  27. if buffer == 0:
  28. poly_inter = poly_det & poly_gt
  29. else:
  30. poly_inter = poly_det.buffer(buffer) & poly_gt.buffer(buffer)
  31. return poly_inter.area, poly_inter
  32. def poly_union(poly_det, poly_gt):
  33. """Calculate the union area between two polygon.
  34. Args:
  35. poly_det (Polygon): A polygon predicted by detector.
  36. poly_gt (Polygon): A gt polygon.
  37. Returns:
  38. union_area (float): The union area between two polygons.
  39. """
  40. assert isinstance(poly_det, Polygon)
  41. assert isinstance(poly_gt, Polygon)
  42. area_det = poly_det.area
  43. area_gt = poly_gt.area
  44. area_inters, _ = poly_intersection(poly_det, poly_gt)
  45. return area_det + area_gt - area_inters
  46. def valid_boundary(x, with_score=True):
  47. num = len(x)
  48. if num < 8:
  49. return False
  50. if num % 2 == 0 and (not with_score):
  51. return True
  52. if num % 2 == 1 and with_score:
  53. return True
  54. return False
  55. def boundary_iou(src, target):
  56. """Calculate the IOU between two boundaries.
  57. Args:
  58. src (list): Source boundary.
  59. target (list): Target boundary.
  60. Returns:
  61. iou (float): The iou between two boundaries.
  62. """
  63. assert valid_boundary(src, False)
  64. assert valid_boundary(target, False)
  65. src_poly = points2polygon(src)
  66. target_poly = points2polygon(target)
  67. return poly_iou(src_poly, target_poly)
  68. def poly_iou(poly_det, poly_gt):
  69. """Calculate the IOU between two polygons.
  70. Args:
  71. poly_det (Polygon): A polygon predicted by detector.
  72. poly_gt (Polygon): A gt polygon.
  73. Returns:
  74. iou (float): The IOU between two polygons.
  75. """
  76. assert isinstance(poly_det, Polygon)
  77. assert isinstance(poly_gt, Polygon)
  78. area_inters, _ = poly_intersection(poly_det, poly_gt)
  79. area_union = poly_union(poly_det, poly_gt)
  80. if area_union == 0:
  81. return 0.0
  82. return area_inters / area_union
  83. def poly_nms(polygons, threshold):
  84. assert isinstance(polygons, list)
  85. polygons = np.array(sorted(polygons, key=lambda x: x[-1]))
  86. keep_poly = []
  87. index = [i for i in range(polygons.shape[0])]
  88. while len(index) > 0:
  89. keep_poly.append(polygons[index[-1]].tolist())
  90. A = polygons[index[-1]][:-1]
  91. index = np.delete(index, -1)
  92. iou_list = np.zeros((len(index), ))
  93. for i in range(len(index)):
  94. B = polygons[index[i]][:-1]
  95. iou_list[i] = boundary_iou(A, B)
  96. remove_index = np.where(iou_list > threshold)
  97. index = np.delete(index, remove_index)
  98. return keep_poly