真实面经题目 · 原创解析
如何实现 NMS 的全过程,包括按 score 排序?
NMS 的流程是按置信度排序,依次保留最高分框,计算它与剩余框的 IoU,并删除重叠过高的候选框,直到候选框处理完。
出现于:字节跳动 · 算法
真实面经题目 · 原创解析
NMS 的流程是按置信度排序,依次保留最高分框,计算它与剩余框的 IoU,并删除重叠过高的候选框,直到候选框处理完。
NMS 用来去掉目标检测中的重复框。实现时先按 score 从高到低排序,取最高分框加入结果,然后计算它和剩余框的 IoU,把 IoU 大于阈值的框删掉;再从剩余框里继续取最高分,重复直到没有候选框。多类别检测通常按类别分别做 NMS。复杂度主要来自排序和两两 IoU 计算,工程上会用向量化、topK 或 batched NMS 优化。
输入是检测框、类别和置信度。先按 score 降序排列,保证每轮优先处理当前最可信的候选框,这是 NMS 贪心策略的基础。
每轮取当前最高分框加入最终结果,然后把它作为基准框,与剩余候选框逐个计算 IoU,判断是否属于同一个目标的重复预测。
如果某个候选框和基准框的 IoU 超过阈值,就认为重叠过高,将其删除;低于阈值的框继续保留,参与后续轮次。
常见做法是同一类别内做 NMS,避免不同类别的框互相抑制。多标签或类别混淆场景要明确类别维度和阈值策略。
朴素 NMS 需要排序和多轮 IoU 计算,框很多时成本高。工程中会先做 score 阈值过滤、topK 截断、向量化计算或使用框架内置 batched NMS。
function nms(boxes, threshold) {
const order = [...boxes].sort((a, b) => b.score - a.score);
const keep = [];
while (order.length > 0) {
const current = order.shift();
keep.push(current);
for (let i = order.length - 1; i >= 0; i -= 1) {
if (iou(current, order[i]) > threshold) {
order.splice(i, 1);
}
}
}
return keep;
} IoU 等于两个框交集面积除以并集面积,需要先求交集矩形,再计算面积。
遮挡或密集目标中,真实相邻目标可能被误删;阈值选择也会影响召回和精度。
Soft-NMS 不直接删除高重叠框,而是降低其分数,能在密集场景保留更多候选。