magic-pdf 0.7.1__py3-none-any.whl → 0.8.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- magic_pdf/dict2md/ocr_mkcontent.py +130 -76
- magic_pdf/integrations/__init__.py +0 -0
- magic_pdf/integrations/rag/__init__.py +0 -0
- magic_pdf/integrations/rag/api.py +82 -0
- magic_pdf/integrations/rag/type.py +82 -0
- magic_pdf/integrations/rag/utils.py +285 -0
- magic_pdf/layout/layout_sort.py +472 -283
- magic_pdf/libs/boxbase.py +188 -149
- magic_pdf/libs/draw_bbox.py +113 -87
- magic_pdf/libs/ocr_content_type.py +21 -18
- magic_pdf/libs/version.py +1 -1
- magic_pdf/model/doc_analyze_by_custom_model.py +14 -2
- magic_pdf/model/magic_model.py +283 -166
- magic_pdf/model/model_list.py +8 -0
- magic_pdf/model/pdf_extract_kit.py +105 -15
- magic_pdf/model/pek_sub_modules/self_modify.py +84 -0
- magic_pdf/para/para_split_v2.py +26 -27
- magic_pdf/pdf_parse_union_core.py +34 -6
- magic_pdf/pipe/AbsPipe.py +4 -1
- magic_pdf/pipe/OCRPipe.py +7 -4
- magic_pdf/pipe/TXTPipe.py +7 -4
- magic_pdf/pipe/UNIPipe.py +11 -6
- magic_pdf/pre_proc/ocr_detect_all_bboxes.py +12 -3
- magic_pdf/pre_proc/ocr_dict_merge.py +60 -59
- magic_pdf/tools/cli.py +56 -29
- magic_pdf/tools/cli_dev.py +61 -64
- magic_pdf/tools/common.py +57 -37
- magic_pdf/user_api.py +17 -9
- {magic_pdf-0.7.1.dist-info → magic_pdf-0.8.1.dist-info}/METADATA +72 -27
- {magic_pdf-0.7.1.dist-info → magic_pdf-0.8.1.dist-info}/RECORD +34 -29
- {magic_pdf-0.7.1.dist-info → magic_pdf-0.8.1.dist-info}/LICENSE.md +0 -0
- {magic_pdf-0.7.1.dist-info → magic_pdf-0.8.1.dist-info}/WHEEL +0 -0
- {magic_pdf-0.7.1.dist-info → magic_pdf-0.8.1.dist-info}/entry_points.txt +0 -0
- {magic_pdf-0.7.1.dist-info → magic_pdf-0.8.1.dist-info}/top_level.txt +0 -0
magic_pdf/libs/boxbase.py
CHANGED
@@ -1,168 +1,166 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
from loguru import logger
|
4
1
|
import math
|
5
2
|
|
3
|
+
|
6
4
|
def _is_in_or_part_overlap(box1, box2) -> bool:
|
7
|
-
"""
|
8
|
-
两个bbox是否有部分重叠或者包含
|
9
|
-
"""
|
5
|
+
"""两个bbox是否有部分重叠或者包含."""
|
10
6
|
if box1 is None or box2 is None:
|
11
7
|
return False
|
12
|
-
|
8
|
+
|
13
9
|
x0_1, y0_1, x1_1, y1_1 = box1
|
14
10
|
x0_2, y0_2, x1_2, y1_2 = box2
|
15
11
|
|
16
12
|
return not (x1_1 < x0_2 or # box1在box2的左边
|
17
13
|
x0_1 > x1_2 or # box1在box2的右边
|
18
14
|
y1_1 < y0_2 or # box1在box2的上边
|
19
|
-
y0_1 > y1_2)
|
15
|
+
y0_1 > y1_2) # box1在box2的下边
|
20
16
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
"""
|
17
|
+
|
18
|
+
def _is_in_or_part_overlap_with_area_ratio(box1,
|
19
|
+
box2,
|
20
|
+
area_ratio_threshold=0.6):
|
21
|
+
"""判断box1是否在box2里面,或者box1和box2有部分重叠,且重叠面积占box1的比例超过area_ratio_threshold."""
|
26
22
|
if box1 is None or box2 is None:
|
27
23
|
return False
|
28
|
-
|
24
|
+
|
29
25
|
x0_1, y0_1, x1_1, y1_1 = box1
|
30
26
|
x0_2, y0_2, x1_2, y1_2 = box2
|
31
27
|
|
32
28
|
if not _is_in_or_part_overlap(box1, box2):
|
33
29
|
return False
|
34
|
-
|
30
|
+
|
35
31
|
# 计算重叠面积
|
36
32
|
x_left = max(x0_1, x0_2)
|
37
33
|
y_top = max(y0_1, y0_2)
|
38
34
|
x_right = min(x1_1, x1_2)
|
39
35
|
y_bottom = min(y1_1, y1_2)
|
40
36
|
overlap_area = (x_right - x_left) * (y_bottom - y_top)
|
41
|
-
|
37
|
+
|
42
38
|
# 计算box1的面积
|
43
39
|
box1_area = (x1_1 - x0_1) * (y1_1 - y0_1)
|
44
|
-
|
40
|
+
|
45
41
|
return overlap_area / box1_area > area_ratio_threshold
|
46
|
-
|
47
|
-
|
42
|
+
|
43
|
+
|
48
44
|
def _is_in(box1, box2) -> bool:
|
49
|
-
"""
|
50
|
-
box1是否完全在box2里面
|
51
|
-
"""
|
45
|
+
"""box1是否完全在box2里面."""
|
52
46
|
x0_1, y0_1, x1_1, y1_1 = box1
|
53
47
|
x0_2, y0_2, x1_2, y1_2 = box2
|
54
48
|
|
55
49
|
return (x0_1 >= x0_2 and # box1的左边界不在box2的左边外
|
56
50
|
y0_1 >= y0_2 and # box1的上边界不在box2的上边外
|
57
51
|
x1_1 <= x1_2 and # box1的右边界不在box2的右边外
|
58
|
-
y1_1 <= y1_2)
|
59
|
-
|
52
|
+
y1_1 <= y1_2) # box1的下边界不在box2的下边外
|
53
|
+
|
54
|
+
|
60
55
|
def _is_part_overlap(box1, box2) -> bool:
|
61
|
-
"""
|
62
|
-
两个bbox是否有部分重叠,但不完全包含
|
63
|
-
"""
|
56
|
+
"""两个bbox是否有部分重叠,但不完全包含."""
|
64
57
|
if box1 is None or box2 is None:
|
65
58
|
return False
|
66
|
-
|
59
|
+
|
67
60
|
return _is_in_or_part_overlap(box1, box2) and not _is_in(box1, box2)
|
68
61
|
|
62
|
+
|
69
63
|
def _left_intersect(left_box, right_box):
|
70
|
-
"检查两个box的左边界是否有交集,也就是left_box的右边界是否在right_box
|
64
|
+
"""检查两个box的左边界是否有交集,也就是left_box的右边界是否在right_box的左边界内."""
|
71
65
|
if left_box is None or right_box is None:
|
72
66
|
return False
|
73
|
-
|
67
|
+
|
74
68
|
x0_1, y0_1, x1_1, y1_1 = left_box
|
75
69
|
x0_2, y0_2, x1_2, y1_2 = right_box
|
76
|
-
|
77
|
-
return x1_1>x0_2 and x0_1<x0_2 and (y0_1<=y0_2<=
|
70
|
+
|
71
|
+
return x1_1 > x0_2 and x0_1 < x0_2 and (y0_1 <= y0_2 <= y1_1
|
72
|
+
or y0_1 <= y1_2 <= y1_1)
|
73
|
+
|
78
74
|
|
79
75
|
def _right_intersect(left_box, right_box):
|
80
|
-
"""
|
81
|
-
检查box是否在右侧边界有交集,也就是left_box的左边界是否在right_box的右边界内
|
82
|
-
"""
|
76
|
+
"""检查box是否在右侧边界有交集,也就是left_box的左边界是否在right_box的右边界内."""
|
83
77
|
if left_box is None or right_box is None:
|
84
78
|
return False
|
85
|
-
|
79
|
+
|
86
80
|
x0_1, y0_1, x1_1, y1_1 = left_box
|
87
81
|
x0_2, y0_2, x1_2, y1_2 = right_box
|
88
|
-
|
89
|
-
return x0_1<x1_2 and x1_1>x1_2 and (y0_1<=y0_2<=
|
82
|
+
|
83
|
+
return x0_1 < x1_2 and x1_1 > x1_2 and (y0_1 <= y0_2 <= y1_1
|
84
|
+
or y0_1 <= y1_2 <= y1_1)
|
90
85
|
|
91
86
|
|
92
87
|
def _is_vertical_full_overlap(box1, box2, x_torlence=2):
|
93
|
-
"""
|
94
|
-
x方向上:要么box1包含box2, 要么box2包含box1。不能部分包含
|
95
|
-
y方向上:box1和box2有重叠
|
96
|
-
"""
|
88
|
+
"""x方向上:要么box1包含box2, 要么box2包含box1。不能部分包含 y方向上:box1和box2有重叠."""
|
97
89
|
# 解析box的坐标
|
98
90
|
x11, y11, x12, y12 = box1 # 左上角和右下角的坐标 (x1, y1, x2, y2)
|
99
91
|
x21, y21, x22, y22 = box2
|
100
92
|
|
101
93
|
# 在x轴方向上,box1是否包含box2 或 box2包含box1
|
102
|
-
contains_in_x = (x11-x_torlence <= x21 and x12+x_torlence >= x22) or (
|
94
|
+
contains_in_x = (x11 - x_torlence <= x21 and x12 + x_torlence >= x22) or (
|
95
|
+
x21 - x_torlence <= x11 and x22 + x_torlence >= x12)
|
103
96
|
|
104
97
|
# 在y轴方向上,box1和box2是否有重叠
|
105
98
|
overlap_in_y = not (y12 < y21 or y11 > y22)
|
106
99
|
|
107
100
|
return contains_in_x and overlap_in_y
|
108
|
-
|
101
|
+
|
109
102
|
|
110
103
|
def _is_bottom_full_overlap(box1, box2, y_tolerance=2):
|
111
|
-
"""
|
112
|
-
|
113
|
-
这个函数和_is_vertical-full_overlap的区别是,这个函数允许box1和box2在x方向上有轻微的重叠,允许一定的模糊度
|
114
|
-
"""
|
104
|
+
"""检查box1下方和box2的上方有轻微的重叠,轻微程度收到y_tolerance的限制 这个函数和_is_vertical-
|
105
|
+
full_overlap的区别是,这个函数允许box1和box2在x方向上有轻微的重叠,允许一定的模糊度."""
|
115
106
|
if box1 is None or box2 is None:
|
116
107
|
return False
|
117
|
-
|
108
|
+
|
118
109
|
x0_1, y0_1, x1_1, y1_1 = box1
|
119
110
|
x0_2, y0_2, x1_2, y1_2 = box2
|
120
111
|
tolerance_margin = 2
|
121
|
-
is_xdir_full_overlap = (
|
122
|
-
|
123
|
-
|
112
|
+
is_xdir_full_overlap = (
|
113
|
+
(x0_1 - tolerance_margin <= x0_2 <= x1_1 + tolerance_margin
|
114
|
+
and x0_1 - tolerance_margin <= x1_2 <= x1_1 + tolerance_margin)
|
115
|
+
or (x0_2 - tolerance_margin <= x0_1 <= x1_2 + tolerance_margin
|
116
|
+
and x0_2 - tolerance_margin <= x1_1 <= x1_2 + tolerance_margin))
|
117
|
+
|
118
|
+
return y0_2 < y1_1 and 0 < (y1_1 -
|
119
|
+
y0_2) < y_tolerance and is_xdir_full_overlap
|
120
|
+
|
121
|
+
|
122
|
+
def _is_left_overlap(
|
123
|
+
box1,
|
124
|
+
box2,
|
125
|
+
):
|
126
|
+
"""检查box1的左侧是否和box2有重叠 在Y方向上可以是部分重叠或者是完全重叠。不分box1和box2的上下关系,也就是无论box1在box2下
|
127
|
+
方还是box2在box1下方,都可以检测到重叠。 X方向上."""
|
124
128
|
|
125
|
-
def _is_left_overlap(box1, box2,):
|
126
|
-
"""
|
127
|
-
检查box1的左侧是否和box2有重叠
|
128
|
-
在Y方向上可以是部分重叠或者是完全重叠。不分box1和box2的上下关系,也就是无论box1在box2下方还是box2在box1下方,都可以检测到重叠。
|
129
|
-
X方向上
|
130
|
-
"""
|
131
129
|
def __overlap_y(Ay1, Ay2, By1, By2):
|
132
130
|
return max(0, min(Ay2, By2) - max(Ay1, By1))
|
133
|
-
|
131
|
+
|
134
132
|
if box1 is None or box2 is None:
|
135
133
|
return False
|
136
|
-
|
134
|
+
|
137
135
|
x0_1, y0_1, x1_1, y1_1 = box1
|
138
136
|
x0_2, y0_2, x1_2, y1_2 = box2
|
139
|
-
|
137
|
+
|
140
138
|
y_overlap_len = __overlap_y(y0_1, y1_1, y0_2, y1_2)
|
141
|
-
ratio_1 = 1.0 * y_overlap_len / (y1_1 - y0_1) if y1_1-y0_1!=0 else 0
|
142
|
-
ratio_2 = 1.0 * y_overlap_len / (y1_2 - y0_2) if y1_2-y0_2!=0 else 0
|
139
|
+
ratio_1 = 1.0 * y_overlap_len / (y1_1 - y0_1) if y1_1 - y0_1 != 0 else 0
|
140
|
+
ratio_2 = 1.0 * y_overlap_len / (y1_2 - y0_2) if y1_2 - y0_2 != 0 else 0
|
143
141
|
vertical_overlap_cond = ratio_1 >= 0.5 or ratio_2 >= 0.5
|
144
|
-
|
145
|
-
#vertical_overlap_cond = y0_1<=y0_2<=y1_1 or y0_1<=y1_2<=y1_1 or y0_2<=y0_1<=y1_2 or y0_2<=y1_1<=y1_2
|
146
|
-
return x0_1<=x0_2<=x1_1 and vertical_overlap_cond
|
142
|
+
|
143
|
+
# vertical_overlap_cond = y0_1<=y0_2<=y1_1 or y0_1<=y1_2<=y1_1 or y0_2<=y0_1<=y1_2 or y0_2<=y1_1<=y1_2
|
144
|
+
return x0_1 <= x0_2 <= x1_1 and vertical_overlap_cond
|
147
145
|
|
148
146
|
|
149
|
-
def __is_overlaps_y_exceeds_threshold(bbox1,
|
147
|
+
def __is_overlaps_y_exceeds_threshold(bbox1,
|
148
|
+
bbox2,
|
149
|
+
overlap_ratio_threshold=0.8):
|
150
150
|
"""检查两个bbox在y轴上是否有重叠,并且该重叠区域的高度占两个bbox高度更低的那个超过80%"""
|
151
151
|
_, y0_1, _, y1_1 = bbox1
|
152
152
|
_, y0_2, _, y1_2 = bbox2
|
153
153
|
|
154
154
|
overlap = max(0, min(y1_1, y1_2) - max(y0_1, y0_2))
|
155
155
|
height1, height2 = y1_1 - y0_1, y1_2 - y0_2
|
156
|
-
max_height = max(height1, height2)
|
156
|
+
# max_height = max(height1, height2)
|
157
157
|
min_height = min(height1, height2)
|
158
158
|
|
159
159
|
return (overlap / min_height) > overlap_ratio_threshold
|
160
160
|
|
161
161
|
|
162
|
-
|
163
162
|
def calculate_iou(bbox1, bbox2):
|
164
|
-
"""
|
165
|
-
计算两个边界框的交并比(IOU)。
|
163
|
+
"""计算两个边界框的交并比(IOU)。
|
166
164
|
|
167
165
|
Args:
|
168
166
|
bbox1 (list[float]): 第一个边界框的坐标,格式为 [x1, y1, x2, y2],其中 (x1, y1) 为左上角坐标,(x2, y2) 为右下角坐标。
|
@@ -170,7 +168,6 @@ def calculate_iou(bbox1, bbox2):
|
|
170
168
|
|
171
169
|
Returns:
|
172
170
|
float: 两个边界框的交并比(IOU),取值范围为 [0, 1]。
|
173
|
-
|
174
171
|
"""
|
175
172
|
# Determine the coordinates of the intersection rectangle
|
176
173
|
x_left = max(bbox1[0], bbox2[0])
|
@@ -188,16 +185,15 @@ def calculate_iou(bbox1, bbox2):
|
|
188
185
|
bbox1_area = (bbox1[2] - bbox1[0]) * (bbox1[3] - bbox1[1])
|
189
186
|
bbox2_area = (bbox2[2] - bbox2[0]) * (bbox2[3] - bbox2[1])
|
190
187
|
|
191
|
-
# Compute the intersection over union by taking the intersection area
|
188
|
+
# Compute the intersection over union by taking the intersection area
|
192
189
|
# and dividing it by the sum of both areas minus the intersection area
|
193
|
-
iou = intersection_area / float(bbox1_area + bbox2_area -
|
190
|
+
iou = intersection_area / float(bbox1_area + bbox2_area -
|
191
|
+
intersection_area)
|
194
192
|
return iou
|
195
193
|
|
196
194
|
|
197
195
|
def calculate_overlap_area_2_minbox_area_ratio(bbox1, bbox2):
|
198
|
-
"""
|
199
|
-
计算box1和box2的重叠面积占最小面积的box的比例
|
200
|
-
"""
|
196
|
+
"""计算box1和box2的重叠面积占最小面积的box的比例."""
|
201
197
|
# Determine the coordinates of the intersection rectangle
|
202
198
|
x_left = max(bbox1[0], bbox2[0])
|
203
199
|
y_top = max(bbox1[1], bbox2[1])
|
@@ -209,16 +205,16 @@ def calculate_overlap_area_2_minbox_area_ratio(bbox1, bbox2):
|
|
209
205
|
|
210
206
|
# The area of overlap area
|
211
207
|
intersection_area = (x_right - x_left) * (y_bottom - y_top)
|
212
|
-
min_box_area = min([(bbox1[2]-bbox1[0])*(bbox1[3]-bbox1[1]),
|
213
|
-
|
208
|
+
min_box_area = min([(bbox1[2] - bbox1[0]) * (bbox1[3] - bbox1[1]),
|
209
|
+
(bbox2[3] - bbox2[1]) * (bbox2[2] - bbox2[0])])
|
210
|
+
if min_box_area == 0:
|
214
211
|
return 0
|
215
212
|
else:
|
216
213
|
return intersection_area / min_box_area
|
217
214
|
|
215
|
+
|
218
216
|
def calculate_overlap_area_in_bbox1_area_ratio(bbox1, bbox2):
|
219
|
-
"""
|
220
|
-
计算box1和box2的重叠面积占bbox1的比例
|
221
|
-
"""
|
217
|
+
"""计算box1和box2的重叠面积占bbox1的比例."""
|
222
218
|
# Determine the coordinates of the intersection rectangle
|
223
219
|
x_left = max(bbox1[0], bbox2[0])
|
224
220
|
y_top = max(bbox1[1], bbox2[1])
|
@@ -230,7 +226,7 @@ def calculate_overlap_area_in_bbox1_area_ratio(bbox1, bbox2):
|
|
230
226
|
|
231
227
|
# The area of overlap area
|
232
228
|
intersection_area = (x_right - x_left) * (y_bottom - y_top)
|
233
|
-
bbox1_area = (bbox1[2]-bbox1[0])*(bbox1[3]-bbox1[1])
|
229
|
+
bbox1_area = (bbox1[2] - bbox1[0]) * (bbox1[3] - bbox1[1])
|
234
230
|
if bbox1_area == 0:
|
235
231
|
return 0
|
236
232
|
else:
|
@@ -238,11 +234,8 @@ def calculate_overlap_area_in_bbox1_area_ratio(bbox1, bbox2):
|
|
238
234
|
|
239
235
|
|
240
236
|
def get_minbox_if_overlap_by_ratio(bbox1, bbox2, ratio):
|
241
|
-
"""
|
242
|
-
|
243
|
-
如果比例大于ratio,则返回小的那个bbox,
|
244
|
-
否则返回None
|
245
|
-
"""
|
237
|
+
"""通过calculate_overlap_area_2_minbox_area_ratio计算两个bbox重叠的面积占最小面积的box的比例
|
238
|
+
如果比例大于ratio,则返回小的那个bbox, 否则返回None."""
|
246
239
|
x1_min, y1_min, x1_max, y1_max = bbox1
|
247
240
|
x2_min, y2_min, x2_max, y2_max = bbox2
|
248
241
|
area1 = (x1_max - x1_min) * (y1_max - y1_min)
|
@@ -256,89 +249,118 @@ def get_minbox_if_overlap_by_ratio(bbox1, bbox2, ratio):
|
|
256
249
|
else:
|
257
250
|
return None
|
258
251
|
|
259
|
-
|
260
|
-
|
261
|
-
|
252
|
+
|
253
|
+
def get_bbox_in_boundary(bboxes: list, boundary: tuple) -> list:
|
254
|
+
x0, y0, x1, y1 = boundary
|
255
|
+
new_boxes = [
|
256
|
+
box for box in bboxes
|
257
|
+
if box[0] >= x0 and box[1] >= y0 and box[2] <= x1 and box[3] <= y1
|
258
|
+
]
|
262
259
|
return new_boxes
|
263
260
|
|
264
261
|
|
265
262
|
def is_vbox_on_side(bbox, width, height, side_threshold=0.2):
|
266
|
-
"""
|
267
|
-
判断一个bbox是否在pdf页面的边缘
|
268
|
-
"""
|
263
|
+
"""判断一个bbox是否在pdf页面的边缘."""
|
269
264
|
x0, x1 = bbox[0], bbox[2]
|
270
|
-
if x1<=width*side_threshold or x0>=width*(1-side_threshold):
|
265
|
+
if x1 <= width * side_threshold or x0 >= width * (1 - side_threshold):
|
271
266
|
return True
|
272
267
|
return False
|
273
268
|
|
269
|
+
|
274
270
|
def find_top_nearest_text_bbox(pymu_blocks, obj_bbox):
|
275
271
|
tolerance_margin = 4
|
276
|
-
top_boxes = [
|
272
|
+
top_boxes = [
|
273
|
+
box for box in pymu_blocks
|
274
|
+
if obj_bbox[1] - box['bbox'][3] >= -tolerance_margin
|
275
|
+
and not _is_in(box['bbox'], obj_bbox)
|
276
|
+
]
|
277
277
|
# 然后找到X方向上有互相重叠的
|
278
|
-
top_boxes = [
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
278
|
+
top_boxes = [
|
279
|
+
box for box in top_boxes if any([
|
280
|
+
obj_bbox[0] - tolerance_margin <= box['bbox'][0] <= obj_bbox[2] +
|
281
|
+
tolerance_margin, obj_bbox[0] -
|
282
|
+
tolerance_margin <= box['bbox'][2] <= obj_bbox[2] +
|
283
|
+
tolerance_margin, box['bbox'][0] -
|
284
|
+
tolerance_margin <= obj_bbox[0] <= box['bbox'][2] +
|
285
|
+
tolerance_margin, box['bbox'][0] -
|
286
|
+
tolerance_margin <= obj_bbox[2] <= box['bbox'][2] +
|
287
|
+
tolerance_margin
|
288
|
+
])
|
289
|
+
]
|
290
|
+
|
284
291
|
# 然后找到y1最大的那个
|
285
|
-
if len(top_boxes)>0:
|
292
|
+
if len(top_boxes) > 0:
|
286
293
|
top_boxes.sort(key=lambda x: x['bbox'][3], reverse=True)
|
287
294
|
return top_boxes[0]
|
288
295
|
else:
|
289
296
|
return None
|
290
|
-
|
297
|
+
|
291
298
|
|
292
299
|
def find_bottom_nearest_text_bbox(pymu_blocks, obj_bbox):
|
293
|
-
bottom_boxes = [
|
300
|
+
bottom_boxes = [
|
301
|
+
box for box in pymu_blocks if box['bbox'][1] -
|
302
|
+
obj_bbox[3] >= -2 and not _is_in(box['bbox'], obj_bbox)
|
303
|
+
]
|
294
304
|
# 然后找到X方向上有互相重叠的
|
295
|
-
bottom_boxes = [
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
305
|
+
bottom_boxes = [
|
306
|
+
box for box in bottom_boxes if any([
|
307
|
+
obj_bbox[0] - 2 <= box['bbox'][0] <= obj_bbox[2] + 2, obj_bbox[0] -
|
308
|
+
2 <= box['bbox'][2] <= obj_bbox[2] + 2, box['bbox'][0] -
|
309
|
+
2 <= obj_bbox[0] <= box['bbox'][2] + 2, box['bbox'][0] -
|
310
|
+
2 <= obj_bbox[2] <= box['bbox'][2] + 2
|
311
|
+
])
|
312
|
+
]
|
313
|
+
|
301
314
|
# 然后找到y0最小的那个
|
302
|
-
if len(bottom_boxes)>0:
|
315
|
+
if len(bottom_boxes) > 0:
|
303
316
|
bottom_boxes.sort(key=lambda x: x['bbox'][1], reverse=False)
|
304
317
|
return bottom_boxes[0]
|
305
318
|
else:
|
306
319
|
return None
|
307
320
|
|
321
|
+
|
308
322
|
def find_left_nearest_text_bbox(pymu_blocks, obj_bbox):
|
309
|
-
"""
|
310
|
-
|
311
|
-
|
312
|
-
|
323
|
+
"""寻找左侧最近的文本block."""
|
324
|
+
left_boxes = [
|
325
|
+
box for box in pymu_blocks if obj_bbox[0] -
|
326
|
+
box['bbox'][2] >= -2 and not _is_in(box['bbox'], obj_bbox)
|
327
|
+
]
|
313
328
|
# 然后找到X方向上有互相重叠的
|
314
|
-
left_boxes = [
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
329
|
+
left_boxes = [
|
330
|
+
box for box in left_boxes if any([
|
331
|
+
obj_bbox[1] - 2 <= box['bbox'][1] <= obj_bbox[3] + 2, obj_bbox[1] -
|
332
|
+
2 <= box['bbox'][3] <= obj_bbox[3] + 2, box['bbox'][1] -
|
333
|
+
2 <= obj_bbox[1] <= box['bbox'][3] + 2, box['bbox'][1] -
|
334
|
+
2 <= obj_bbox[3] <= box['bbox'][3] + 2
|
335
|
+
])
|
336
|
+
]
|
337
|
+
|
320
338
|
# 然后找到x1最大的那个
|
321
|
-
if len(left_boxes)>0:
|
339
|
+
if len(left_boxes) > 0:
|
322
340
|
left_boxes.sort(key=lambda x: x['bbox'][2], reverse=True)
|
323
341
|
return left_boxes[0]
|
324
342
|
else:
|
325
343
|
return None
|
326
|
-
|
344
|
+
|
327
345
|
|
328
346
|
def find_right_nearest_text_bbox(pymu_blocks, obj_bbox):
|
329
|
-
"""
|
330
|
-
|
331
|
-
|
332
|
-
|
347
|
+
"""寻找右侧最近的文本block."""
|
348
|
+
right_boxes = [
|
349
|
+
box for box in pymu_blocks if box['bbox'][0] -
|
350
|
+
obj_bbox[2] >= -2 and not _is_in(box['bbox'], obj_bbox)
|
351
|
+
]
|
333
352
|
# 然后找到X方向上有互相重叠的
|
334
|
-
right_boxes = [
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
353
|
+
right_boxes = [
|
354
|
+
box for box in right_boxes if any([
|
355
|
+
obj_bbox[1] - 2 <= box['bbox'][1] <= obj_bbox[3] + 2, obj_bbox[1] -
|
356
|
+
2 <= box['bbox'][3] <= obj_bbox[3] + 2, box['bbox'][1] -
|
357
|
+
2 <= obj_bbox[1] <= box['bbox'][3] + 2, box['bbox'][1] -
|
358
|
+
2 <= obj_bbox[3] <= box['bbox'][3] + 2
|
359
|
+
])
|
360
|
+
]
|
361
|
+
|
340
362
|
# 然后找到x0最小的那个
|
341
|
-
if len(right_boxes)>0:
|
363
|
+
if len(right_boxes) > 0:
|
342
364
|
right_boxes.sort(key=lambda x: x['bbox'][0], reverse=False)
|
343
365
|
return right_boxes[0]
|
344
366
|
else:
|
@@ -346,8 +368,7 @@ def find_right_nearest_text_bbox(pymu_blocks, obj_bbox):
|
|
346
368
|
|
347
369
|
|
348
370
|
def bbox_relative_pos(bbox1, bbox2):
|
349
|
-
"""
|
350
|
-
判断两个矩形框的相对位置关系
|
371
|
+
"""判断两个矩形框的相对位置关系.
|
351
372
|
|
352
373
|
Args:
|
353
374
|
bbox1: 一个四元组,表示第一个矩形框的左上角和右下角的坐标,格式为(x1, y1, x1b, y1b)
|
@@ -357,20 +378,19 @@ def bbox_relative_pos(bbox1, bbox2):
|
|
357
378
|
一个四元组,表示矩形框1相对于矩形框2的位置关系,格式为(left, right, bottom, top)
|
358
379
|
其中,left表示矩形框1是否在矩形框2的左侧,right表示矩形框1是否在矩形框2的右侧,
|
359
380
|
bottom表示矩形框1是否在矩形框2的下方,top表示矩形框1是否在矩形框2的上方
|
360
|
-
|
361
381
|
"""
|
362
382
|
x1, y1, x1b, y1b = bbox1
|
363
383
|
x2, y2, x2b, y2b = bbox2
|
364
|
-
|
384
|
+
|
365
385
|
left = x2b < x1
|
366
386
|
right = x1b < x2
|
367
387
|
bottom = y2b < y1
|
368
388
|
top = y1b < y2
|
369
389
|
return left, right, bottom, top
|
370
|
-
|
390
|
+
|
391
|
+
|
371
392
|
def bbox_distance(bbox1, bbox2):
|
372
|
-
"""
|
373
|
-
计算两个矩形框的距离。
|
393
|
+
"""计算两个矩形框的距离。
|
374
394
|
|
375
395
|
Args:
|
376
396
|
bbox1 (tuple): 第一个矩形框的坐标,格式为 (x1, y1, x2, y2),其中 (x1, y1) 为左上角坐标,(x2, y2) 为右下角坐标。
|
@@ -378,16 +398,17 @@ def bbox_distance(bbox1, bbox2):
|
|
378
398
|
|
379
399
|
Returns:
|
380
400
|
float: 矩形框之间的距离。
|
381
|
-
|
382
401
|
"""
|
402
|
+
|
383
403
|
def dist(point1, point2):
|
384
|
-
|
385
|
-
|
404
|
+
return math.sqrt((point1[0] - point2[0])**2 +
|
405
|
+
(point1[1] - point2[1])**2)
|
406
|
+
|
386
407
|
x1, y1, x1b, y1b = bbox1
|
387
408
|
x2, y2, x2b, y2b = bbox2
|
388
|
-
|
409
|
+
|
389
410
|
left, right, bottom, top = bbox_relative_pos(bbox1, bbox2)
|
390
|
-
|
411
|
+
|
391
412
|
if top and left:
|
392
413
|
return dist((x1, y1b), (x2b, y2))
|
393
414
|
elif left and bottom:
|
@@ -404,5 +425,23 @@ def bbox_distance(bbox1, bbox2):
|
|
404
425
|
return y1 - y2b
|
405
426
|
elif top:
|
406
427
|
return y2 - y1b
|
407
|
-
|
408
|
-
|
428
|
+
return 0.0
|
429
|
+
|
430
|
+
|
431
|
+
def box_area(bbox):
|
432
|
+
return (bbox[2] - bbox[0]) * (bbox[3] - bbox[1])
|
433
|
+
|
434
|
+
|
435
|
+
def get_overlap_area(bbox1, bbox2):
|
436
|
+
"""计算box1和box2的重叠面积占bbox1的比例."""
|
437
|
+
# Determine the coordinates of the intersection rectangle
|
438
|
+
x_left = max(bbox1[0], bbox2[0])
|
439
|
+
y_top = max(bbox1[1], bbox2[1])
|
440
|
+
x_right = min(bbox1[2], bbox2[2])
|
441
|
+
y_bottom = min(bbox1[3], bbox2[3])
|
442
|
+
|
443
|
+
if x_right < x_left or y_bottom < y_top:
|
444
|
+
return 0.0
|
445
|
+
|
446
|
+
# The area of overlap area
|
447
|
+
return (x_right - x_left) * (y_bottom - y_top)
|