remove_bbox_overlap.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. from magic_pdf.config.drop_reason import DropReason
  2. from magic_pdf.libs.boxbase import _is_in, _is_part_overlap
  3. def _remove_overlap_between_bbox(bbox1, bbox2):
  4. if _is_part_overlap(bbox1, bbox2):
  5. ix0, iy0, ix1, iy1 = bbox1
  6. x0, y0, x1, y1 = bbox2
  7. diff_x = min(x1, ix1) - max(x0, ix0)
  8. diff_y = min(y1, iy1) - max(y0, iy0)
  9. if diff_y > diff_x:
  10. if x1 >= ix1:
  11. mid = (x0 + ix1) // 2
  12. ix1 = min(mid - 0.25, ix1)
  13. x0 = max(mid + 0.25, x0)
  14. else:
  15. mid = (ix0 + x1) // 2
  16. ix0 = max(mid + 0.25, ix0)
  17. x1 = min(mid - 0.25, x1)
  18. else:
  19. if y1 >= iy1:
  20. mid = (y0 + iy1) // 2
  21. y0 = max(mid + 0.25, y0)
  22. iy1 = min(iy1, mid - 0.25)
  23. else:
  24. mid = (iy0 + y1) // 2
  25. y1 = min(y1, mid - 0.25)
  26. iy0 = max(mid + 0.25, iy0)
  27. if ix1 > ix0 and iy1 > iy0 and y1 > y0 and x1 > x0:
  28. bbox1 = [ix0, iy0, ix1, iy1]
  29. bbox2 = [x0, y0, x1, y1]
  30. return bbox1, bbox2, None
  31. else:
  32. return bbox1, bbox2, DropReason.NEGATIVE_BBOX_AREA
  33. else:
  34. return bbox1, bbox2, None
  35. def _remove_overlap_between_bboxes(arr):
  36. drop_reasons = []
  37. N = len(arr)
  38. keeps = [True] * N
  39. res = [None] * N
  40. for i in range(N):
  41. for j in range(N):
  42. if i == j:
  43. continue
  44. if _is_in(arr[i]['bbox'], arr[j]['bbox']):
  45. keeps[i] = False
  46. for idx, v in enumerate(arr):
  47. if not keeps[idx]:
  48. continue
  49. for i in range(N):
  50. if res[i] is None:
  51. continue
  52. bbox1, bbox2, drop_reason = _remove_overlap_between_bbox(
  53. v['bbox'], res[i]['bbox']
  54. )
  55. if drop_reason is None:
  56. v['bbox'] = bbox1
  57. res[i]['bbox'] = bbox2
  58. else:
  59. if v['score'] > res[i]['score']:
  60. keeps[i] = False
  61. res[i] = None
  62. else:
  63. keeps[idx] = False
  64. drop_reasons.append(drop_reasons)
  65. if keeps[idx]:
  66. res[idx] = v
  67. return res, drop_reasons
  68. def remove_overlap_between_bbox_for_span(spans):
  69. arr = [{'bbox': span['bbox'], 'score': span.get('score', 0.1)} for span in spans]
  70. res, drop_reasons = _remove_overlap_between_bboxes(arr)
  71. ret = []
  72. for i in range(len(res)):
  73. if res[i] is None:
  74. continue
  75. spans[i]['bbox'] = res[i]['bbox']
  76. ret.append(spans[i])
  77. return ret, drop_reasons
  78. def remove_overlap_between_bbox_for_block(all_bboxes):
  79. arr = [{'bbox': bbox[:4], 'score': bbox[-1]} for bbox in all_bboxes]
  80. res, drop_reasons = _remove_overlap_between_bboxes(arr)
  81. ret = []
  82. for i in range(len(res)):
  83. if res[i] is None:
  84. continue
  85. all_bboxes[i][:4] = res[i]['bbox']
  86. ret.append(all_bboxes[i])
  87. return ret, drop_reasons