mirror of
https://github.com/opendatalab/MinerU.git
synced 2026-11-02 21:42:09 +08:00
183 lines
8.9 KiB
Python
183 lines
8.9 KiB
Python
from magic_pdf.layout.bbox_sort import X0_EXT_IDX, X0_IDX, X1_EXT_IDX, X1_IDX, Y0_IDX, Y1_EXT_IDX, Y1_IDX
|
||
from magic_pdf.libs.boxbase import _is_bottom_full_overlap, _left_intersect, _right_intersect
|
||
|
||
|
||
def find_all_left_bbox_direct(this_bbox, all_bboxes) -> list:
|
||
"""
|
||
在all_bboxes里找到所有右侧垂直方向上和this_bbox有重叠的bbox, 不用延长线
|
||
并且要考虑两个box左右相交的情况,如果相交了,那么右侧的box就不算最左侧。
|
||
"""
|
||
left_boxes = [box for box in all_bboxes if box[X1_IDX] <= this_bbox[X0_IDX]
|
||
and any([
|
||
box[Y0_IDX] < this_bbox[Y0_IDX] < box[Y1_IDX], box[Y0_IDX] < this_bbox[Y1_IDX] < box[Y1_IDX],
|
||
this_bbox[Y0_IDX] < box[Y0_IDX] < this_bbox[Y1_IDX], this_bbox[Y0_IDX] < box[Y1_IDX] < this_bbox[Y1_IDX],
|
||
box[Y0_IDX]==this_bbox[Y0_IDX] and box[Y1_IDX]==this_bbox[Y1_IDX]]) or _left_intersect(box[:4], this_bbox[:4])]
|
||
|
||
# 然后再过滤一下,找到水平上距离this_bbox最近的那个——x1最大的那个
|
||
if len(left_boxes) > 0:
|
||
left_boxes.sort(key=lambda x: x[X1_EXT_IDX] if x[X1_EXT_IDX] else x[X1_IDX], reverse=True)
|
||
left_boxes = left_boxes[0]
|
||
else:
|
||
left_boxes = None
|
||
return left_boxes
|
||
|
||
def find_all_right_bbox_direct(this_bbox, all_bboxes) -> list:
|
||
"""
|
||
找到在this_bbox右侧且距离this_bbox距离最近的bbox.必须是直接遮挡的那种
|
||
"""
|
||
right_bboxes = [box for box in all_bboxes if box[X0_IDX] >= this_bbox[X1_IDX]
|
||
and any([
|
||
this_bbox[Y0_IDX] < box[Y0_IDX] < this_bbox[Y1_IDX], this_bbox[Y0_IDX] < box[Y1_IDX] < this_bbox[Y1_IDX],
|
||
box[Y0_IDX] < this_bbox[Y0_IDX] < box[Y1_IDX], box[Y0_IDX] < this_bbox[Y1_IDX] < box[Y1_IDX],
|
||
box[Y0_IDX]==this_bbox[Y0_IDX] and box[Y1_IDX]==this_bbox[Y1_IDX]]) or _right_intersect(this_bbox[:4], box[:4])]
|
||
|
||
if len(right_bboxes)>0:
|
||
right_bboxes.sort(key=lambda x: x[X0_EXT_IDX] if x[X0_EXT_IDX] else x[X0_IDX])
|
||
right_bboxes = right_bboxes[0]
|
||
else:
|
||
right_bboxes = None
|
||
return right_bboxes
|
||
|
||
def find_all_top_bbox_direct(this_bbox, all_bboxes) -> list:
|
||
"""
|
||
找到在this_bbox上侧且距离this_bbox距离最近的bbox.必须是直接遮挡的那种
|
||
"""
|
||
top_bboxes = [box for box in all_bboxes if box[Y1_IDX] <= this_bbox[Y0_IDX] and any([
|
||
box[X0_IDX] < this_bbox[X0_IDX] < box[X1_IDX], box[X0_IDX] < this_bbox[X1_IDX] < box[X1_IDX],
|
||
this_bbox[X0_IDX] < box[X0_IDX] < this_bbox[X1_IDX], this_bbox[X0_IDX] < box[X1_IDX] < this_bbox[X1_IDX],
|
||
box[X0_IDX]==this_bbox[X0_IDX] and box[X1_IDX]==this_bbox[X1_IDX]])]
|
||
|
||
if len(top_bboxes)>0:
|
||
top_bboxes.sort(key=lambda x: x[Y1_EXT_IDX] if x[Y1_EXT_IDX] else x[Y1_IDX], reverse=True)
|
||
top_bboxes = top_bboxes[0]
|
||
else:
|
||
top_bboxes = None
|
||
return top_bboxes
|
||
|
||
def find_all_bottom_bbox_direct(this_bbox, all_bboxes) -> list:
|
||
"""
|
||
找到在this_bbox下侧且距离this_bbox距离最近的bbox.必须是直接遮挡的那种
|
||
"""
|
||
bottom_bboxes = [box for box in all_bboxes if box[Y0_IDX] >= this_bbox[Y1_IDX] and any([
|
||
this_bbox[X0_IDX] < box[X0_IDX] < this_bbox[X1_IDX], this_bbox[X0_IDX] < box[X1_IDX] < this_bbox[X1_IDX],
|
||
box[X0_IDX] < this_bbox[X0_IDX] < box[X1_IDX], box[X0_IDX] < this_bbox[X1_IDX] < box[X1_IDX],
|
||
box[X0_IDX]==this_bbox[X0_IDX] and box[X1_IDX]==this_bbox[X1_IDX]])]
|
||
|
||
if len(bottom_bboxes)>0:
|
||
bottom_bboxes.sort(key=lambda x: x[Y0_IDX])
|
||
bottom_bboxes = bottom_bboxes[0]
|
||
else:
|
||
bottom_bboxes = None
|
||
return bottom_bboxes
|
||
|
||
# ===================================================================================================================
|
||
def find_bottom_bbox_direct_from_right_edge(this_bbox, all_bboxes) -> list:
|
||
"""
|
||
找到在this_bbox下侧且距离this_bbox距离最近的bbox.必须是直接遮挡的那种
|
||
"""
|
||
bottom_bboxes = [box for box in all_bboxes if box[Y0_IDX] >= this_bbox[Y1_IDX] and any([
|
||
this_bbox[X0_IDX] < box[X0_IDX] < this_bbox[X1_IDX], this_bbox[X0_IDX] < box[X1_IDX] < this_bbox[X1_IDX],
|
||
box[X0_IDX] < this_bbox[X0_IDX] < box[X1_IDX], box[X0_IDX] < this_bbox[X1_IDX] < box[X1_IDX],
|
||
box[X0_IDX]==this_bbox[X0_IDX] and box[X1_IDX]==this_bbox[X1_IDX]])]
|
||
|
||
if len(bottom_bboxes)>0:
|
||
# y0最小, X1最大的那个,也就是box上边缘最靠近this_bbox的那个,并且还最靠右
|
||
bottom_bboxes.sort(key=lambda x: x[Y0_IDX])
|
||
bottom_bboxes = [box for box in bottom_bboxes if box[Y0_IDX]==bottom_bboxes[0][Y0_IDX]]
|
||
# 然后再y1相同的情况下,找到x1最大的那个
|
||
bottom_bboxes.sort(key=lambda x: x[X1_IDX], reverse=True)
|
||
bottom_bboxes = bottom_bboxes[0]
|
||
else:
|
||
bottom_bboxes = None
|
||
return bottom_bboxes
|
||
|
||
def find_bottom_bbox_direct_from_left_edge(this_bbox, all_bboxes) -> list:
|
||
"""
|
||
找到在this_bbox下侧且距离this_bbox距离最近的bbox.必须是直接遮挡的那种
|
||
"""
|
||
bottom_bboxes = [box for box in all_bboxes if box[Y0_IDX] >= this_bbox[Y1_IDX] and any([
|
||
this_bbox[X0_IDX] < box[X0_IDX] < this_bbox[X1_IDX], this_bbox[X0_IDX] < box[X1_IDX] < this_bbox[X1_IDX],
|
||
box[X0_IDX] < this_bbox[X0_IDX] < box[X1_IDX], box[X0_IDX] < this_bbox[X1_IDX] < box[X1_IDX],
|
||
box[X0_IDX]==this_bbox[X0_IDX] and box[X1_IDX]==this_bbox[X1_IDX]])]
|
||
|
||
if len(bottom_bboxes)>0:
|
||
# y0最小, X0最小的那个
|
||
bottom_bboxes.sort(key=lambda x: x[Y0_IDX])
|
||
bottom_bboxes = [box for box in bottom_bboxes if box[Y0_IDX]==bottom_bboxes[0][Y0_IDX]]
|
||
# 然后再y0相同的情况下,找到x0最小的那个
|
||
bottom_bboxes.sort(key=lambda x: x[X0_IDX])
|
||
bottom_bboxes = bottom_bboxes[0]
|
||
else:
|
||
bottom_bboxes = None
|
||
return bottom_bboxes
|
||
|
||
def find_top_bbox_direct_from_left_edge(this_bbox, all_bboxes) -> list:
|
||
"""
|
||
找到在this_bbox上侧且距离this_bbox距离最近的bbox.必须是直接遮挡的那种
|
||
"""
|
||
top_bboxes = [box for box in all_bboxes if box[Y1_IDX] <= this_bbox[Y0_IDX] and any([
|
||
box[X0_IDX] < this_bbox[X0_IDX] < box[X1_IDX], box[X0_IDX] < this_bbox[X1_IDX] < box[X1_IDX],
|
||
this_bbox[X0_IDX] < box[X0_IDX] < this_bbox[X1_IDX], this_bbox[X0_IDX] < box[X1_IDX] < this_bbox[X1_IDX],
|
||
box[X0_IDX]==this_bbox[X0_IDX] and box[X1_IDX]==this_bbox[X1_IDX]])]
|
||
|
||
if len(top_bboxes)>0:
|
||
# y1最大, X0最小的那个
|
||
top_bboxes.sort(key=lambda x: x[Y1_IDX], reverse=True)
|
||
top_bboxes = [box for box in top_bboxes if box[Y1_IDX]==top_bboxes[0][Y1_IDX]]
|
||
# 然后再y1相同的情况下,找到x0最小的那个
|
||
top_bboxes.sort(key=lambda x: x[X0_IDX])
|
||
top_bboxes = top_bboxes[0]
|
||
else:
|
||
top_bboxes = None
|
||
return top_bboxes
|
||
|
||
def find_top_bbox_direct_from_right_edge(this_bbox, all_bboxes) -> list:
|
||
"""
|
||
找到在this_bbox上侧且距离this_bbox距离最近的bbox.必须是直接遮挡的那种
|
||
"""
|
||
top_bboxes = [box for box in all_bboxes if box[Y1_IDX] <= this_bbox[Y0_IDX] and any([
|
||
box[X0_IDX] < this_bbox[X0_IDX] < box[X1_IDX], box[X0_IDX] < this_bbox[X1_IDX] < box[X1_IDX],
|
||
this_bbox[X0_IDX] < box[X0_IDX] < this_bbox[X1_IDX], this_bbox[X0_IDX] < box[X1_IDX] < this_bbox[X1_IDX],
|
||
box[X0_IDX]==this_bbox[X0_IDX] and box[X1_IDX]==this_bbox[X1_IDX]])]
|
||
|
||
if len(top_bboxes)>0:
|
||
# y1最大, X1最大的那个
|
||
top_bboxes.sort(key=lambda x: x[Y1_IDX], reverse=True)
|
||
top_bboxes = [box for box in top_bboxes if box[Y1_IDX]==top_bboxes[0][Y1_IDX]]
|
||
# 然后再y1相同的情况下,找到x1最大的那个
|
||
top_bboxes.sort(key=lambda x: x[X1_IDX], reverse=True)
|
||
top_bboxes = top_bboxes[0]
|
||
else:
|
||
top_bboxes = None
|
||
return top_bboxes
|
||
|
||
# ===================================================================================================================
|
||
|
||
def get_left_edge_bboxes(all_bboxes) -> list:
|
||
"""
|
||
返回最左边的bbox
|
||
"""
|
||
left_bboxes = [box for box in all_bboxes if find_all_left_bbox_direct(box, all_bboxes) is None]
|
||
return left_bboxes
|
||
|
||
def get_right_edge_bboxes(all_bboxes) -> list:
|
||
"""
|
||
返回最右边的bbox
|
||
"""
|
||
right_bboxes = [box for box in all_bboxes if find_all_right_bbox_direct(box, all_bboxes) is None]
|
||
return right_bboxes
|
||
|
||
def fix_vertical_bbox_pos(bboxes:list):
|
||
"""
|
||
检查这批bbox在垂直方向是否有轻微的重叠,如果重叠了,就把重叠的bbox往下移动一点
|
||
在x方向上必须一个包含或者被包含,或者完全重叠,不能只有部分重叠
|
||
"""
|
||
bboxes.sort(key=lambda x: x[Y0_IDX]) # 从上向下排列
|
||
for i in range(0, len(bboxes)):
|
||
for j in range(i+1, len(bboxes)):
|
||
if _is_bottom_full_overlap(bboxes[i][:4], bboxes[j][:4]):
|
||
# 如果两个bbox有部分重叠,那么就把下面的bbox往下移动一点
|
||
bboxes[j][Y0_IDX] = bboxes[i][Y1_IDX] + 2 # 2是个经验值
|
||
break
|
||
return bboxes
|