从 YOLO 到 DETR:目标检测范式的演化与分工

1. DETR 出现的原因

在目标检测的发展历程中,YOLO 与 DETR 往往被视为两种截然不同的技术路线,其差异不仅体现在网络结构或训练策略上,更反映了对“目标检测这一问题应当如何建模”的根本理解差别。

直观而言,YOLO 系列方法遵循的是一种密集预测思路:模型在图像的各个空间位置上独立判断是否存在目标,并同时回归其类别与边界框位置。这种做法强调局部决策与并行计算,因而具备极高的推理效率,但也不可避免地会对同一目标产生多次冗余预测,必须借助非极大值抑制等后处理机制进行去重。具体可参考: 物体检测评估指标和YOLO-v1实现思路

YOLO 目标检测流程示意图

与此不同,DETR 则从整体视角重新审视检测任务,将其建模为一个集合预测问题:模型首先对整幅图像进行全局建模,再通过一组固定数量的查询向量为潜在目标分配预测“名额”,并利用集合匹配机制确保每个真实目标只被预测一次。具体可参考:基于Transformer的detr目标检测算法思路分析

DETR(Detection Transformer)端到端目标检测流程示意图

在过去十年中,目标检测领域以 YOLO 系列为代表的一阶段检测模型在工业界取得了很全面的成功,其在速度、稳定性与工程可控性方面已成为事实标准;另一方面,学术界却并未在这一范式上停下脚步,提出了 DETR 这样一种在结构与思想上都显著不同的新模型。表面上看,这似乎是一种“在问题已被解决之后重新发明轮子”的行为,但如果深入分析其动机与背景,会发现 DETR 的出现并非偶然。

本章将从工业现实与研究动机两个维度出发,回答一个核心问题:当 YOLO 已经足够高效且成熟时,目标检测领域究竟还存在哪些未被真正解决的问题,从而促使 DETR 这样的模型得以诞生。

1.1 工业现实:YOLO 已成为目标检测的事实标准

从工程应用的角度看,YOLO 系列模型已经在相当程度上“赢得了竞争”。其推理链路高度统一:输入图像经过骨干网络提取特征,再由检测头在多尺度特征上进行密集预测,最终通过阈值筛选与 NMS 得到结果。该流程天然适配 GPU 并行计算与现代推理框架,因而在云端、边缘、嵌入式等多种场景中都能维持可预期的延迟与吞吐。

更重要的是,YOLO 的工程生态成熟且可迁移。围绕其形成了完善的部署工具链(如 ONNX、TensorRT 等),并积累了大量量化、剪枝、蒸馏等工程经验,使其在真实生产环境中具备较低的维护成本。对于工业系统而言,很多时候“可解释、可调参的不足”反而是一种优势:当出现漏检或误检时,问题往往能够被定位到阈值选择、特定尺度的特征表达或数据分布偏差,从而具备清晰的调试路径与控制手段。

在这样的背景下,单纯从结果导向的角度出发,很难得出“必须引入全新检测范式”的结论。DETR 的出现因此更像是来自研究层面对“范式边界”的反思,而非对 YOLO 现实表现不足的回应。

1.2 三个工程妥协

尽管 YOLO 在实践中表现卓越,但从建模角度看,它的成功始终伴随着若干难以回避的工程妥协。这些妥协并不一定会导致性能灾难,却在理论一致性与模型优雅性上留下了长期争议。

  1. NMS:不可微、阈值敏感、训练与推理割裂。
    非极大值抑制是密集预测范式下冲突消解的关键步骤,但其本质是一种启发式规则:依赖置信度排序与 IoU 阈值设定,并且不可微。这意味着模型在训练过程中无法感知 NMS 的存在,优化目标与推理阶段的实际行为之间始终存在间隙。
  2. Anchor/先验:迁移成本高,仍依赖经验设计。
    无论是显式 Anchor 还是后续 Anchor-free 变体,其核心思想仍是在特征空间中预设大量潜在目标假设,并通过回归或中心点机制对这些假设进行修正。即便自动 Anchor 搜索、解耦预测头等设计在一定程度上缓解了人工经验依赖,但“先验假设强、数据集变化时需要再次适配”的问题并未彻底消除。
  3. 密集预测:计算冗余不可避免。
    YOLO 的核心假设是:图像的任意空间位置都可能存在目标。为了不漏检,模型必须在大量位置生成候选预测,而真实目标数量通常远小于候选数量。换言之,推理中相当一部分计算被用于生成最终必然被丢弃的结果。这种冗余在算力充足时并非不可接受,但从建模思想上看,它暗含着“先过度假设、再事后修正”的思路。

这三点妥协共同指向同一个事实:YOLO 的成功依赖于一套成熟而有效的工程机制,但这套机制并不必然是目标检测问题的唯一表述方式。

1.3 一个被长期忽略的问题:是否必须“先预测很多,再删掉大多数”

将上述现象综合起来,可以发现传统一阶段检测方法隐含着一个几乎未被质疑的前提:检测过程必须经历两步——先生成大量候选预测,再通过规则或排序机制将其中绝大多数剔除。该前提在工程上行之有效,却并非逻辑上的必然。真实场景中,一幅图像里实际存在的目标数量通常是有限且相对稳定的;从问题定义的角度看,检测更接近于“找出图像中有哪些目标实例”,而不是“在所有位置上判断是否存在目标”。

正是在这一层面上,DETR 提出了截然不同的建模视角:它不再试图覆盖所有潜在位置,而是假设目标输出本质上是一个无序集合,并用固定数量的 object queries 直接预测这一集合中的元素。由此,冗余预测与冲突消解被前移至模型内部,通过结构约束与一对一匹配实现,而不再依赖 NMS 等外部后处理。

因此,DETR 的出现并不是对 YOLO 性能不足的回应,而是对其建模思想的一次根本性反思。理解这一点,是理解后续范式演化(包括 Deformable DETR、开放词汇检测等)的关键前提。

flowchart LR
	%% DETR pipeline
    subgraph DETR["DETR:集合预测 + 匹配"]
        direction LR
        B1[输入图像]
        B2[CNN Backbone]
        B3[Transformer Encoder]
        B4[Transformer Decoder
+ Object Queries(固定数量)] B5[固定数量输出
目标 / 空集] B1 --> B2 --> B3 --> B4 --> B5 end %% YOLO pipeline subgraph YOLO["YOLO:密集预测 + NMS"] direction LR A1[输入图像] A2[CNN Backbone] A3[密集预测头
多尺度特征] A4[大量候选框] A5[NMS 去重] A6[最终检测结果] A1 --> A2 --> A3 --> A4 --> A5 --> A6 end
图1-1 YOLO 与 DETR 检测流程对比示意图

如上图对比了两种主流目标检测范式的整体流程:YOLO 通过密集预测与后处理去重来维持输出稳定;DETR 通过固定数量 queries 的集合预测与一对一结构约束,在模型内部完成冲突消解与去重,不再依赖 NMS。该对比直观体现了“先预测大量候选再筛选”与“直接预测目标集合”两种范式在建模思路上的根本差异。

2. YOLO 的本质:把目标检测当成“密集预测与排序”的问题

在明确了 DETR 出现的背景之后,有必要重新回到 YOLO 本身,理解其长期成功所依赖的核心建模假设。本章不沿着 YOLO 版本更迭的时间线展开,而是从统一的建模视角出发,分析 YOLO 系列模型在十余年演化过程中始终保持不变的思想内核。

2.1 一阶段检测的统一建模假设

YOLO 并非一个具体模型,而是一类方法的代表。这类方法的共同点在于,将目标检测视为一个密集预测问题。模型首先将连续的图像空间离散化为规则的特征网格(或特征图),随后在每一个空间位置上,同时预测类别概率与边界框参数。

这一建模方式隐含着一个关键假设:图像中的任意空间位置,都可能存在一个目标实例。为了避免漏检,模型必须对整个空间进行覆盖式预测。这一假设在形式上极为直接,却带来了两个结构性后果:

  1. 预测数量远大于真实目标数量
    在大多数真实场景中,图像中实际存在的目标数量是有限的,且远少于特征图上的预测位置数。然而,YOLO 仍需在所有位置生成预测结果,其中绝大多数最终都会被判定为背景。
  2. 检测问题自然转化为排序问题
    同一目标往往会在多个相邻位置被重复预测,模型必须依据某种置信度标准,对这些预测进行排序与筛选,才能得到最终输出。

这一逻辑并非 YOLO 独有,而是几乎所有一阶段检测方法的共同基础。不同版本之间的差异,更多体现在如何提高这一过程的效率与稳定性,而非对其进行根本性重构。

2.2 Anchor 与 NMS 并非历史包袱,而是逻辑结果

在密集预测假设成立的前提下,Anchor 与 NMS 的出现并非偶然选择,而是直接的逻辑推论。

Anchor 机制的核心作用,在于将连续的边界框回归问题转化为相对于一组离散参考框的偏移预测。通过在每个位置预设多种尺度与长宽比,模型可以更容易覆盖不同形态的目标实例,并在训练早期获得更稳定的梯度信号。这一设计在早期检测模型中显著提升了收敛速度与定位精度。

然而,Anchor 的引入也进一步放大了预测冗余:每增加一种 Anchor 配置,都会成倍增加潜在预测数量。即便在 Anchor-free 方法中,显式的 Anchor 被移除,模型依然在每个位置生成多组候选,只是将先验从“框形状”转化为“回归参数”。

在这一背景下,NMS 成为不可或缺的冲突消解机制。只要模型允许同一目标在多个位置被预测,就必须在推理阶段通过某种规则,将这些重复预测压缩为单一输出。从这个意义上看,NMS 并非某个实现细节的权宜之计,而是密集预测范式下维持实例一致性的必要机制。

2.3 YOLO 十年演化中真正变化与不变的部分

回顾 YOLO 从最初版本到近期模型的发展轨迹,可以发现其演化并非围绕“是否密集预测”展开,而是集中于如何降低密集预测所带来的副作用。在变化的层面,模型结构与训练策略经历了多次重要调整:

多尺度特征被引入以改善小目标检测能力;解耦预测头缓解了分类与回归之间的相互干扰;更合理的损失函数与样本分配策略提升了定位精度与训练稳定性。这些改进显著提高了 YOLO 的性能上限,使其在速度与精度之间取得了更优平衡。

与此同时,大量工程层面的优化被不断引入,包括数据增强、推理加速、模型压缩等。这些优化并不改变模型的核心建模方式,却极大增强了其工程可用性。

然而,在不变的层面,YOLO 始终坚持同一套核心逻辑:对整个空间进行密集预测,并在预测之后通过排序与抑制机制得到最终结果。无论是 Anchor-based 还是 Anchor-free,无论网络结构如何变化,这一逻辑始终未被打破。

这一事实具有重要意义:YOLO 的成功,并非源于对检测问题本质的重新定义,而是对既有工程范式的持续打磨与极致优化。

2.4 排序视角下的目标检测

从更抽象的角度看,YOLO 将目标检测问题隐式地表述为一个排序问题。模型输出的是一组带有置信度评分的候选框集合,推理阶段的核心任务,是在这些候选中选出排名靠前且相互不冲突的部分。

这一视角在实践中非常自然,却也引入了若干难以避免的副作用。排序机制对评分分布高度敏感,微小的分数变化可能导致输出结果发生显著差异。此外,不同类别之间的排序与抑制规则往往需要额外设计,增加了系统复杂度。

更关键的是,排序并非目标检测问题的唯一表述方式。目标实例之间本质上是无序的集合关系,而非有序序列。当检测被强行映射为排序问题时,模型需要在后处理阶段额外承担这一结构错配所带来的代价。正是这一点,为后续基于集合预测的检测方法提供了切入空间。

flowchart LR
    A[特征图
Dense Feature Map] --> B[密集预测
大量重叠候选框] B --> C[按置信度排序
Score Ranking] C --> D[NMS 筛选
Suppress Overlap] D --> E[最终检测结果
少量高置信度框] B -. 冗余预测 .-> C C -. 排序依赖 .-> D
图2-1 密集预测与排序机制示意图

如上图展示了以 YOLO 为代表的一阶段检测方法中的典型处理流程:模型在特征图上生成大量彼此重叠的候选框,通过排序与非极大值抑制逐步消除冗余预测,最终输出少量检测结果。该流程直观体现了密集预测方法中“预测冗余”与“排序筛选”之间的紧密耦合关系,也揭示了其对后处理机制的高度依赖。

3. YOLO 很强,但 NMS 为什么始终无法被移除?

在过去数年中,YOLO 系列模型在网络结构、训练策略和工程实现层面不断演化,其检测精度与稳定性已远超早期版本。然而,一个看似矛盾的事实始终存在:尽管模型本身不断变强,非极大值抑制(NMS)这一后处理步骤却从未被真正移除。即便在 Anchor-free、解耦预测头等新设计出现之后,NMS 仍然作为推理流程中的关键组成部分存在。

这一现象并非偶然。本章将从建模逻辑的角度出发,分析 NMS 在一阶段检测范式中的必然性,并进一步指出这一必然性所揭示的深层问题。

3.1 NMS 解决的不是检测,而是预测冲突

从功能上看,NMS 并不参与“是否存在目标”的判断,而是专门用于解决预测之间的冲突。所谓冲突,指的是同一真实目标被模型在多个空间位置、多个尺度下重复预测,从而在输出中形成大量高度重叠的候选框。

在密集预测框架下,这种冲突几乎不可避免。模型在特征图上进行覆盖式预测,相邻位置会对同一目标给出相似但不完全一致的回归结果。这些预测在几何上高度重叠,在语义上却彼此独立,模型本身并不具备“这些预测属于同一实例”的显式表示能力。

NMS 的引入,正是为了在推理阶段弥补这一能力缺失。通过设定置信度排序规则和 IoU 阈值,NMS 将多个相似预测压缩为单一输出,从而恢复实例级别的一致性。需要强调的是,这一过程完全发生在模型之外,模型在训练时并不知道哪些预测最终会被保留。

3.2 IoU 阈值问题揭示的结构性不稳定

在实际应用中,NMS 的阈值选择往往成为影响性能的关键因素之一。过高的 IoU 阈值可能导致重复检测,过低的阈值则容易误删相邻目标,尤其是在密集场景中。

这一现象并非简单的参数调优问题,而是结构性不稳定的体现。IoU 阈值试图用一个全局规则,解决所有目标实例之间的局部几何关系。然而,不同类别、不同尺度、不同密度分布的目标,其合理的抑制策略并不相同。单一阈值难以在所有场景下取得理想平衡。

更重要的是,NMS 的排序机制使得检测结果对置信度分布高度敏感。微小的分数变化,可能改变候选框的保留顺序,从而导致输出结果发生非连续变化。这种不稳定性在视频流或在线系统中尤为明显。

3.3 Anchor-free 并未真正消除冗余预测

近年来,Anchor-free 方法常被视为简化检测流程的重要方向。通过直接预测中心点或边界距离,这类方法在形式上摆脱了对预设 Anchor 的依赖,并在一定程度上降低了设计复杂度。

然而,从预测密度的角度看,Anchor-free 并未改变一阶段检测的基本假设。模型依然在每一个空间位置生成预测,只是将显式的 Anchor 先验转化为隐式的回归参数。对于同一目标,多个相邻位置仍可能同时给出有效预测,从而产生与 Anchor-based 方法相同的冲突结构。

因此,即便在 Anchor-free 架构中,NMS 依然不可或缺。它解决的并不是 Anchor 带来的问题,而是密集预测本身带来的实例歧义。这一事实进一步表明,Anchor 只是冗余预测的放大器,而非其根本原因。

3.4 一个关键反思:当模型需要 NMS,意味着什么?

综合以上分析,可以提出一个更具根本性的问题:当一个检测模型在推理阶段必须依赖 NMS 才能输出合理结果时,这意味着什么?

从实例层面看,真实场景中的目标数量通常是有限的,且每个目标在图像中只对应一个实例。然而,密集预测范式却假设每一个位置都可能对应一个独立实例,并在事后通过规则将这些假设合并。这种“先过度假设,再事后修正”的策略在工程上可行,却在建模上显得迂回。

正是在这一反思中,另一种建模思路逐渐浮现:如果模型在结构上就明确规定“每个目标只能被预测一次”,并在训练阶段强制执行这一约束,那么预测冲突是否可以被从源头上消除?如果检测输出不再是排序后的候选集合,而是一个无序的目标实例集合,那么后处理规则是否还有存在的必要?

这些问题并非对 YOLO 的否定,而是对其建模假设边界的清晰认知。也正是在这一认知基础上,DETR 所代表的集合预测范式得以提出,并为目标检测问题提供了另一种可能的答案。

flowchart LR
    A[同一目标
在相邻位置被多次预测] --> B[生成多个高度重叠的预测框] B --> C[按置信度排序
Score Ranking] C --> D{IoU > 阈值?} D -->|是| E[抑制低置信度框] D -->|否| F[保留该预测框] E --> D F --> G[最终检测结果
单一目标框]
图3-1 NMS 冲突消解过程示意图

这一章的结论可以一句话概括:NMS 不是一个可以随意移除的工程细节,而是密集预测范式的逻辑产物。要真正摆脱 NMS,必须在建模阶段改变“同一目标允许被多次预测”的前提条件。下一章将以此为起点,系统讨论 DETR 如何通过集合预测与一对一约束,从源头上消解这一问题。

4. DETR 的核心思想:将目标检测建模为一个集合预测问题

在前一章中,我们已经看到:在密集预测范式下,只要允许同一目标被多次预测,冲突消解机制(如 NMS)就不可避免。DETR 的出发点,正是对这一前提的根本性否定。它并不试图改进 NMS,也不试图减少预测冗余,而是直接重新定义了目标检测的输出形式。

4.1 从“覆盖所有可能位置”到“只预测应该存在的目标”

传统一阶段检测方法的核心策略,是对空间位置进行穷尽式覆盖:在特征图的每一个位置上判断是否存在目标。DETR 则采取了相反的思路。它不再假设每个空间位置都对应一个潜在实例,而是假设一幅图像中存在若干个目标实例,这些实例构成一个无序集合

基于这一假设,检测任务被重新表述为:直接预测这个集合中的元素,而非对空间位置逐一作出判断。DETR 通过引入固定数量的 object queries 实现这一目标。每一个 query 可以被理解为一个“目标槽位”,其输出要么对应一个真实目标实例,要么明确表示为空(no-object)。

这一设计在结构上引入了一个强约束:目标实例的数量是受控的,且每个实例最多只能被预测一次。冗余预测不再是一个需要在推理阶段解决的问题,而是在建模阶段被直接禁止。

4.2 固定数量预测与一对一约束的含义

DETR 的输出并不是空间分布,而是一个固定长度的预测列表。每个列表元素包含类别预测和边界框回归结果,所有元素在语义上是对等的、无序的。模型不关心“第几个预测对应图像的哪个位置”,而是关心“这些预测作为一个集合,是否完整描述了图像中的目标实例”。

关键在于一对一约束。在 DETR 中,每个真实目标在训练阶段最多只会被分配给一个 query,其余 query 必须学习输出 no-object。这一约束使模型在结构上具备“一个目标只预测一次”的能力,从而从源头上避免了重复预测与实例冲突。

需要注意的是,这种约束并非通过推理规则实现,而是通过训练目标强制学习得到。预测数量在一开始就是受控的,模型不再需要在输出之后再进行筛选或压缩。

4.3 为什么 DETR 天然不需要 NMS

在理解了一对一预测的结构之后,DETR 不再使用 NMS 便显得顺理成章。由于模型在设计上已经保证了预测之间不存在实例级冲突,推理阶段不再需要任何基于排序或阈值的冲突消解规则。

更重要的是,NMS 的移除并不仅仅减少了一个后处理步骤,而是消除了检测流程中一个不可微、不可学习的环节。DETR 的训练目标与推理行为保持高度一致,模型可以直接针对最终输出进行端到端优化。这种一致性正是 DETR 被视为范式转变的重要原因之一。

从这一角度看,DETR 的优势并不在于“更强的网络结构”,而在于“更一致的问题表述”。

4.4 集合视角下的检测任务重构

将目标检测视为集合预测问题,还带来了更深层次的建模变化。在集合视角下,目标实例之间不再通过空间位置隐式关联,而是通过模型内部的表示进行显式区分。每个 query 在高维特征空间中承担着区分不同实例的角色。

这种建模方式使检测任务更容易与其他实例级任务结合。例如,当检测结果需要进一步参与关系建模、实例交互或多任务联合预测时,集合形式的输出比排序后的候选列表更自然、更稳定。

需要强调的是,这种优势并不会立刻转化为单一指标上的性能提升。DETR 的价值并不在于短期 mAP 表现,而在于为目标检测提供了一种新的结构化表达方式。

4.5 范式转变的意义

从更宏观的角度看,DETR 的核心贡献并不在于某个具体模块,而在于其对目标检测问题本质的重新定义。它将检测从“空间覆盖与后处理驱动”的问题,转化为“实例集合预测”的问题,从而在逻辑上摆脱了对排序与抑制机制的依赖。

这一转变并不意味着传统方法的失效,而是拓展了问题的解空间。YOLO 所代表的密集预测范式在工程效率与实时性方面仍具有不可替代的优势;而 DETR 所代表的集合预测范式,则为更高层次的视觉理解任务提供了更自然的建模基础。

flowchart LR
    subgraph Dense["密集预测范式(YOLO 等)"]
        direction LR
        A1[特征图]
        A2[大量候选框预测]
        A3[排序]
        A4[NMS 去重]
        A5[最终检测结果]
        A1 --> A2 --> A3 --> A4 --> A5
    end

    subgraph SetPred["集合预测范式(DETR)"]
        direction LR
        B1[全局特征表示]
        B2[固定数量
Object Queries] B3[一对一预测
Set Prediction] B4[直接输出目标集合] B1 --> B2 --> B3 --> B4 end
图4-1 集合预测与密集预测对比示意图

到这里,DETR 的核心建模思想已经完整闭环

  • 第 3 章指出了 NMS 的结构必然性;
  • 第 4 章给出了“如何从根源上避免它”的答案。

5. 匈牙利匹配:DETR 中最容易被误解的部分

在 DETR 的整体设计中,匈牙利匹配常常被视为一个“复杂但必要的算法组件”,甚至被误解为 Transformer 不擅长检测而不得不引入的补丁。然而,从建模角度看,这种理解是本末倒置的。匈牙利匹配并不是 DETR 的附加技巧,而是集合预测范式在监督学习条件下的逻辑必然结果

如果忽略这一点,DETR 所强调的一对一预测机制将无法成立。

5.1 匈牙利匹配不是后处理,而是监督对齐机制

在 DETR 中,模型在一次前向传播中会输出固定数量的预测查询。这些查询在初始阶段是对等且无序的,并不预先绑定某个具体目标。与此同时,一张图像中真实存在的目标数量是变化的,且真实目标本身同样构成一个无序集合。

训练阶段必须解决一个核心问题:预测集合中的元素,如何与真实目标集合中的元素建立对应关系?

如果缺乏统一的分配机制,多个预测可能会同时对同一个真实目标产生响应,从而破坏“一对一预测”的基本假设。匈牙利匹配正是为了解决这一问题而引入的。它在训练阶段对预测集合与真实集合进行全局匹配,在所有可能的一对一分配方案中,选择整体代价最小的那一个。

因此,匈牙利匹配的本质作用并不是“提升匹配精度”,而是为训练过程提供一个稳定、明确的一对一监督对齐关系

5.2 为什么必须是一对一匹配

一对一匹配是 DETR 成立的前提条件,而非一个可选设计。如果允许多对一或一对多的匹配关系,那么同一个真实目标就可能同时监督多个预测查询,模型便会自然回到冗余预测的状态。

在这种情况下,即便结构上使用了固定数量的查询,模型仍然会倾向于“多个查询预测同一目标”,从而在推理阶段重新引入实例冲突。这与 DETR 试图从源头消除冗余预测的目标是根本冲突的。

通过强制一对一匹配,DETR 在训练阶段就明确规定:每个真实目标只能由一个查询负责,其余查询必须学习输出 no-object。这种约束迫使模型在查询层面形成稳定分工,为推理阶段的无冲突输出奠定基础。

5.3 代价函数的真正含义:实例相似度,而非几何距离

在匈牙利匹配中,匹配关系的确定依赖于一个代价函数。该函数通常由分类代价与回归代价共同构成,用于衡量预测结果与真实目标之间的相似程度。

需要强调的是,这一代价函数并非简单的框距离度量。它并不是在寻找“最近的预测框”,而是在寻找最可能对应同一实例的预测。换言之,代价函数度量的是实例级相似度,而非纯几何邻近关系。

这种定义使得匹配过程具有语义一致性:一个预测只有在类别和位置上同时合理时,才会被分配给某个真实目标。这一机制确保了监督信号的稳定性,也避免了训练过程中的随机分配问题。

5.4 从优化视角理解 Set Prediction

从更抽象的角度看,DETR 所解决的是一个典型的集合预测问题。在集合预测中,输出元素之间是无序的,损失函数必须对排列不敏感。匈牙利匹配正是实现这一“排列不变性”的关键工具。

通过在训练阶段寻找最优的一对一匹配,损失计算只依赖于集合内容本身,而不依赖于预测的排列顺序。这使得模型能够在连续参数空间中进行梯度优化,同时在离散匹配空间中保持监督结构的一致性。

从这一视角看,匈牙利匹配并不是 DETR 的额外复杂性,而是集合预测问题在监督学习框架下的自然结果。

5.5 常见误解与澄清

围绕匈牙利匹配,存在两类常见误解。其一是认为其计算复杂度过高,不适用于实际系统。事实上,由于 DETR 中查询数量通常是固定且相对较小的,匹配过程在整体训练时间中的占比有限,并不会成为主要瓶颈。

其二是认为匈牙利匹配在推理阶段同样存在。需要明确的是,匹配仅用于训练阶段的监督对齐,推理阶段并不涉及任何匹配、排序或抑制操作。

澄清这些误解,有助于避免将 DETR 简化为“复杂但低效的检测模型”,而忽略其在建模层面的真正创新。

flowchart LR
    subgraph Pred["预测集合(Object Queries)"]
        direction TB
        P1[预测 #1]
        P2[预测 #2]
        P3[预测 #3]
        P4[预测 #4]
    end

    subgraph GT["真实目标集合(Ground Truth)"]
        direction TB
        G1[目标 A]
        G2[目标 B]
    end

    P1 -- 最优匹配 --> G1
    P3 -- 最优匹配 --> G2

    P2 -. 未匹配 .-> N[No Object]
    P4 -. 未匹配 .-> N
图5-1 预测集合与真实集合的一对一匹配示意图

这一章的核心结论是:匈牙利匹配不是 DETR 的“复杂之处”,而是其建模逻辑得以成立的必要条件。它为无序集合预测提供了可学习的一对一监督机制,使“一个目标只预测一次”从设计理念转化为可优化的训练目标。

6. DETR-V1:理念正确,却并不好用

在前述章节中,DETR 作为一种集合预测范式,展示了高度一致且优雅的建模逻辑。然而,在其最初提出时,DETR 并未在主流评测基准上全面超越成熟的一阶段检测模型。相反,其训练缓慢、推理成本高、对小目标不友好等问题,成为限制其实际应用的主要因素。

理解这些问题的来源,对于正确评价 DETR 的意义至关重要。它们并非实现细节不足,而是集合预测范式在缺乏结构先验条件下的直接结果。

6.1 Transformer 在检测任务中的天然不适配

初代 DETR 直接采用标准 Transformer 结构作为核心建模模块。这一选择在语义建模能力上具有明显优势,但在目标检测任务中也暴露出结构性不适配。

标准自注意力机制在空间维度上是全局的。对于高分辨率特征图而言,每一个查询都需要与所有空间位置建立关联。这种全局建模虽然在理论上信息充分,但在检测任务中往往显得代价过高:大量计算被用于建模与当前目标无关的背景区域。

此外,目标检测高度依赖局部几何信息,尤其是在小目标场景中。全局注意力缺乏对局部结构的显式偏置,使模型在训练初期难以聚焦于目标区域。相比之下,卷积网络通过局部感受野和权值共享,天然具备对局部模式的敏感性。

因此,将标准 Transformer 直接用于检测,并非“用错模型”,而是用了一种缺乏检测先验的通用结构

6.2 收敛缓慢是学习难度,而非工程问题

初代 DETR 的另一个典型问题是训练收敛缓慢。相较于 YOLO 等模型,DETR 往往需要显著更长的训练周期才能达到可接受性能。

这一现象并非源于优化器选择或超参数设置,而是由其建模假设所决定。在 DETR 中,对象查询在初始化时是完全对称的,不具备任何空间或语义先验。模型不仅需要学习目标的类别与位置,还需要同时学习查询之间的分工关系。

这种“从零开始分配实例责任”的学习过程本身难度较高。相比之下,密集预测方法在训练一开始就通过空间位置、Anchor 或特征金字塔为预测提供了强先验,从而显著降低了学习难度。

从这一角度看,DETR 的收敛缓慢并非缺陷,而是其去除工程先验所必须付出的代价

6.3 小目标性能受限的根本原因

在早期实验中,DETR 在小目标检测上的表现明显弱于基于多尺度特征的检测模型。这一问题同样可以追溯到其结构设计。

一方面,初代 DETR 通常仅使用单一尺度的高层特征进行预测。对于尺寸较小的目标,其细节信息往往在高层特征中被显著压缩,难以保留足够的判别信号。

另一方面,全局注意力机制在面对大量背景区域时,容易分散注意力权重,使小目标的信号被淹没在背景信息之中。这种现象在目标稀疏但背景复杂的场景中尤为明显。

这些问题并非通过简单调参即可解决,而是提示需要在保持集合预测思想的同时,引入更符合检测任务特性的结构设计。

6.4 一个关键判断:DETR 是“草图”,而非终态

综合来看,初代 DETR 所暴露的问题并不意味着集合预测范式本身存在缺陷。相反,它清晰地指出了范式落地所需要补齐的关键环节:更高效的注意力机制、更合理的特征层级设计,以及对训练过程的适当引导。

从技术演化的角度看,DETR 更像是一份“概念验证”或“第一版草图”,而非可直接替代现有方法的工程方案。它的价值在于明确了方向,而非提供了最终答案。

正是在这一基础上,后续工作开始围绕“如何在不破坏集合预测核心思想的前提下,引入必要的结构先验”展开。下一章将讨论的 Deformable DETR,正是这一探索路径上的关键节点。

flowchart LR
    subgraph Global["标准 Transformer 注意力"]
        direction LR
        A1[特征图所有位置]
        A2[全局两两计算
Self-Attention] A3[注意力分散
背景占比高] A4[计算量大
小目标信号被稀释] A1 --> A2 --> A3 --> A4 end subgraph DetectNeed["检测任务的关注需求"] direction LR B1[特征图] B2[少量关键区域
(目标位置)] B3[局部聚焦计算] B4[高效且对小目标友好] B1 --> B2 --> B3 --> B4 end
图6-1 标准 Transformer 注意力与检测任务需求对比示意图

这一章的结论可以总结为:DETR 的问题不在于“集合预测是否合理”,而在于“如何让这一范式高效落地”

7. Deformable DETR:让 Transformer 学会只看重要区域

在上一章中,我们已经明确:初代 DETR 的问题不在于集合预测这一思想本身,而在于其实现方式缺乏对检测任务的结构性适配。Deformable DETR 的出现,正是为了回答一个关键问题:在不破坏集合预测与一对一匹配这一核心思想的前提下,如何显著提升效率与可用性?

Deformable DETR 给出的答案并不是推翻 DETR,而是对其注意力机制与特征使用方式进行有针对性的重构。

7.1 从全局注意力到稀疏注意力的必然转变

初代 DETR 使用标准 Transformer 自注意力机制,其特点是对特征图中所有位置进行两两交互。这种设计在语义建模任务中具有优势,但在目标检测中代价高昂且效率低下。

Deformable DETR 的核心改变在于:放弃全局遍历,转而采用稀疏注意力机制。对于每一个 object query,模型不再关注整幅特征图,而是仅在少量关键位置上进行特征聚合。这些位置并非人工指定,而是由模型在训练过程中自动学习。

这一转变直接带来了两个结果:

  1. 计算复杂度显著降低,使 Transformer 能够处理更高分辨率的特征;
  2. 注意力更加聚焦于潜在目标区域,而非被背景信息稀释。

7.2 “可变形”并非几何形变,而是可学习的采样位置

“Deformable”一词常被直观理解为几何形变,但在 Deformable DETR 中,其核心含义是采样位置的可学习性

对于每一个 query,模型会预测若干个参考点及其偏移量,从而在特征图上选取少量最相关的位置进行信息聚合。这种机制相当于为每个查询配备了一组自适应的“观察点”,它们会在训练过程中逐渐对齐到目标实例的关键区域,例如中心或边界附近。

从直觉上看,这一机制为 Transformer 引入了类似卷积网络中“局部感受野”的结构偏置,但这种偏置是动态的、可学习的,而非固定的。这使模型在保持表达灵活性的同时,获得了对检测任务至关重要的局部聚焦能力。

7.3 多尺度特征:补齐小目标的结构性短板

除了稀疏注意力机制,Deformable DETR 还系统性地引入了多尺度特征表示。不同尺度的特征图可以捕获不同尺寸目标的判别信息,使模型在面对小目标与大目标时具备更均衡的感知能力。

在这一设计下,每个 query 可以同时从多个尺度的特征图中采样信息,而不再受限于单一高层特征。这一改进显著缓解了初代 DETR 在小目标场景中的性能不足。

需要强调的是,多尺度设计并未改变 DETR 的输出形式或训练方式。一对一匹配、集合预测以及端到端优化框架均保持不变,改进仅发生在特征提取与注意力计算层面

7.4 收敛速度与性能的数量级提升

得益于稀疏注意力和多尺度特征的引入,Deformable DETR 在训练效率上取得了数量级的提升。相较于初代 DETR,其收敛所需的训练轮数显著减少,使集合预测范式第一次在实践中具备可行性。

在性能层面,Deformable DETR 在多个评测基准上显著缩小了与成熟一阶段检测模型之间的差距,并在高 IoU 阈值下展现出较为稳定的定位能力。这表明,集合预测并非天然劣于密集预测,其性能瓶颈更多来自实现方式而非理论上限。

7.5 改了什么,没改什么

从方法演进的角度看,Deformable DETR 的重要性在于其“克制的改动”。
它改的部分

  • 注意力从全局变为稀疏
  • 引入可学习的采样位置
  • 系统性使用多尺度特征

它没改的部分

  • 集合预测的输出形式
  • 一对一匹配与匈牙利监督
  • 不依赖 NMS 的端到端检测流程

这种“只改实现、不改范式”的策略,使 Deformable DETR 成为 DETR 家族中的关键转折点,也为后续一系列基于 Transformer 的检测方法奠定了基础。

flowchart LR
    subgraph Global["全局注意力(Standard Self-Attention)"]
        direction LR
        A1[特征图所有位置 H×W]
        A2[全局两两计算]
        A3[注意力分散]
        A4[计算开销大]
        A1 --> A2 --> A3 --> A4
    end

    subgraph Deform["可变形注意力(Deformable Attention)"]
        direction LR
        B1[特征图]
        B2[为每个 Query 预测 K 个采样点]
        B3[仅在采样点聚合特征]
        B4[聚焦目标区域
高效且稳定] B1 --> B2 --> B3 --> B4 end
图7-1 全局注意力与可变形注意力对比示意图

这一章的核心结论是:Deformable DETR 并没有改变 DETR 的“是什么”,而是第一次回答了 DETR 的“如何才能好用”

8. YOLO 与 DETR:不是替代关系,而是建模思想的分工

在前述章节中,YOLO 与 DETR 被作为两种截然不同的目标检测范式加以分析。从密集预测到集合预测,从后处理驱动到端到端建模,这种差异在结构与训练方式上表现得尤为明显。然而,如果仅以性能指标或发布时间顺序来比较二者,往往会得出片面的结论。

更合理的视角是:YOLO 与 DETR 关注的并不是同一个层级的问题。它们并非站在同一条技术路径上竞争,而是在不同约束条件下,对“目标检测应如何被建模”给出的两种合理答案。

8.1 两种范式解决的是不同层级的问题

YOLO 所代表的一阶段检测方法,本质上解决的是高效感知问题。其核心目标是在严格的延迟、算力与部署约束下,稳定地回答“哪里有什么目标”。在这一层级上,速度、可预测性与工程可控性往往比理论一致性更为重要。

与之相对,DETR 所关注的问题层级更高。通过将检测建模为集合预测任务,DETR 更强调实例级一致性与全局建模能力。这种设计天然适合与关系建模、多任务学习等更复杂的视觉理解任务结合,而不仅仅停留在目标定位本身。

因此,YOLO 与 DETR 并非在同一个目标函数上竞争,而是在不同问题抽象层级上各自优化。

8.2 工业系统为何长期偏向 YOLO

在现实工程系统中,YOLO 被广泛采用并非因为其在所有指标上最优,而是因为其整体行为高度可控。

首先,YOLO 的推理延迟和吞吐率具有良好的可预测性,这对于实时系统至关重要。其次,其失败模式通常与阈值设置、特定尺度特征或数据分布偏差相关,具有明确的调试路径。

此外,YOLO 的结构相对简单,易于裁剪、量化和跨平台部署。这些特性使其在长期维护和工程落地中具备明显优势。

相比之下,DETR 及其变体在结构复杂度和推理成本上仍然偏高,其行为也更依赖整体表示能力。这些特性并不一定适合对延迟和资源高度敏感的场景。

8.3 当检测不再是终点,DETR 的优势开始显现

尽管在纯检测任务中 YOLO 仍具优势,但当检测不再是系统的最终输出,而是更大视觉系统中的中间表示时,DETR 的建模优势开始显现。

在多任务场景中,检测结果往往需要与分割、跟踪、关系推理等任务共享表示。集合预测形式的输出更容易与这些任务进行统一建模,而无需额外引入排序或去重规则。

此外,DETR 的端到端特性使其更容易融入大规模预训练框架。在这一背景下,检测不再是孤立任务,而是整体视觉理解能力的一部分。这也是近年来 DETR 风格方法在研究领域持续活跃的重要原因。

8.4 一个容易被忽略的事实:YOLO 也在吸收 DETR 的思想

需要指出的是,范式之间并非泾渭分明。近年来,YOLO 系列模型也在不断吸收 DETR 所代表的一些思想,例如更简洁的预测头设计、对冗余预测的进一步抑制,以及在一定程度上弱化后处理规则的影响。

这种相互借鉴说明,目标检测的发展并非沿着单一方向演进,而是在不同范式之间不断调整平衡。YOLO 与 DETR 更像是两种极端假设下的代表性方案,其实际应用形态往往位于两者之间。

8.5 分工而非胜负的现实结论

综合来看,将 YOLO 与 DETR 视为胜负关系,往往会遮蔽二者在不同问题层级上的合理定位。YOLO 并未因 DETR 的出现而失去价值,DETR 也并非为了取代 YOLO 而设计。

更合理的理解方式是,将二者视为目标检测问题在不同约束条件下的两种解法:

  • YOLO 强调效率、稳定性与工程可控性;
  • DETR 强调一致性、结构表达与可扩展性。

正是在这种分工关系下,目标检测领域得以同时满足工业实践与理论探索的双重需求。

flowchart TB
    subgraph DETR["DETR:结构建模层"]
        direction TB
        B1[实例集合建模]
        B2[一对一预测]
        B3[端到端一致性]
        B1 --> B2 --> B3
    end

    subgraph YOLO["YOLO:高效感知层"]
        direction TB
        A1[实时性优先]
        A2[密集预测 + 规则去重]
        A3[工程可控、稳定输出]
        A1 --> A2 --> A3
    end
图8-1 YOLO 与 DETR 在系统层级上的分工示意图

这一章的结论可以概括为:YOLO 与 DETR 并非在“谁更好”的问题上竞争,而是在“在什么约束下该如何建模”这一问题上各司其职

9. 实践:YOLO 与 DETR 范式在真实数据上的差异体现在哪里

在前述章节中,YOLO 与 DETR 的差异主要从建模思想与结构设计层面加以分析。然而,不同检测范式的设计取舍是否具有现实意义,最终仍需回到真实数据与具体结果上进行检验。本章通过一组对照实验,考察 一阶段检测范式(YOLO)集合预测范式(DETR 系) 在真实检测任务中的行为差异

需要强调的是,本章的关注重点并非比较模型的极限性能,而在于揭示不同范式在复杂场景中所呈现出的典型错误模式与可控性差异

9.1 实验目标:关注错误结构,而非单一指标

在目标检测评测中,mAP 等综合指标通常被用作主要比较依据。然而,这类指标在一定程度上会掩盖模型在不同场景下的结构性行为差异。例如,两种模型可能取得相近的 mAP,但其漏检位置、误检分布以及错误可调性却截然不同。
因此,本章实验并非回答“哪个模型更强”,而是试图回答以下问题:

  • 在相同数据分布与算力约束下,不同检测范式更容易在什么情况下失败?
  • 这些失败是推理阶段的规则性问题,还是源于建模假设本身?
  • 不同范式的错误在实践中是否具有可调性与可控性?

基于上述目标,实验重点从以下三个维度展开分析:

  1. 小目标场景
  2. 密集目标场景
  3. 推理延迟与稳定性

9.2 实验设置概述

实验选用一个规模适中、目标分布较为复杂的coco数据集,以避免单一场景对结论产生过强影响。数据集中同时包含孤立目标与密集排列目标,并覆盖多个尺度区间,从而对模型的泛化行为提出更具挑战性的要求。

模型选择方面,本章采用如下配置:

  • 使用轻量化配置的 YOLO 模型 作为一阶段检测范式的代表;
  • 使用 Deformable DETR 作为集合预测范式的代表实现。

之所以采用 Deformable DETR 而非原始 DETR,是基于以下考虑:原始 DETR 在小目标建模与收敛效率方面存在已知局限,而 Deformable DETR 在保持端到端集合预测与一对一匹配特性的同时,通过可变形注意力机制显著增强了对多尺度与稀疏特征的建模能力,更能代表当前 DETR 范式在实践中的合理形态。

所有模型均在相近训练预算下完成收敛,推理阶段统一采用官方推荐的默认配置,避免针对单一模型进行极端调优,从而保证对比的公平性。评测阶段使用统一的框格式、IoU 计算方式与错误统计逻辑,以确保不同模型的输出行为在同一语义空间中进行比较。

9.3 定量结果:性能数字背后的含义

从整体指标上看,YOLO 在推理速度与吞吐率方面保持明显优势,尤其在资源受限或对实时性要求较高的环境中表现稳定。其性能随模型规模变化呈现出较好的可预测性,工程部署成本相对较低。

相比之下,Deformable DETR 在较高 IoU 阈值下展现出更稳定的定位表现,预测框在位置一致性方面具有一定优势,尤其在目标分布复杂的场景中表现出更强的召回能力。但这一优势以更高的推理延迟与显存占用为代价,其部署复杂度仍明显高于同级别的 YOLO 模型。

需要指出的是,这些数值差异本身并不构成优劣判断,而是反映了两种检测范式在优化目标与资源分配策略上的不同取舍

9.4 定性分析:典型错误模式的对比

相比定量指标,错误模式的分析更能揭示模型的内在特性。

密集目标场景中,YOLO 更容易出现因非极大值抑制(NMS)导致的漏检现象。当多个目标在空间位置上高度接近且尺度相似时,模型往往能够生成多个合理候选,但在后处理阶段被规则性合并为较少的预测结果。这类错误具有一定的可解释性,并可通过阈值调节在不同场景下进行折中,但难以彻底消除。

小目标场景中,集合预测范式的优势与局限同时显现。Deformable DETR 相比原始 DETR 在小目标召回方面已有明显改善,但仍可观察到部分小目标未被任何查询有效覆盖的情况。这类错误并非源于后处理,而是发生在模型内部的查询分配与特征建模阶段,属于结构性遗漏。

值得注意的是,两类错误在性质上存在显著差异:

  • YOLO 的错误主要发生在推理阶段,依赖规则与阈值,具有一定可调性;
  • Deformable DETR 的错误更多发生在建模阶段,一旦形成,往往难以通过简单规则进行修正。

9.5 调参能解决的,与调参解决不了的

实践中常见的一种误区,是将不同模型之间的性能差异简单归因于参数设置不当。实验结果表明,这种看法并不完全成立。

对于 YOLO,置信度阈值、NMS 阈值等参数对检测结果具有显著影响。通过合理调节,这些参数可以在误检与漏检之间取得不同权衡。这种可调性正是其工程友好性的体现。

而对于 Deformable DETR,尽管查询数量、匹配代价权重等参数会对训练过程产生影响,但其对最终错误分布的影响相对有限。一旦模型在特征层级或查询表达能力上存在不足,简单调参难以从根本上改变结果。这反映出集合预测范式对结构设计的高度敏感性

9.6 代码与实现

本节将对照实验整理为最小可运行工程 YOLO_DeformableDETR_behavior_study。该工程的核心思想是:用统一的数据接口与评测逻辑,将不同检测范式(YOLO 一阶段密集预测、Deformable DETR 集合预测)约束在同一语义空间内比较,从而把差异聚焦到“模型行为”而非“评测适配”。工程实现流程可概括为四个层次:数据层、模型层、评测层与汇总层。

9.6.1 数据层:COCO 标注解析与受控抽样

数据入口位于 datasets/coco.py。使用 pycocotools.COCO 读取 COCO 格式标注(instances_val2017.json),并从验证集图片 ID 中随机抽取 sample_n 张构成评测子集。每次迭代返回两类信息:

  • 一是以 numpy.ndarray 形式加载的 RGB 图像;
  • 二是由 COCO bbox(xywh)转换得到的 GT 框(xyxy)。

这一设计保证了两种模型接收的输入完全一致,并使实验规模可控、复现实验成本可接受。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import random
from pycocotools.coco import COCO
import cv2
import os

class CocoDataset:
"""
COCO 数据集最小封装,用于推理/评测阶段(非训练)。
功能:
- 从 COCO 标注文件中随机抽取 sample_n 张图片
- 按顺序返回:
- RGB 图像(numpy.ndarray, H×W×3)
- 对应的 GT 边界框列表(xyxy 格式)
"""
def __init__(self, img_dir, ann_path, sample_n=300):
"""
参数说明:
- img_dir : COCO 图像目录(如 val2017/)
- ann_path: COCO 标注文件路径(instances_val2017.json)
- sample_n: 随机抽取的图像数量,用于构建受控评测子集
"""
# 加载 COCO 标注
self.coco = COCO(ann_path)
# 图像根目录
self.img_dir = img_dir
# 从所有图像 ID 中随机抽取 sample_n 个
# 目的是控制实验规模,同时保持真实数据分布
self.img_ids = random.sample(self.coco.getImgIds(), sample_n)

def __len__(self):
"""返回数据集中图像数量"""
return len(self.img_ids)

def __iter__(self):
"""
迭代器接口:每次返回一张图像及其对应的 GT 边界框
"""
for iid in self.img_ids:
# 读取图像元信息(文件名、尺寸等)
info = self.coco.loadImgs(iid)[0]
# 读取图像文件(OpenCV 默认 BGR,需要转为 RGB)
img_path = os.path.join(self.img_dir, info['file_name'])
img = cv2.cvtColor(cv2.imread(img_path), cv2.COLOR_BGR2RGB)
# 加载该图像对应的所有标注(annotations)
ann_ids = self.coco.getAnnIds(imgIds=iid)
anns = self.coco.loadAnns(ann_ids)
# 将 COCO 的 bbox(xywh)转换为 xyxy 格式
boxes = []
for a in anns:
x, y, w, h = a['bbox']
boxes.append([x, y, x + w, y + h])
# - img : RGB 图像(numpy.ndarray)
# - boxes: GT 边界框列表(List[List[float]])
yield img, boxes

9.6.2 模型层:以 Wrapper 统一不同范式的推理接口

模型接入位于 wrappers/ 目录,YOLO 与 Deformable DETR 各自实现 predict(img) -> (boxes, scores)。

  • wrappers/yolo_wrapper.py 负责封装 YOLO 的推理流程,并将其输出规范化为 boxes_xyxy 与 scores。YOLO 内部可能包含解码、阈值过滤与 NMS,但这些差异被封装在 wrapper 内部,不向外泄漏。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import numpy as np
import torch
from ultralytics import YOLO

class YOLOWrapper:
"""
YOLO 推理封装类。
该封装用于将一阶段检测模型(YOLO)的推理过程
统一为实验所需的预测接口:
predict(img) -> (boxes_xyxy, scores)
通过 wrapper 屏蔽 YOLO 内部的 dense prediction、anchor 解码、NMS 等工程细节,使其输出可与 Deformable DETR 直接对照。
"""
def __init__(self, device="cpu", score_thr=0.25, model_name="yolov8n.pt", imgsz=640):
"""
参数说明:
- device : 推理设备("cpu" / "cuda" / "cuda:0")
- score_thr : 置信度阈值,用于过滤低置信预测框
- model_name : YOLO 权重文件名或路径(Ultralytics 格式)
- imgsz : 推理时使用的输入分辨率
"""
self.device = device
self.score_thr = float(score_thr)
self.imgsz = int(imgsz)
# 加载 YOLO 模型(如本地不存在,Ultralytics 会自动下载权重)
self.model = YOLO(model_name)
# 尝试将模型移动到指定设备
# 不同版本的 Ultralytics 对 .to(device) 的支持略有差异,因此使用 try / except 保证代码的兼容性
try:
self.model.to(device)
except Exception:
pass

@torch.no_grad()
def predict(self, img_rgb: np.ndarray):
"""
对单张图像执行 YOLO 推理。
参数:
- img_rgb : numpy.ndarray,RGB 图像,形状为 (H, W, 3)
返回:
- boxes_xyxy : numpy.ndarray,形状 (N, 4),边界框坐标 (x1, y1, x2, y2)
- scores : numpy.ndarray,形状 (N,),对应的置信度分数
"""
# Ultralytics YOLO 支持直接以 numpy RGB 图像作为输入,内部自动完成 resize、归一化与前向推理
results = self.model.predict(
source=img_rgb,
imgsz=self.imgsz,
conf=self.score_thr,
device=self.device,
verbose=False
)[0] # 只取当前图像对应的预测结果

# 若该图像没有任何检测结果,返回空数组,以保证后续评测(IoU / error_profile)逻辑稳定
if results.boxes is None or len(results.boxes) == 0:
return (
np.zeros((0, 4), dtype=np.float32),
np.zeros((0,), dtype=np.float32)
)

# 提取预测框坐标(xyxy)与置信度分数
boxes = (
results.boxes.xyxy
.detach()
.cpu()
.numpy()
.astype(np.float32)
)
scores = (
results.boxes.conf
.detach()
.cpu()
.numpy()
.astype(np.float32)
)

# 再次应用置信度阈值过滤,作为不同 YOLO 版本行为差异的保险措施
keep = scores >= self.score_thr

return boxes[keep], scores[keep]
  • wrappers/detr_wrapper.py 使用 HuggingFace Transformers 的 DeformableDetrForObjectDetection 与对应 processor:完成输入预处理、模型前向与 post_process_object_detection,并输出与 YOLO 相同格式的 boxes_xyxy 与 scores。Deformable DETR 的集合预测特性(有限查询、无 NMS、一对一匹配)因此被完整保留,同时在接口层面与 YOLO 对齐。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import numpy as np
import torch
from PIL import Image
from transformers import AutoImageProcessor, DeformableDetrForObjectDetection

class DetrWrapper:
"""
Deformable DETR 推理封装类。
该封装用于将集合预测范式(Deformable DETR)的推理流程
统一为实验所需的预测接口:
predict(img) -> (boxes_xyxy, scores)
与 YOLOWrapper 保持相同的输出语义,
以支持不同检测范式在同一评测逻辑下的对照分析。
"""
def __init__(self, device='cpu', score_thr=0.5):
"""
参数说明:
- device : 推理设备('cpu' / 'cuda' / 'cuda:0')
- score_thr : 置信度阈值,用于过滤低置信预测结果
"""
# 指定推理设备
self.device = torch.device(device)
self.score_thr = score_thr

# 加载 Deformable DETR 的图像预处理器,负责 resize、归一化以及输入张量构建
self.processor = AutoImageProcessor.from_pretrained(
'SenseTime/deformable-detr'
)

# 加载预训练的 Deformable DETR 模型并进入评估模式
self.model = (
DeformableDetrForObjectDetection
.from_pretrained('SenseTime/deformable-detr')
.to(self.device)
.eval()
)

@torch.no_grad()
def predict(self, img):
"""
对单张图像执行 Deformable DETR 推理。
参数:
- img : 输入图像,可为 numpy.ndarray(RGB)或 PIL.Image
返回:
- boxes_xyxy : numpy.ndarray,形状 (N, 4),预测框坐标 (x1, y1, x2, y2)
- scores : numpy.ndarray,形状 (N,),对应的置信度分数
"""
# 若输入为 numpy 数组,则转换为 PIL.Image,以满足 HuggingFace processor 的输入要求
if isinstance(img, np.ndarray):
img = Image.fromarray(img)

# 图像预处理:构建模型所需的输入张量
inputs = self.processor(
images=img,
return_tensors='pt'
).to(self.device)

# 前向推理
outputs = self.model(**inputs)

# 获取原始图像尺寸(注意 PIL.Image.size 返回顺序为 (W, H))
h, w = img.size[1], img.size[0]

# 后处理:将模型输出的相对坐标,转换为与原图尺寸一致的绝对坐标(xyxy),同时根据 score_thr 过滤低置信预测
res = self.processor.post_process_object_detection(
outputs,
target_sizes=torch.tensor([[h, w]], device=self.device),
threshold=self.score_thr
)[0]

# 返回 numpy 格式的预测框与置信度
return (
res['boxes'].cpu().numpy().astype(np.float32),
res['scores'].cpu().numpy().astype(np.float32)
)

通过 wrapper 机制,实验主循环无需关心模型内部差异,从而避免“为适配模型而改变评测”的隐性偏差。

9.7.3 评测层:基于 IoU 的结构性错误统计(TP/FP/FN/dup)

评测逻辑位于 utils/boxes.py。工程不直接依赖 mAP,而是计算 GT 框与预测框之间的 IoU 矩阵,并在图像级别统计四类结构性错误:

  • TP:被至少一个预测框命中的 GT 数量(GT 视角);
  • FN:未被任何预测框命中的 GT 数量(GT 视角);
  • FP:未命中任何 GT 的预测框数量(Pred 视角);
  • dup:多个预测框命中同一 GT 的重复量(用于观察冗余与后处理需求)。

实现上,为避免 NumPy/Torch 混用带来的语义差异与广播陷阱,评测层统一使用 torch.Tensor 完成 IoU 与统计计算,并在输出阶段再转换为 Python 标量。这使得不同模型输出的比较建立在同一套数值语义与阈值标准之上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import torch
import numpy as np
from collections import Counter

def box_iou_xyxy(a, b):
"""
计算两组边界框之间的 IoU(Intersection over Union)。
输入:
- a : (Na, 4),边界框,xyxy 格式
- b : (Nb, 4),边界框,xyxy 格式
返回:
- iou : (Na, Nb),IoU 矩阵
iou[i, j] 表示第 i 个 GT 框与第 j 个预测框之间的 IoU
"""
# --------- 统一数据类型为 torch.Tensor ---------
# 允许输入为 numpy.ndarray 或 torch.Tensor
if isinstance(a, np.ndarray):
a = torch.from_numpy(a)
if isinstance(b, np.ndarray):
b = torch.from_numpy(b)

a = a.float()
b = b.float()

# --------- 计算每个框的面积 ---------
area_a = (
(a[:, 2] - a[:, 0]).clamp(min=0) *
(a[:, 3] - a[:, 1]).clamp(min=0)
)
area_b = (
(b[:, 2] - b[:, 0]).clamp(min=0) *
(b[:, 3] - b[:, 1]).clamp(min=0)
)

# --------- 计算两两框的交集区域 ---------
# 左上角取最大值,右下角取最小值
lt = torch.max(a[:, None, :2], b[None, :, :2])
rb = torch.min(a[:, None, 2:], b[None, :, 2:])

# 交集宽高(负值截断为 0)
wh = (rb - lt).clamp(min=0)
inter = wh[..., 0] * wh[..., 1]

# --------- 计算并集面积 ---------
union = area_a[:, None] + area_b[None, :] - inter + 1e-9

# --------- 返回 IoU 矩阵 ---------
return (inter / union).float()

def error_profile(gt_boxes, pred_boxes, iou_thr=0.5):
"""
计算结构性错误统计(TP / FP / FN / dup)。
与传统 mAP 不同,该函数关注的是:
- 模型“如何出错”,而不是“错了多少”。
参数:
- gt_boxes : GT 边界框(List / np.ndarray / torch.Tensor)
- pred_boxes : 预测边界框(List / np.ndarray / torch.Tensor)
- iou_thr : IoU 阈值,用于判断是否命中(默认 0.5)
返回:
- dict,包含:
{
'tp' : 命中目标数量(GT 视角)
'fp' : 误检数量(Pred 视角)
'fn' : 漏检数量(GT 视角)
'dup' : 重复预测数量(多个预测命中同一 GT)
}
"""
# --------- 边界情况处理 ---------
# 没有 GT:所有预测都算 FP
if len(gt_boxes) == 0:
return {'tp': 0, 'fp': len(pred_boxes), 'fn': 0, 'dup': 0}

# 没有预测:所有 GT 都算 FN
if len(pred_boxes) == 0:
return {'tp': 0, 'fp': 0, 'fn': len(gt_boxes), 'dup': 0}

# --------- 统一输入类型 ---------
if isinstance(gt_boxes, list):
gt_boxes = torch.tensor(gt_boxes)
if isinstance(pred_boxes, list):
pred_boxes = torch.tensor(pred_boxes)

# --------- 计算 IoU 矩阵 ---------
# iou.shape = (num_gt, num_pred)
iou = box_iou_xyxy(gt_boxes, pred_boxes)

# ================= GT 视角 =================
# 每个 GT 只关心与其 IoU 最大的预测框
gt_best = iou.max(dim=1).values
gt_hit = gt_best >= iou_thr

# 命中的 GT 数量
tp = int(gt_hit.sum())

# 未命中的 GT 数量
fn = int((~gt_hit).sum())

# ================= Pred 视角 =================
# 每个预测框只关心与其 IoU 最大的 GT
pred_best_iou, pred_best_gt = iou.max(dim=0)
pred_hit = pred_best_iou >= iou_thr

# 未命中任何 GT 的预测框视为 FP
fp = int((~pred_hit).sum())

# ================= 重复预测(dup) =================
# 若多个预测命中同一个 GT,则计为重复预测
dup = 0
if pred_hit.any():
cnt = Counter(pred_best_gt[pred_hit].tolist())
dup = sum(v - 1 for v in cnt.values() if v > 1)

return {'tp': tp, 'fp': fp, 'fn': fn, 'dup': dup}

9.6.4 汇总层:逐样本记录与整体统计输出

主入口 run_experiment.py 负责组织实验执行。其核心循环对每一张图像依次执行:读取 (img, gt_boxes)、调用两种模型的 predict 得到预测框、分别调用 error_profile 得到错误结构字典,并将结果追加到 summary 中。最终通过汇总函数对 300 张样本的错误结构累加,输出全局 TP/FP/FN/dup。若启用延迟测试(可在工程中扩展),则调用 utils/profiler.py 的 benchmark_latency 对同一输入重复推理若干次,统计 mean/std/p95,用于对比范式在工程可用性上的代价差异。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import argparse
from tqdm import tqdm

# 数据集封装:负责从 COCO 中按需抽样并返回 (img, gt_boxes)
from datasets.coco import CocoDataset

# 模型封装:统一不同检测范式的推理接口
from wrappers.yolo_wrapper import YOLOWrapper
from wrappers.detr_wrapper import DetrWrapper

# 评测工具:计算 TP / FP / FN / dup 等结构性错误
from utils.boxes import error_profile

def summarize(err_list):
"""
将逐样本的错误统计结果进行累加汇总。
参数:
- err_list : List[dict],每个元素对应一张图像的错误统计
返回:
- dict,包含整体 TP / FP / FN / dup
"""
out = {"tp": 0, "fp": 0, "fn": 0, "dup": 0}
for e in err_list:
for k in out:
out[k] += e[k]
return out

def main():
"""
实验主入口。
负责:
1. 解析命令行参数
2. 构建数据集与模型
3. 执行逐样本推理与错误统计
4. 汇总并输出实验结果
"""
# --------- 命令行参数 ---------
ap = argparse.ArgumentParser()
ap.add_argument('--img_dir', required=True,
help='COCO 图像目录,如 val2017/')
ap.add_argument('--ann_path', required=True,
help='COCO 标注文件,如 instances_val2017.json')
ap.add_argument('--sample_n', type=int, default=300,
help='随机抽取的评测样本数量')
ap.add_argument('--device', default='cpu',
help='推理设备:cpu / cuda / cuda:0')
args = ap.parse_args()

# --------- 构建数据集 ---------
# 从 COCO 标注中随机抽取 sample_n 张图像
ds = CocoDataset(
args.img_dir,
args.ann_path,
sample_n=args.sample_n
)

# --------- 构建模型封装 ---------
# 两种检测范式通过 wrapper 接入,统一 predict 接口
yolo = YOLOWrapper(device=args.device)
detr = DetrWrapper(device=args.device)

# --------- 实验主循环 ---------
# 用于记录逐样本的错误统计结果
summary = {'yolo': [], 'detr': []}

for img, gt_boxes in tqdm(ds):
# YOLO 推理(一阶段密集预测)
yb, _ = yolo.predict(img)

# Deformable DETR 推理(集合预测)
db, _ = detr.predict(img)

# 对同一张图像,分别统计两种模型的结构性错误
summary['yolo'].append(
error_profile(gt_boxes, yb)
)
summary['detr'].append(
error_profile(gt_boxes, db)
)

# --------- 汇总并输出结果 ---------
print("=== Error Summary ===")
print("all samples:", len(summary["yolo"]))
print(" YOLO:", summarize(summary["yolo"]))
print(" DETR:", summarize(summary["detr"]))

if __name__ == "__main__":
main()

总体而言,YOLO_DeformableDETR_behavior_study 将“范式对照”落实为一条清晰的代码链路:COCO 统一输入 → wrapper 统一输出 → IoU 统一评测 → 汇总得到结构性错误分布与延迟统计。

9.6.5 实验结果分析

1
2
3
4
=== Error Summary ===
all samples: 300
YOLO: {'tp': 1177, 'fp': 320, 'fn': 1210, 'dup': 110}
DETR: {'tp': 1151, 'fp': 110, 'fn': 1236, 'dup': 5}

在 300 张 COCO 验证样本的统一评测下,YOLO 与 Deformable DETR 在整体召回能力上表现接近,二者的 TP 与 FN 数量处于同一量级。然而,两种范式在错误分布结构上呈现出显著差异。YOLO 产生了更多误检(FP)与重复预测(dup),反映出密集预测与后处理机制在复杂场景中的固有冗余;相比之下,Deformable DETR 的误检数量显著更低,且几乎不存在重复预测,体现了集合预测与一对一匹配约束在抑制冗余方面的结构性优势。这表明,两种模型的差异并非体现在“能否检测到目标”,而在于“如何组织与约束预测结果”。

9.7 实践层面的综合观察

综合上述实验结果可以得出一个清晰结论:YOLO 与 DETR 范式的差异不仅体现在性能指标上,更体现在错误分布形态与可控性上。

  • YOLO 通过规则与阈值在推理阶段维持结果稳定,其不完美是“可调的”,更符合工程场景对可控性的需求;
  • Deformable DETR 则将更多决策前移至模型内部,以换取端到端一致性与更强的全局建模能力,其不完美往往是“结构性的”。

这种差异并不存在绝对优劣,而是对应不同应用需求与设计目标。本章实验结果为前述理论分析提供了现实层面的佐证,也为后续关于检测范式演进趋势的讨论奠定了经验基础。

10. 总结:从任务模型到视觉系统能力

在比较 YOLO 与 DETR 两种经典检测范式之后,一个更值得关注的问题逐渐浮现:目标检测这一任务本身,是否仍将以“检测模型”的形式长期存在? 近年来出现的一系列工作,尤其是以 YOLO-World 为代表的方法,正在从根本上重塑检测任务在视觉系统中的定位。

本章不再聚焦具体模型细节,而是从方法演进的角度,概括目标检测正在发生的几项结构性变化,并据此给出一个更长远的判断。

10.1 从封闭类别到开放语义空间

传统目标检测几乎无一例外地建立在封闭类别假设之上:模型只能在训练时预定义的类别集合中进行预测。这一假设在工程实践中长期有效,却也天然限制了模型的泛化能力。

近年来,检测模型开始与大规模语言或跨模态表示对齐,使“类别预测”逐步转变为“语义匹配”。在这一框架下,检测不再局限于输出离散类别编号,而是与自然语言语义空间建立联系,从而具备一定的开放词汇能力。

这一变化并非简单的类别扩展,而是检测任务语义层级的整体提升:模型开始回答“图像中存在哪些语义实体”,而不仅仅是“是否属于某个已知类别”。

10.2 检测模型正在融入基础视觉表示

随着大规模视觉预训练模型的发展,目标检测不再被视为孤立的下游任务,而是逐渐成为基础视觉表示之上的一种能力头

在这一趋势下,检测模型的关注点从“如何高效地产生边界框”,转向“如何在共享表示空间中稳定地定位实例”。检测开始与分类、分割、检索等任务共享特征表示,从而降低整体系统复杂度。

这一变化使得检测模型的角色发生转变:它不再是一个独立终点,而是视觉系统中用于实例级理解的基础模块。

10.3 集合预测在系统级建模中的长期价值

在这一背景下,DETR 所代表的集合预测范式开始展现出其长期价值。集合形式的输出天然适合作为其他模块的输入,无需依赖排序、阈值或启发式规则进行整理。

当检测结果需要进一步参与关系建模、时序推理或多任务联合优化时,端到端、结构一致的输出形式显得尤为重要。这也是 DETR 风格方法在多任务与大模型背景下持续受到关注的根本原因。

需要指出的是,这并不意味着密集预测范式将被淘汰,而是表明集合预测在系统层级上具有更强的可组合性

10.4 实时性约束下的再平衡

尽管检测任务正在向更高层次演化,实时性仍然是不可忽视的硬约束。YOLO-World 等工作尝试在引入开放语义能力的同时,尽量保持 YOLO 系列一贯的效率优势。

这一现象表明,未来的发展方向并非在 YOLO 与 DETR 之间做出非此即彼的选择,而是在统一建模能力与工程可行性之间不断寻找新的平衡点。部分 DETR 的思想正在被引入高效模型中,而部分 YOLO 的工程经验也在影响更复杂系统的设计。

10.5 结语:检测作为能力,而非终点

综合来看,目标检测正在逐步失去其作为独立终点任务的地位,而演化为视觉系统中的一种基础能力。未来的检测模型,可能不再以传统意义上的“边界框列表”为主要输出形式,而是以更抽象、更结构化的方式参与整体视觉理解过程。

在这一演化过程中,被淘汰的并非某一种模型,而是一种将大量工程规则视为理所当然、并在事后用启发式方法弥补建模缺陷的思维方式。YOLO 与 DETR 所代表的两种范式,将在相当长一段时间内共存,并在不同系统层级上发挥各自优势。

目标检测的未来,或许不再“长得像检测”,但其核心使命将更加清晰:为视觉系统提供稳定、可扩展且语义一致的实例级表示

11. 备注