刘虾 2025-09-18 23:31 采纳率: 49.4%
浏览 8
已结题

python将目标识别多个框汇总一个大框

python目标识别有多个框,有40个框,其中有30个框的位置在一排(y方向坐标几乎相同),通过交并比判断大于0.1的,将这30个框汇总一个大框,最终是有11个框,画框在原图上

  • 写回答

7条回答 默认 最新

  • 檀越@新空间 2025-09-18 23:32
    关注

    晚上好🌙🌙🌙
    本答案参考通义千问

    在Python中,如果你有多个目标检测框(bounding boxes),并且希望将其中位置相近的框合并为一个大框,可以通过以下步骤实现:


    1. 问题分析

    • 你有40个目标检测框。
    • 其中有30个框位于同一行(y方向坐标几乎相同)。
    • 需要通过**交并比(IoU)**来判断这些框是否可以合并。
    • IoU大于0.1的框将被合并成一个大的框。
    • 最终结果是11个框

    2. 解决方案

    步骤一:定义 bounding box 的结构

    每个框由 [x1, y1, x2, y2] 表示,表示左上角和右下角坐标。

    步骤二:计算两个框之间的 IoU

    def compute_iou(box1, box2):
        # 计算两个框的交集区域
        x1 = max(box1[0], box2[0])
        y1 = max(box1[1], box2[1])
        x2 = min(box1[2], box2[2])
        y2 = min(box1[3], box2[3])
    
        # 计算交集面积
        intersection_area = max(0, x2 - x1) * max(0, y2 - y1)
    
        # 计算两个框的面积
        area1 = (box1[2] - box1[0]) * (box1[3] - box1[1])
        area2 = (box2[2] - box2[0]) * (box2[3] - box2[1])
    
        # 计算并集面积
        union_area = area1 + area2 - intersection_area
    
        # 计算 IoU
        iou = intersection_area / union_area if union_area > 0 else 0
        return iou
    

    步骤三:合并相似框

    def merge_boxes(boxes, iou_threshold=0.1):
        merged_boxes = []
        used = [False] * len(boxes)
    
        for i in range(len(boxes)):
            if not used[i]:
                current_box = boxes[i]
                # 合并所有与当前框 IoU 大于阈值的框
                for j in range(i + 1, len(boxes)):
                    if not used[j] and compute_iou(current_box, boxes[j]) > iou_threshold:
                        # 合并框
                        new_x1 = min(current_box[0], boxes[j][0])
                        new_y1 = min(current_box[1], boxes[j][1])
                        new_x2 = max(current_box[2], boxes[j][2])
                        new_y2 = max(current_box[3], boxes[j][3])
                        current_box = [new_x1, new_y1, new_x2, new_y2]
                        used[j] = True
                merged_boxes.append(current_box)
                used[i] = True
    
        return merged_boxes
    

    步骤四:画出合并后的框

    使用 OpenCV 或 PIL 绘制框:

    import cv2
    
    # 假设原图是 image
    image = cv2.imread("your_image.jpg")
    
    # merged_boxes 是经过合并后的框列表
    for box in merged_boxes:
        x1, y1, x2, y2 = box
        cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
    
    cv2.imshow("Merged Boxes", image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    3. 完整流程总结

    1. 输入:原始目标检测框列表(如从模型输出获得)。
    2. 计算 IoU:遍历所有框,找出 IoU 大于 0.1 的框。
    3. 合并框:将相似的框合并为一个大的框。
    4. 输出:得到最终的 11 个框,并在图像上绘制。

    4. 示例代码整合

    import cv2
    
    def compute_iou(box1, box2):
        x1 = max(box1[0], box2[0])
        y1 = max(box1[1], box2[1])
        x2 = min(box1[2], box2[2])
        y2 = min(box1[3], box2[3])
        intersection_area = max(0, x2 - x1) * max(0, y2 - y1)
        area1 = (box1[2] - box1[0]) * (box1[3] - box1[1])
        area2 = (box2[2] - box2[0]) * (box2[3] - box2[1])
        union_area = area1 + area2 - intersection_area
        iou = intersection_area / union_area if union_area > 0 else 0
        return iou
    
    def merge_boxes(boxes, iou_threshold=0.1):
        merged_boxes = []
        used = [False] * len(boxes)
    
        for i in range(len(boxes)):
            if not used[i]:
                current_box = boxes[i]
                for j in range(i + 1, len(boxes)):
                    if not used[j] and compute_iou(current_box, boxes[j]) > iou_threshold:
                        new_x1 = min(current_box[0], boxes[j][0])
                        new_y1 = min(current_box[1], boxes[j][1])
                        new_x2 = max(current_box[2], boxes[j][2])
                        new_y2 = max(current_box[3], boxes[j][3])
                        current_box = [new_x1, new_y1, new_x2, new_y2]
                        used[j] = True
                merged_boxes.append(current_box)
                used[i] = True
    
        return merged_boxes
    
    # 示例输入
    boxes = [[100, 200, 150, 250], [160, 200, 210, 250], [220, 200, 270, 250], ...]  # 40个框
    merged_boxes = merge_boxes(boxes)
    
    # 绘制
    image = cv2.imread("your_image.jpg")
    for box in merged_boxes:
        x1, y1, x2, y2 = box
        cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
    
    cv2.imshow("Merged Boxes", image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    5. 注意事项

    • 确保框的格式统一,如 [x1, y1, x2, y2]
    • 如果你的目标检测模型输出的是 [x_center, y_center, width, height],需要先转换为 [x1, y1, x2, y2]
    • 可以调整 iou_threshold 来控制合并的严格程度。

    6. 总结

    重点步骤如下:

    1. 计算 IoU 来判断框之间是否重叠。
    2. 合并重叠框,生成新的大框。
    3. 绘制最终框 到原图上。

    通过这种方式,你可以将原本 40 个框合并为 11 个更合理的框。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(6条)

报告相同问题?

问题事件

  • 系统已结题 10月1日
  • 已采纳回答 9月23日
  • 创建了问题 9月18日