通过率 0% · 提交 0 · 通过 0
这道 OJ 的配套动画
IoU 计算 · 对应本题的思路、过程和代码
目标检测评估时,需要度量预测框与真值框的重合程度。框用连续坐标 (x1, y1, x2, y2) 表示,宽 = x2 - x1,高 = y2 - y1。两个框的 IoU = 交集面积 / 并集面积;两框只共享一条边或一个点时交集面积为 0,IoU 记为 0。给定 N 个预测框与 M 个真值框,请输出 N×M 的 IoU 矩阵。
这类题属于算法机考高频题型中「华为 AI 岗 / IoU」方向的高频题型,通常考察对「华为 AI 岗 / IoU」的建模能力与边界条件处理。掌握本题的解题思路后,可举一反三应对同类真题方向,稳步提升机考通过率。
第一行输入 N M。接下来 N 行,每行 4 个实数 x1 y1 x2 y2,表示预测框。最后 M 行,每行 4 个实数,表示真值框。
输出 N 行,每行 M 个数,第 i 行第 j 个数是第 i 个预测框与第 j 个真值框的 IoU,按四舍五入保留 4 位小数,用单个空格分隔。
1 <= N, M <= 200;坐标是至多一位小数的实数,-1000 <= 坐标 <= 1000;保证每个框 x1 < x2 且 y1 < y2。
示例 1
输入示例
2 1 0 0 2 2 1 1 3 3 0 0 2 2
输出示例
1.0000 0.1429
两预测框对一真值框
示例 2
输入示例
1 1 0.5 0.5 2.5 1.5 1.0 0.0 3.0 2.0
输出示例
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。
训练营动画视频讲解
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。
0.3333
一位小数坐标
时间限制 2000 ms · 内存限制 256 MB
这些是真正决定能不能 AC、但通用题解里常被略过的点。
对每一对预测框和真值框,交集宽度为 max(0,min(x2)-max(x1)),交集高度同理,二者乘积得到交集面积。并集面积等于两框面积之和减交集面积,IoU 为交集除以并集。按预测框为行、真值框为列输出矩阵。
两框在每个坐标轴上的重叠长度由右端点较小值减左端点较大值给出;无重叠或只接触时钳制为 0。矩形交集面积是两个重叠长度的乘积,容斥公式给出并集面积,因此比值就是题目定义的 IoU。
共计算 N·M 对框,每对只做常数次运算,时间复杂度为 O(NM);除输出矩阵外额外空间为 O(1)。
本题使用连续坐标,宽和高不加 1。共享边或点时 IoU 为 0;包含关系下交集等于小框面积。输入最多一位小数,参考实现放大 10 倍转为整数计算,减少浮点误差。
# 坐标最多一位小数:先精确放大 10 倍成整数,再用整数完成面积与四舍五入
import sys
from decimal import Decimal
def fmt4(inter, union):
scaled = (20000 * inter + union) // (2 * union)
return "%d.%04d" % (scaled // 10000, scaled % 10000)
def main():
data = sys.stdin.buffer.read().split()
at = 0
n = int(data[at]); at += 1
m = int(data[at]); at += 1
vals = [int(Decimal(x.decode()) * 10) for x in data[at:at + 4 * (n + m)]]
pred = [tuple(vals[4 * i:4 * i + 4]) for i in range(n)]
gt = [tuple(vals[4 * (n + i):4 * (n + i) + 4]) for i in range(m)]
lines = []
for p in pred:
pa = (p[2] - p[0]) * (p[3] - p[1])
row = []
for g in gt:
ix = max(0, min(p[2], g[2]) - max(p[0], g[0]))
iy = max(0, min(p[3], g[3]) - max(p[1], g[1]))
inter = ix * iy
union = pa + (g[2] - g[0]) * (g[3] - g[1]) - inter
row.append(fmt4(inter, union))
lines.append(" ".join(row))
sys.stdout.write("\n".join(lines) + "\n")
main()