如何匹配两个列表的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
关键修正点
- 坐标转换:将输入的
[Top, Left, Width, Height]转换为实际的边界坐标[Top, Left, Right, Bottom],确保交集计算的坐标正确。 - 面积计算优化:直接用Width*Height计算面积,比用边界差计算更简洁,结果一致。
修正后,IOU计算会返回正确的数值,匹配逻辑就能正常找到对应的边界框。
内容的提问来源于stack exchange,提问作者InterestingPenguin80
相关产品推荐
相关产品推荐

