File size: 2,850 Bytes
79125e3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c59b15b
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
def remove_duplicate_boxes(boxes, compare_single=None, iou_threshold=0.7):
    """
    Removes duplicate or highly overlapping boxes, keeping the larger one.
    :param boxes: List of (x1, y1, x2, y2) boxes.
    :param compare_single: Optional single box to compare against the list.
    :param iou_threshold: IOU threshold to consider as duplicate.
    :return: 
        - If compare_single is None: deduplicated list of boxes.
        - If compare_single is provided: tuple (is_duplicate, updated_box_or_none)
    """
    def compute_iou(boxA, boxB):
        xA = max(boxA[0], boxB[0])
        yA = max(boxA[1], boxB[1])
        xB = min(boxA[2], boxB[2])
        yB = min(boxA[3], boxB[3])
        interArea = max(0, xB - xA) * max(0, yB - yA)
        if interArea == 0:
            return 0.0
        boxAArea = (boxA[2] - boxA[0]) * (boxA[3] - boxA[1])
        boxBArea = (boxB[2] - boxB[0]) * (boxB[3] - boxB[1])
        return interArea / float(boxAArea + boxBArea - interArea)

    def compute_area(box):
        return (box[2] - box[0]) * (box[3] - box[1])

    # Single comparison mode
    if compare_single is not None:
        single_area = compute_area(compare_single)
        for existing_box in boxes:
            iou = compute_iou(compare_single, existing_box)
            if iou > iou_threshold:
                existing_area = compute_area(existing_box)
                if single_area > existing_area:
                    return True, compare_single  # Keep new (larger) box
                else:
                    return True, None  # Existing box is better, discard new
        return False, compare_single  # No overlap found, keep it

    # Bulk deduplication mode
    unique_boxes = []
    for box in boxes:
        box_area = compute_area(box)
        replaced_existing = False
        
        # Check against existing unique boxes
        for i, ubox in enumerate(unique_boxes):
            if compute_iou(box, ubox) > iou_threshold:
                ubox_area = compute_area(ubox)
                # If current box is larger, replace the existing one
                if box_area > ubox_area:
                    unique_boxes[i] = box
                    replaced_existing = True
                # If existing box is larger or equal, ignore current box
                break
        
        # If no overlap found, add the box
        if not replaced_existing and not any(compute_iou(box, ubox) > iou_threshold for ubox in unique_boxes):
            unique_boxes.append(box)

    print(f"✅ Found {abs(len(unique_boxes) - len(boxes))} duplicates")
    return unique_boxes

def count_panels_inside(target_box, other_boxes):
    x1a, y1a, x2a, y2a = target_box
    count = 0
    for x1b, y1b, x2b, y2b in other_boxes:
        if x1a <= x1b and y1a <= y1b and x2a >= x2b and y2a >= y2b:
            count += 1
    return count