layout_det_utils.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. from magic_pdf.layout.bbox_sort import X0_EXT_IDX, X0_IDX, X1_EXT_IDX, X1_IDX, Y0_IDX, Y1_EXT_IDX, Y1_IDX
  2. from magic_pdf.libs.boxbase import _is_bottom_full_overlap, _left_intersect, _right_intersect
  3. def find_all_left_bbox_direct(this_bbox, all_bboxes) -> list:
  4. """
  5. 在all_bboxes里找到所有右侧垂直方向上和this_bbox有重叠的bbox, 不用延长线
  6. 并且要考虑两个box左右相交的情况,如果相交了,那么右侧的box就不算最左侧。
  7. """
  8. left_boxes = [box for box in all_bboxes if box[X1_IDX] <= this_bbox[X0_IDX]
  9. and any([
  10. box[Y0_IDX] < this_bbox[Y0_IDX] < box[Y1_IDX], box[Y0_IDX] < this_bbox[Y1_IDX] < box[Y1_IDX],
  11. this_bbox[Y0_IDX] < box[Y0_IDX] < this_bbox[Y1_IDX], this_bbox[Y0_IDX] < box[Y1_IDX] < this_bbox[Y1_IDX],
  12. box[Y0_IDX]==this_bbox[Y0_IDX] and box[Y1_IDX]==this_bbox[Y1_IDX]]) or _left_intersect(box[:4], this_bbox[:4])]
  13. # 然后再过滤一下,找到水平上距离this_bbox最近的那个——x1最大的那个
  14. if len(left_boxes) > 0:
  15. left_boxes.sort(key=lambda x: x[X1_EXT_IDX] if x[X1_EXT_IDX] else x[X1_IDX], reverse=True)
  16. left_boxes = left_boxes[0]
  17. else:
  18. left_boxes = None
  19. return left_boxes
  20. def find_all_right_bbox_direct(this_bbox, all_bboxes) -> list:
  21. """
  22. 找到在this_bbox右侧且距离this_bbox距离最近的bbox.必须是直接遮挡的那种
  23. """
  24. right_bboxes = [box for box in all_bboxes if box[X0_IDX] >= this_bbox[X1_IDX]
  25. and any([
  26. this_bbox[Y0_IDX] < box[Y0_IDX] < this_bbox[Y1_IDX], this_bbox[Y0_IDX] < box[Y1_IDX] < this_bbox[Y1_IDX],
  27. box[Y0_IDX] < this_bbox[Y0_IDX] < box[Y1_IDX], box[Y0_IDX] < this_bbox[Y1_IDX] < box[Y1_IDX],
  28. box[Y0_IDX]==this_bbox[Y0_IDX] and box[Y1_IDX]==this_bbox[Y1_IDX]]) or _right_intersect(this_bbox[:4], box[:4])]
  29. if len(right_bboxes)>0:
  30. right_bboxes.sort(key=lambda x: x[X0_EXT_IDX] if x[X0_EXT_IDX] else x[X0_IDX])
  31. right_bboxes = right_bboxes[0]
  32. else:
  33. right_bboxes = None
  34. return right_bboxes
  35. def find_all_top_bbox_direct(this_bbox, all_bboxes) -> list:
  36. """
  37. 找到在this_bbox上侧且距离this_bbox距离最近的bbox.必须是直接遮挡的那种
  38. """
  39. top_bboxes = [box for box in all_bboxes if box[Y1_IDX] <= this_bbox[Y0_IDX] and any([
  40. box[X0_IDX] < this_bbox[X0_IDX] < box[X1_IDX], box[X0_IDX] < this_bbox[X1_IDX] < box[X1_IDX],
  41. this_bbox[X0_IDX] < box[X0_IDX] < this_bbox[X1_IDX], this_bbox[X0_IDX] < box[X1_IDX] < this_bbox[X1_IDX],
  42. box[X0_IDX]==this_bbox[X0_IDX] and box[X1_IDX]==this_bbox[X1_IDX]])]
  43. if len(top_bboxes)>0:
  44. top_bboxes.sort(key=lambda x: x[Y1_EXT_IDX] if x[Y1_EXT_IDX] else x[Y1_IDX], reverse=True)
  45. top_bboxes = top_bboxes[0]
  46. else:
  47. top_bboxes = None
  48. return top_bboxes
  49. def find_all_bottom_bbox_direct(this_bbox, all_bboxes) -> list:
  50. """
  51. 找到在this_bbox下侧且距离this_bbox距离最近的bbox.必须是直接遮挡的那种
  52. """
  53. bottom_bboxes = [box for box in all_bboxes if box[Y0_IDX] >= this_bbox[Y1_IDX] and any([
  54. this_bbox[X0_IDX] < box[X0_IDX] < this_bbox[X1_IDX], this_bbox[X0_IDX] < box[X1_IDX] < this_bbox[X1_IDX],
  55. box[X0_IDX] < this_bbox[X0_IDX] < box[X1_IDX], box[X0_IDX] < this_bbox[X1_IDX] < box[X1_IDX],
  56. box[X0_IDX]==this_bbox[X0_IDX] and box[X1_IDX]==this_bbox[X1_IDX]])]
  57. if len(bottom_bboxes)>0:
  58. bottom_bboxes.sort(key=lambda x: x[Y0_IDX])
  59. bottom_bboxes = bottom_bboxes[0]
  60. else:
  61. bottom_bboxes = None
  62. return bottom_bboxes
  63. # ===================================================================================================================
  64. def find_bottom_bbox_direct_from_right_edge(this_bbox, all_bboxes) -> list:
  65. """
  66. 找到在this_bbox下侧且距离this_bbox距离最近的bbox.必须是直接遮挡的那种
  67. """
  68. bottom_bboxes = [box for box in all_bboxes if box[Y0_IDX] >= this_bbox[Y1_IDX] and any([
  69. this_bbox[X0_IDX] < box[X0_IDX] < this_bbox[X1_IDX], this_bbox[X0_IDX] < box[X1_IDX] < this_bbox[X1_IDX],
  70. box[X0_IDX] < this_bbox[X0_IDX] < box[X1_IDX], box[X0_IDX] < this_bbox[X1_IDX] < box[X1_IDX],
  71. box[X0_IDX]==this_bbox[X0_IDX] and box[X1_IDX]==this_bbox[X1_IDX]])]
  72. if len(bottom_bboxes)>0:
  73. # y0最小, X1最大的那个,也就是box上边缘最靠近this_bbox的那个,并且还最靠右
  74. bottom_bboxes.sort(key=lambda x: x[Y0_IDX])
  75. bottom_bboxes = [box for box in bottom_bboxes if box[Y0_IDX]==bottom_bboxes[0][Y0_IDX]]
  76. # 然后再y1相同的情况下,找到x1最大的那个
  77. bottom_bboxes.sort(key=lambda x: x[X1_IDX], reverse=True)
  78. bottom_bboxes = bottom_bboxes[0]
  79. else:
  80. bottom_bboxes = None
  81. return bottom_bboxes
  82. def find_bottom_bbox_direct_from_left_edge(this_bbox, all_bboxes) -> list:
  83. """
  84. 找到在this_bbox下侧且距离this_bbox距离最近的bbox.必须是直接遮挡的那种
  85. """
  86. bottom_bboxes = [box for box in all_bboxes if box[Y0_IDX] >= this_bbox[Y1_IDX] and any([
  87. this_bbox[X0_IDX] < box[X0_IDX] < this_bbox[X1_IDX], this_bbox[X0_IDX] < box[X1_IDX] < this_bbox[X1_IDX],
  88. box[X0_IDX] < this_bbox[X0_IDX] < box[X1_IDX], box[X0_IDX] < this_bbox[X1_IDX] < box[X1_IDX],
  89. box[X0_IDX]==this_bbox[X0_IDX] and box[X1_IDX]==this_bbox[X1_IDX]])]
  90. if len(bottom_bboxes)>0:
  91. # y0最小, X0最小的那个
  92. bottom_bboxes.sort(key=lambda x: x[Y0_IDX])
  93. bottom_bboxes = [box for box in bottom_bboxes if box[Y0_IDX]==bottom_bboxes[0][Y0_IDX]]
  94. # 然后再y0相同的情况下,找到x0最小的那个
  95. bottom_bboxes.sort(key=lambda x: x[X0_IDX])
  96. bottom_bboxes = bottom_bboxes[0]
  97. else:
  98. bottom_bboxes = None
  99. return bottom_bboxes
  100. def find_top_bbox_direct_from_left_edge(this_bbox, all_bboxes) -> list:
  101. """
  102. 找到在this_bbox上侧且距离this_bbox距离最近的bbox.必须是直接遮挡的那种
  103. """
  104. top_bboxes = [box for box in all_bboxes if box[Y1_IDX] <= this_bbox[Y0_IDX] and any([
  105. box[X0_IDX] < this_bbox[X0_IDX] < box[X1_IDX], box[X0_IDX] < this_bbox[X1_IDX] < box[X1_IDX],
  106. this_bbox[X0_IDX] < box[X0_IDX] < this_bbox[X1_IDX], this_bbox[X0_IDX] < box[X1_IDX] < this_bbox[X1_IDX],
  107. box[X0_IDX]==this_bbox[X0_IDX] and box[X1_IDX]==this_bbox[X1_IDX]])]
  108. if len(top_bboxes)>0:
  109. # y1最大, X0最小的那个
  110. top_bboxes.sort(key=lambda x: x[Y1_IDX], reverse=True)
  111. top_bboxes = [box for box in top_bboxes if box[Y1_IDX]==top_bboxes[0][Y1_IDX]]
  112. # 然后再y1相同的情况下,找到x0最小的那个
  113. top_bboxes.sort(key=lambda x: x[X0_IDX])
  114. top_bboxes = top_bboxes[0]
  115. else:
  116. top_bboxes = None
  117. return top_bboxes
  118. def find_top_bbox_direct_from_right_edge(this_bbox, all_bboxes) -> list:
  119. """
  120. 找到在this_bbox上侧且距离this_bbox距离最近的bbox.必须是直接遮挡的那种
  121. """
  122. top_bboxes = [box for box in all_bboxes if box[Y1_IDX] <= this_bbox[Y0_IDX] and any([
  123. box[X0_IDX] < this_bbox[X0_IDX] < box[X1_IDX], box[X0_IDX] < this_bbox[X1_IDX] < box[X1_IDX],
  124. this_bbox[X0_IDX] < box[X0_IDX] < this_bbox[X1_IDX], this_bbox[X0_IDX] < box[X1_IDX] < this_bbox[X1_IDX],
  125. box[X0_IDX]==this_bbox[X0_IDX] and box[X1_IDX]==this_bbox[X1_IDX]])]
  126. if len(top_bboxes)>0:
  127. # y1最大, X1最大的那个
  128. top_bboxes.sort(key=lambda x: x[Y1_IDX], reverse=True)
  129. top_bboxes = [box for box in top_bboxes if box[Y1_IDX]==top_bboxes[0][Y1_IDX]]
  130. # 然后再y1相同的情况下,找到x1最大的那个
  131. top_bboxes.sort(key=lambda x: x[X1_IDX], reverse=True)
  132. top_bboxes = top_bboxes[0]
  133. else:
  134. top_bboxes = None
  135. return top_bboxes
  136. # ===================================================================================================================
  137. def get_left_edge_bboxes(all_bboxes) -> list:
  138. """
  139. 返回最左边的bbox
  140. """
  141. left_bboxes = [box for box in all_bboxes if find_all_left_bbox_direct(box, all_bboxes) is None]
  142. return left_bboxes
  143. def get_right_edge_bboxes(all_bboxes) -> list:
  144. """
  145. 返回最右边的bbox
  146. """
  147. right_bboxes = [box for box in all_bboxes if find_all_right_bbox_direct(box, all_bboxes) is None]
  148. return right_bboxes
  149. def fix_vertical_bbox_pos(bboxes:list):
  150. """
  151. 检查这批bbox在垂直方向是否有轻微的重叠,如果重叠了,就把重叠的bbox往下移动一点
  152. 在x方向上必须一个包含或者被包含,或者完全重叠,不能只有部分重叠
  153. """
  154. bboxes.sort(key=lambda x: x[Y0_IDX]) # 从上向下排列
  155. for i in range(0, len(bboxes)):
  156. for j in range(i+1, len(bboxes)):
  157. if _is_bottom_full_overlap(bboxes[i][:4], bboxes[j][:4]):
  158. # 如果两个bbox有部分重叠,那么就把下面的bbox往下移动一点
  159. bboxes[j][Y0_IDX] = bboxes[i][Y1_IDX] + 2 # 2是个经验值
  160. break
  161. return bboxes