包围盒交并比(IoU)是两个矩形框重叠面积与并集面积的比值,用于目标检测评估;其NumPy实现需用向量化计算求交集坐标、判空、算面积,输入为(N,4)的[x1,y1,x2,y2]格式ndarray。

什么是包围盒交并比(IoU)?
IoU 是两个矩形框重叠区域面积与它们并集区域面积的比值,常用于目标检测评估。它不关心坐标系原点在哪,只依赖四个顶点或 [x_min, y_min, x_max, y_max] 形式的边界框表示。
用NumPy实现IoU计算的最简方式
核心是向量化计算:避免 for 循环,用广播机制一次性处理多个框对。关键步骤是求交集坐标、判空、算面积。
- 输入必须是
shape = (N, 4)的ndarray,每行是[x1, y1, x2, y2],且满足x1 和 <code>y1 - 交集左上角取较大值:
np.maximum(boxes1[:, :2], boxes2[:, :2]) - 交集右下角取较小值:
np.minimum(boxes1[:, 2:], boxes2[:, 2:]) - 交集宽高为负时说明无重叠,需用
np.clip(..., 0, None)截断
def iou(boxes1, boxes2):
# boxes1: (N, 4), boxes2: (M, 4)
lt = np.maximum(boxes1[:, None, :2], boxes2[None, :, :2]) # (N, M, 2)
rb = np.minimum(boxes1[:, None, 2:], boxes2[None, :, 2:]) # (N, M, 2)
wh = np.clip(rb - lt, 0, None) # (N, M, 2)
inter = wh[:, :, 0] * wh[:, :, 1] # (N, M)
<pre class='brush:python;toolbar:false;'>area1 = (boxes1[:, 2] - boxes1[:, 0]) * (boxes1[:, 3] - boxes1[:, 1]) # (N,)
area2 = (boxes2[:, 2] - boxes2[:, 0]) * (boxes2[:, 3] - boxes2[:, 1]) # (M,)
union = area1[:, None] + area2[None, :] - inter
return np.divide(inter, union, out=np.zeros_like(inter, dtype=float), where=union!=0)常见错误和兼容性注意点
实际用的时候,90% 的问题出在数据格式和坐标顺序上,不是算法本身。
-
boxes1和boxes2若混用[x_center, y_center, w, h]格式,必须先转成[x1, y1, x2, y2],否则np.maximum会错位 - OpenCV 默认返回
(x, y, w, h),YOLO 输出常为归一化中心坐标 —— 这些都不能直接喂给上面的iou函数 - 当某对框完全不重叠时,
union可能为 0,除零会得nan;用np.divide(..., where=...)或提前掩码更安全 - 若只需单对框 IoU(比如
boxes1.shape == (4,)),别硬套广播版,改用标量逻辑更清晰:
def iou_single(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])
if x1 >= x2 or y1 >= y2:
return 0.0
inter = (x2 - x1) * (y2 - y1)
area1 = (box1[2] - box1[0]) * (box1[3] - box1[1])
area2 = (box2[2] - box2[0]) * (box2[3] - box2[1])
return inter / (area1 + area2 - inter)为什么不用 scikit-image 或 torchvision?
如果你只是做后处理或写 demo,直接用 NumPy 更轻量、无依赖、可控性强。但要注意:
立即学习“Python免费学习笔记(深入)”;
-
skimage.metrics.bounding_box_iou输入是(r0, c0, r1, c1)(即y1, x1, y2, x2),Y 轴在前,容易和习惯的x1,y1,x2,y2搞反 -
torchvision.ops.box_iou要求输入是torch.Tensor,且默认在 GPU 上跑 —— 纯 NumPy 场景下引入 PyTorch 不划算 - 自己写的 NumPy 版本可以无缝嵌入
numba.jit加速,而第三方封装往往不支持
坐标顺序、数据类型、空框处理,这几个地方不盯紧,IoU 值就可能全错,而且错得不报错。


















