remove_bbox_overlap.py 3.02 KB
Newer Older
1
2
3
from magic_pdf.config.drop_reason import DropReason
from magic_pdf.libs.boxbase import _is_in, _is_part_overlap

许瑞's avatar
许瑞 committed
4
5

def _remove_overlap_between_bbox(bbox1, bbox2):
6
    if _is_part_overlap(bbox1, bbox2):
许瑞's avatar
许瑞 committed
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
        ix0, iy0, ix1, iy1 = bbox1
        x0, y0, x1, y1 = bbox2

        diff_x = min(x1, ix1) - max(x0, ix0)
        diff_y = min(y1, iy1) - max(y0, iy0)

        if diff_y > diff_x:
            if x1 >= ix1:
                mid = (x0 + ix1) // 2
                ix1 = min(mid - 0.25, ix1)
                x0 = max(mid + 0.25, x0)
            else:
                mid = (ix0 + x1) // 2
                ix0 = max(mid + 0.25, ix0)
                x1 = min(mid - 0.25, x1)
        else:
            if y1 >= iy1:
                mid = (y0 + iy1) // 2
                y0 = max(mid + 0.25, y0)
26
                iy1 = min(iy1, mid - 0.25)
许瑞's avatar
许瑞 committed
27
28
            else:
                mid = (iy0 + y1) // 2
29
                y1 = min(y1, mid - 0.25)
许瑞's avatar
许瑞 committed
30
31
32
33
34
35
36
37
                iy0 = max(mid + 0.25, iy0)

        if ix1 > ix0 and iy1 > iy0 and y1 > y0 and x1 > x0:
            bbox1 = [ix0, iy0, ix1, iy1]
            bbox2 = [x0, y0, x1, y1]
            return bbox1, bbox2, None
        else:
            return bbox1, bbox2, DropReason.NEGATIVE_BBOX_AREA
38
39
    else:
        return bbox1, bbox2, None
许瑞's avatar
许瑞 committed
40
41
42
43
44
45
46
47
48


def _remove_overlap_between_bboxes(arr):
    drop_reasons = []
    N = len(arr)
    keeps = [True] * N
    res = [None] * N
    for i in range(N):
        for j in range(N):
许瑞's avatar
许瑞 committed
49
50
            if i == j:
                continue
51
            if _is_in(arr[i]['bbox'], arr[j]['bbox']):
许瑞's avatar
许瑞 committed
52
53
                keeps[i] = False

许瑞's avatar
许瑞 committed
54
    for idx, v in enumerate(arr):
许瑞's avatar
许瑞 committed
55
56
        if not keeps[idx]:
            continue
许瑞's avatar
许瑞 committed
57
58
        for i in range(N):
            if res[i] is None:
许瑞's avatar
许瑞 committed
59
                continue
60
61
62
63

            bbox1, bbox2, drop_reason = _remove_overlap_between_bbox(
                v['bbox'], res[i]['bbox']
            )
许瑞's avatar
许瑞 committed
64
            if drop_reason is None:
65
66
                v['bbox'] = bbox1
                res[i]['bbox'] = bbox2
许瑞's avatar
许瑞 committed
67
            else:
68
                if v['score'] > res[i]['score']:
许瑞's avatar
许瑞 committed
69
                    keeps[i] = False
许瑞's avatar
许瑞 committed
70
                    res[i] = None
许瑞's avatar
许瑞 committed
71
                else:
许瑞's avatar
许瑞 committed
72
73
74
75
76
                    keeps[idx] = False
                drop_reasons.append(drop_reasons)
        if keeps[idx]:
            res[idx] = v
    return res, drop_reasons
77
78
79


def remove_overlap_between_bbox_for_span(spans):
80
    arr = [{'bbox': span['bbox'], 'score': span.get('score', 0.1)} for span in spans]
许瑞's avatar
许瑞 committed
81
82
83
84
85
    res, drop_reasons = _remove_overlap_between_bboxes(arr)
    ret = []
    for i in range(len(res)):
        if res[i] is None:
            continue
86
        spans[i]['bbox'] = res[i]['bbox']
许瑞's avatar
许瑞 committed
87
88
        ret.append(spans[i])
    return ret, drop_reasons
89
90
91


def remove_overlap_between_bbox_for_block(all_bboxes):
92
    arr = [{'bbox': bbox[:4], 'score': bbox[-1]} for bbox in all_bboxes]
许瑞's avatar
许瑞 committed
93
94
95
96
97
    res, drop_reasons = _remove_overlap_between_bboxes(arr)
    ret = []
    for i in range(len(res)):
        if res[i] is None:
            continue
98
        all_bboxes[i][:4] = res[i]['bbox']
许瑞's avatar
许瑞 committed
99
100
        ret.append(all_bboxes[i])
    return ret, drop_reasons