You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何匹配两个列表的Bounding Box?IOU匹配代码全返回None求排查

边界框匹配IOU代码逻辑问题排查

你有两个边界框列表:Expected_Boxes(预期边界框)和OCR_Boxes(OCR返回边界框),格式均为[Top, Left, Width, Height],尝试用IOU算法匹配时所有结果返回None,问题出在IOU计算的坐标转换逻辑错误。

原始边界框列表

Expected_Boxes= [[96, 752, 784, 172],
 [876, 754, 674, 174],
 [1536, 756, 620, 170],
 [2146, 754, 318, 176],
 [1136, 960, 66, 70],
 [1406, 928, 906, 112],
 [184, 1076, 60, 56],
 [442, 1192, 812, 132],
 [1710, 1232, 62, 54],
 [2012, 1228, 58, 58],
 [176, 1332, 1062, 128],
 [1302, 1334, 1128, 126],
 [128, 1526, 950, 106],
 [1098, 1532, 402, 98],
 [1534, 1538, 450, 88],
 [2010, 1512, 434, 110],
 [804, 1680, 62, 62],
 [992, 1684, 56, 60],
 [742, 1816, 62, 60],
 [1158, 1814, 64, 60],
 [100, 1994, 776, 102],
 [910, 1996, 748, 98],
 [1728, 1994, 714, 96],
 [1728, 1994, 714, 96],
 [2218, 2302, 58, 62],
 [2072, 2486, 60, 60],
 [2218, 2486, 60, 62],
 [56, 1430, 336, 66]]

OCR_Boxes = [[793, 1660, 248, 81],
 [806, 223, 215, 85],
 [812, 1009, 219, 67],
 [812, 2248, 86, 53],
 [947, 1563, 556, 80],
 [970, 1143, 44, 44],
 [1080, 188, 46, 46],
 [1208, 651, 406, 82],
 [1234, 2015, 47, 46],
 [1235, 1710, 46, 47],
 [1364, 1422, 827, 96],
 [1375, 338, 602, 93],
 [1536, 1523, 516, 102],
 [1550, 2115, 180, 76],
 [1562, 429, 648, 70],
 [1691, 991, 48, 47],
 [1692, 808, 47, 46],
 [1822, 1765, 46, 48],
 [1823, 1166, 47, 47],
 [1824, 746, 46, 45],
 [2007, 195, 374, 91],
 [2011, 1858, 380, 82],
 [2014, 1019, 339, 81],
 [2304, 2223, 49, 50],
 [2305, 2078, 47, 46],
 [2492, 2224, 46, 47],
 [2492, 2081, 46, 47],
 [2553, 485, 1124, 48],
 [2790, 1168, 1269, 210],
 [2906, 193, 391, 89]]

原始代码

def intersection_over_union(boxA, boxB):
    # determine the (x, y)-coordinates of the intersection rectangle
    xA = max(boxA[0], boxB[0])
    yA = max(boxA[1], boxB[1])
    xB = min(boxA[2], boxB[2])
    yB = min(boxA[3], boxB[3])
    # compute the area of intersection rectangle
    interArea = max(0, xB - xA + 1) * max(0, yB - yA + 1)
    # compute the area of both the prediction and ground-truth
    # rectangles
    boxAArea = (boxA[2] - boxA[0] + 1) * (boxA[3] - boxA[1] + 1)
    boxBArea = (boxB[2] - boxB[0] + 1) * (boxB[3] - boxB[1] + 1)
    # compute the intersection over union by taking the intersection
    # area and dividing it by the sum of prediction + ground-truth
    # areas - the interesection area
    iou = interArea / float(boxAArea + boxBArea - interArea)
    # return the intersection over union value
    return iou 



def match_bounding_boxes(image1, image2):
    matches = []
    for box1 in image1:
        best_iou = 0
        best_box = None
        for box2 in image2:
            iou = intersection_over_union(box1, box2)
            if iou > best_iou:
                best_iou = iou
                best_box = box2
        matches.append((box1, best_box))
    return matches

问题分析

你的边界框格式是[Top, Left, Width, Height],但IOU函数里直接把boxA[2](Width)当作右边界、boxA[3](Height)当作下边界,这完全错误。正确的边界计算应该是:

  • 右边界 = Left + Width
  • 下边界 = Top + Height

因为原始代码用Width和Height直接参与坐标计算,导致所有框的交集面积都是0,IOU值为0。而match_bounding_boxes函数中初始best_iou是0,iou > best_iou的条件永远不成立,所以best_box始终是None。

修正后的代码

def intersection_over_union(boxA, boxB):
    # 转换框格式:[Top, Left, Width, Height] -> [Top, Left, Right, Bottom]
    # boxA的坐标转换
    a_top, a_left, a_width, a_height = boxA
    a_right = a_left + a_width
    a_bottom = a_top + a_height
    
    # boxB的坐标转换
    b_top, b_left, b_width, b_height = boxB
    b_right = b_left + b_width
    b_bottom = b_top + b_height
    
    # 计算交集矩形的坐标
    xA = max(a_left, b_left)
    yA = max(a_top, b_top)
    xB = min(a_right, b_right)
    yB = min(a_bottom, b_bottom)
    
    # 计算交集面积
    interArea = max(0, xB - xA + 1) * max(0, yB - yA + 1)
    
    # 计算两个框的面积
    boxAArea = a_width * a_height
    boxBArea = b_width * b_height
    
    # 计算IOU
    iou = interArea / float(boxAArea + boxBArea - interArea)
    return iou


def match_bounding_boxes(image1, image2):
    matches = []
    for box1 in image1:
        best_iou = 0
        best_box = None
        for box2 in image2:
            iou = intersection_over_union(box1, box2)
            if iou > best_iou:
                best_iou = iou
                best_box = box2
        matches.append((box1, best_box))
    return matches

关键修正点

  1. 坐标转换:将输入的[Top, Left, Width, Height]转换为实际的边界坐标[Top, Left, Right, Bottom],确保交集计算的坐标正确。
  2. 面积计算优化:直接用Width*Height计算面积,比用边界差计算更简洁,结果一致。

修正后,IOU计算会返回正确的数值,匹配逻辑就能正常找到对应的边界框。

内容的提问来源于stack exchange,提问作者InterestingPenguin80

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 20:00:16