作为做检测的老兵,从 Faster R-CNN 时代一路走过来的人,对“Anchor”这个词多少都有点复杂感情。早期它确实让检测精度有了大跨越,但随着任务越来越复杂,Anchor 参数(尺度、比例、数量)对数据集本身的敏感性也让人头大——换一套数据、换一个分布,往往就要重新聚类或者手工调参。所以当 CenterNet 这类把问题和流程“砍到极简”的方法出现时,我第一时间就在小数据集上试了试。核心思路一句话:把目标检测从“画框子”变成“找中心点”,不仅省掉了 Anchor 相关的全部参数搜索,还顺手把 NMS 也拿掉了。这篇文章我就结合自己跑实验踩坑的过程,把 CenterNet 的原理、训练细节、推理流程和一些实战经验掰开揉碎了讲清楚。
1. 从“画框子”到“找中心点”:CenterNet 的出场背景
先说说为什么要折腾“关键点检测”这条路。传统检测器(两阶段或一阶段)本质上是在做“滑动窗口候选框的判别”,也就是说,在网格的每个位置放一堆预设尺寸的框(anchor),然后判断这些框到底有没有框住物体、需不需要修正位置。这个思路的问题很明显:一是预设框的数量极其庞大(一张图几万到几十万个候选),大部分都是负样本,训练优化容易被大量简单负样本主导;二是 anchor 的超参数非常依赖经验,和检测器精度、收敛速度直接挂钩。
CenterNet 走的思路完全不一样:它把物体的表示方式从“框”改成“物体中心点”。训练时,我们只需要告诉网络“物体的中心落在哪、物体多大多宽”,推理时也只需要从特征图上找到那些峰值的点,直接解码出框。整个过程没有包围框建议子网络,没有各层级的 anchor 数量调整,也没有两阶段那样的 region pooling。整张图从头到尾就是“全卷积 + 峰值提取”。
从任务目标来说,CenterNet 不光能做目标检测。它把检测、姿态估计甚至 3D 目标检测都统一到了同一个关键点检测框架里:检测是物体中心点加宽高偏移,姿态是中心点加关键点坐标,3D 检测是中心点加朝向、尺寸、深度。本质上都在做“预测图像中某些固定位置的响应”。这个“统一”能力在方法论上非常有价值,尤其是做工业落地项目的时候,一套特征提取网络如果既出检测框又出关键点信息,维护成本会低非常多。
从架构效率来看,CenterNet 没有 Anchor-based 方法里常见的 RPN 或一阶段检测头,也没有类似于“分类分支和回归分支各自解耦再融合”的复杂设计。它的检测头只是几条并行的 1x1 卷积,输出的特征图通道数分别是类别数、偏移(2通道)、尺寸(2通道)。轻量到可以塞进任何以“空间下采样再上采样”为骨架的网络中。可以说,CenterNet 是我见过“训练流程最像分类任务、推理流程最像简单后处理”的检测器。
实战里,CenterNet 对算力的要求也比较友好。我们的测试场景中,用 ResNet-50 级别的骨干网络,单卡训练 batch size 能比同分辨率的两阶段检测器开得更大;推理阶段由于不跑 NMS,纯卷积输出的延迟很稳定。这个特点在边缘设备部署时尤其吃香,我在后续的嵌入式移植中确实是受益者。
2. 拆掉 anchor 和 NMS 的两根支柱:热图和中心点回归
2.1 高斯热图:为什么一个点能代替一堆框
CenterNet 的训练标签长什么样子?假设输入是一张 H×W 的图像,网络输出的热图是 H/R × W/R × C,其中 R 是下采样倍数(常用 4),C 是类别数。针对每个标注框,CenterNet 把框中心位置映射到低分辨率特征图上,然后在以这个中心为中心的圆形区域填充高斯核的响应值。高斯核半径怎么定?这是整个方法里最容易让人产生细节误解的地方之一。
官方的做法是:根据标注框的大小计算一个半径 r,使得在这个半径范围内的所有有点都能和真实框产生足够的“交叠面积”,从而在训练时这些位置被视为“中心附近的可接受区域”。我之前看源码的时候一直没搞懂为什么半径有时候是 1,有时候又是 3 或 5,后来沿着代码推了一遍才发现,它其实是在按照 CornerNet 那篇推导里的 IoU 阈值反推来的:取一个整数半径,使得以中心点为圆心画圆,圆内任意位置对应的预测框和真实标注框的最小 IoU 不小于设定的阈值(一般是 0.3 或 0.7,取决于版本和数据集设置)。
这里有个值得注意的思维转换。Anchor-free 不是没有“候选降低了”这个概念,而是把“离散候选”(anchor 框)换成了“连续响应”(热图峰值)。每一个像素位置,网络都要学会判断该位置是不是某个物体的中心区域。高斯核的半径实际上是在告诉网络:“中心处是强正样本,离中心一定距离内的是软正样本,再远的就是负样本。”这个“软正样本区域”设计很关键,它能给正样本附近提供足够的梯度信号,让网络不至于只能向中心点这一个孤零零的像素学习。
实际训练时,损失函数采用的是带 penalty reduction 的 focal loss 变体。对每个像素,预测值和真实高斯图上对应位置的值之间的交叉熵会被加权:当真实值接近 1 时,权重小;当真实值接近 0 时,权重根据难易程度自适应调整。这个设计和 RetinaNet 里 focal loss 的初衷类似,都是为了解决“大部分像素都是负样本”这种极端类别不平衡问题。
2.2 偏移和尺寸分支:从中心点还原完整的框
有了中心点,还不能直接得到框,需要补两个东西:中心点的量化误差和物体的宽高。
由于特征图下采样了 4 倍,训练时我们其实是在低分辨率图上标注的坐标(真实位置除以 4 取整)。这样一来,把中心点映射回原图时,会引入一个最多 3 个像素的量化误差。CenterNet 用一个额外的 2 通道特征图直接回归中心点的偏移值,训练用 L1 损失,推理的时候把预测的偏移和整数坐标相加,得到更精确的中心位置。说到底,这个偏移分支就是在“校准下采样的信息损失”。它只监督中心点附近的那些位置,不会对全图所有像素强加约束,所以训练起来比较稳。
尺寸分支则输出每个中心点对应物体的宽高,同样用 L1 损失。这里有个很多人都踩过的坑——训练的时候尺寸分支的输出会直接除以输入图像的缩放比例,但在自定义数据集上,如果你没有按原图尺度做 resize,就要额外小心坐标统一的问题。我一开始图省事,直接在预处理里缩放到统一尺寸,但没有保留缩放系数,结果推理出来的框在小目标上整体偏移。后来把原图尺度、resize 比例、模型输入尺寸这三者的换算关系理清楚,问题才消失。
推理阶段,CenterNet 从热图上取每个类别响应值最高的 K 个点(通常 K 取 100),先按照热图分数过滤一遍,再读取对应位置的偏移和尺寸信息,最终把中心点加减半宽半高得到边界框。整个后处理就这么两三行代码,没有 per-class 的 NMS,也没有跨类别的抑制逻辑,速度优势在 batch=1 的在线推理场景下尤其明显。
2.3 没有 NMS 还能保证输出干净的核心原因
很多人第一反应是:没有 NMS,不会产生一堆高度重叠的框吗?理论上如果网络对同一个物体输出多个中心点,确实会这样。但 CenterNet 的实际设计大大降低了这种概率。
第一层保障来自高斯热图的监督:同一个目标周围只有中心点附近的区域是正样本,边角区域都被惩罚为负样本,所以热图峰值本质上是稀疏的、局部唯一的。第二层保障来自中心点本身的语义:一个矩形的目标只有一个几何中心,不存在“多个互为重叠的候选框都包含这个物体并共享同一个中心点”的情况。只要网络学得足够好,每个物体至多生成一个峰值,也就不需要 NMS 去过滤多框。
不过我这里说句实在话:“不需要 NMS”是有前提的。如果检测类别之间存在遮挡或者目标尺寸悬殊,两个不同物体的中心点恰好落在相邻很近的位置(比如一只鸟站在树枝前面,鸟的中心和树枝的一小段重叠),热图可能会连成一片。这种情况下没有 NMS 反而容易把两个类别输出粘连在一起。业内不少改进版(如 CenterNet++ 思路)依然会加一个轻量的包围框合并后处理,或者直接提高 K 值再按 IoU 过滤,目的就是解决这种极端场景。对纯 CenterNet 而言,“no NMS”更像是一种设计目标,而不是绝对真理。
3. 训练和推理里必须看懂的细节:损失函数、骨干网络与后处理
3.1 损失函数三件套:热图、偏移、尺寸如何协作
整体损失三部分加权求和:热图损失、中心点偏移损失、宽高损失。热图损失用修正版的 focal loss,偏移和宽高只用中心点位置的真值来计算 L1。热图的权重一般是 1,偏移和尺寸的权重分别由对应损失权重超参数决定,官方实现里尺寸损失权重是 0.1。
为什么尺寸损失权重这么低?因为尺寸分支的回归尺度变化范围非常大(宽高从十几个像素到上千像素),如果给太高权重,训练早期网络会专注于“把大目标的长宽学好”,而中心点定位精度反而受影响。但中心点定位才是关键,后续所有解码都建立在中心点的精确性上。所以按我的经验,不要随意调大尺寸损失权重,尤其不要按 L1 数值大小去分配权重——这个损失天然偏大,0.1 这个比例是经过实验验证的平衡点。
热图损失里有个细节不少初学者会忽略:focal loss 的负样本概率是 1 减去预测值,而对靠近高斯中心但并非真正中心的位置(软正样本),真实标签是小于 1 的高斯响应值,而不是二进制 0 或 1。这意味着这些像素的“难度”天然比纯背景低,所以 focal loss 给的抑制权重会更小。这其实非常聪明:它允许网络在中心附近产生一定宽度的激活峰,退化成极端的单像素检测器反而更脆弱。
3.2 骨干网络选择:DLA、沙漏网络、ResNet 怎么选
CenterNet 官方实验里用了几类骨干:堆叠沙漏网络(Hourglass)、带有可变形卷积的 DLA、以及 ResNet。从我的实测来看:
- 堆叠沙漏网络:精度最高,但对显存和推理延迟都很不友好。如果你的设备是单张消费级显卡且需要处理 512 以上分辨率,我不建议选它,训练速度和推理稳定性都是问题。
- DLA 结构:精度和速度相对均衡,尤其是官方提供的带可变形卷积的版本,能有效捕获多尺度几何变化。实际工程里可以把它作为默认选型。
- ResNet 加反卷积头:结构最简单、最容易调参和复现,精度略低于 DLA 但部署友好。做移动端或快速验证时我一般先拿 ResNet-50 跑通链路,再去换更重的网络提高精度。
这里补充一个个人建议:如果你用 DLA 结构,预处理阶段不要随意对图像做太多的颜色扰动,因为 CenterNet 的热图预测对纹理细节依赖度不低,过强的数据增强(比如大尺度随机裁剪、复杂的颜色抖动)会让 center 响应不稳定。相比通用检测器,CenterNet 的表面特征和空间位置耦合更紧,增强策略要保守一些。
3.3 推理阶段 top-k 和阈值怎么设才合理
推理的核心参数是 K(每个类别最多保留多少个峰值点)。官方默认 K=100,但我实际跑下来,在目标数量不太多的场景(比如单张图 20 个以内的目标),把 K 降到 50 能显著减少不必要的后处理计算量,精度损失几乎为零。反过来,如果做密集场景(街景、人群),K=100 都不够,我会提到 200,然后看热图质量决定是否加一个简单的置信度阈值过滤。
阈值怎么选?官方不设阈值,只是取 top-k 之后按照分数排序输出。这意味着即使预测分数很低(小于 0.1),它也会输出一个框。实践上我会加一个输出分数阈值(例如 0.3),避免大量低质量框污染评估结果。但是这个阈值不宜太高,因为 CenterNet 的分数分布普遍比较保守,我见过很多正确框的得分只有 0.3-0.5 左右就正常输出了,所以阈值设在 0.25-0.35 之间比较合理。
此外,如果你想在推理时获得更好的定位精度,可以把输出特征图的上采样倍数注意一下。CenterNet 默认下采样 4 倍,如果目标普遍很小,下采样 4 倍会让某些目标中心直接落在特征图的整数格点之间,这时偏移分支的预测压力会变大。有一个低成本方案:把输入分辨率提升到 640 或 768,往往比换更强的骨干网络更直接地提升小目标检测效果。
4. 实战踩坑实录:CenterNet 使用中的典型问题和排查思路
4.1 小目标漏检:中心点的天然劣势
在所有 anchor-free 方法里,小目标都是难点。CenterNet 尤其明显:如果两个小物体靠得近,它们的中心点在低分辨率热图上可能只隔 1-2 个像素,高斯核一扩展就会融合,网络很难输出两个清晰的独立峰值。我在密集货架商品检测任务上就遇到过这种情况:两瓶紧挨着的洗护用品,检测结果经常二变一。
排查思路:首先确认是不是下采样倍数太高。R=4 通常还能接受,但如果你的骨干网络本身有 5 次 stride=2 的下采样,再叠加检测头的输出,实际下采样可能更大。其次试一下增大输入分辨率。这个方法在训练和推理阶段同时生效,对小目标非常有效。另外你也可以考虑把高斯核半径适当缩小一点,减少相邻目标的软正样本区域重叠。不过这个操作要谨慎,因为你同时会降低正样本的覆盖范围,可能导致中心点漏检。我最后的折中方案是在训练时对密集小目标做马赛克增强,强制网络同时学习分离相邻峰值。
4.2 重叠和遮挡目标:一个中心点覆盖另一个
当两个同类目标高度重叠时,CenterNet 在高斯图上只能看到一个大而平的峰,很难分离。和高密度小目标不同的地方在于,这类重叠目标往往是大目标,中心点的语义本身还是清晰的(比如一个大人站在另一个人前面),但后面的那个人中心就被覆盖了。
这时候纯 CenterNet 几乎没有还手之力。我的经验是,对于存在严重遮挡的业务,最好在 CenterNet 基础上额外引入一个“局部峰值校正”分支,或者在热图输出之后做一个基于梯度的局部最大值搜索,而不是简单取 top-k。还有一种思路是用多尺度热图融合:同时预测原尺寸和两倍下采样的热图,然后按位置融合分数,能在一定程度上恢复部分被覆盖的中心。
4.3 训练后期 loss 下降缓慢,热图响应变得模糊
CenterNet 训练过程中有个比较普遍的现象:前期热图损失下降很快,但到了中后期(尤其是使用 DLA 骨架时)loss 曲线变得平缓,热图的峰值越来越模糊。这种情况往往和正负样本比例失衡、高斯核半径设置不当有关。
我的排查顺序是先检查标签热图的可视化结果。你会发现有些目标的热图峰值根本不是 1,而是 0.7、0.8——这说明高斯核半径的计算在这个类别下偏大或者相邻目标重叠区域太多,导致软正样本区域淹没了真正的中心。对症下药有两个方向:一是调小半径(我通常会把 IoU 阈值从 0.7 降到 0.5,这样半径会变小),二是把损失函数里的负样本惩罚权重调大,让网络更关注远离中心的区域,减少模糊响应。
另外,如果你的数据集中有大量宽高比接近 1:1 的方形目标,高斯核半径会相对稳定;但遇到长条形目标(比如桥梁、飞机),高斯核半径几乎是完全不同的数量级,这时候你可能需要单独为长宽比极值类别定制半径计算函数。我当时的解决方案是直接把半径计算从“基于 IoU 阈值”改成“基于最长边比例”,并在验证集上对比了两周,效果提升大约 2-3 个点。
4.4 模型部署时 BN 层统计量漂移
CenterNet 的骨干网络一般带有 BatchNorm 层。训练和推理阶段的统计量不一致几乎是老生常谈,但在 CenterNet 上有个特殊问题:热图输出对全局像素的激活幅度非常敏感,BN 漂移会导致整个热图响应整体偏移,有时候表现为所有物体分数整体降低,有时候表现为输出大量低置信度域。
我在边缘设备部署时遇到的就是最后一种:在开发机上跑 mAP 还可以,导出后本地推理目标分数全线下降,漏检严重。排查方法很简单,把训练好的模型在少量验证图片上重新跑一遍统计量(相当于把 BN 的 running_mean/running_var 重新校准),很快就能止血。这个经验虽然不新鲜,但在 CenterNet 这种热图输出型的检测器上尤其重要,因为热图分数的“绝对值”并没有像分类器输出那样经过 softmax 校准,直接拿 BN 统计量去跨设备推理风险更高。
5. 和同期无 Anchor 方法的横向对比:CenterNet、CornerNet 与后续 DETR 的关系
放到 2019-2020 年那个时间节点看,无 Anchor / 无 NMS 其实是一条很热门的技术路线,CenterNet 只是其中一支。为了让你对它在技术版图中的位置有更直观的感觉,我把几个代表性方法做了对比:
| 方法 | 预测目标 | NMS 依赖 | 最大优势 | 最大短板 |
|---|---|---|---|---|
| CornerNet | 左上角 + 右下角关键点 | 需要(角点配对) | 角点检测独立性强 | 角点全局上下文弱,误配率高 |
| CenterNet | 中心点 + 宽高 | 不需要 | 流程最简、速度优势明显 | 重叠遮挡难处理 |
| DETR | 目标查询序列 | 不需要(匈牙利匹配) | 端到端全局建模 | 训练收敛慢,小目标不稳 |
从架构演进角度来说,CenterNet 实现了“单阶段、全卷积、无 anchor、无 NMS”的最简组合,后处理代码量极低;CornerNet 虽然也去掉了 anchor,但仍需通过嵌入向量对角点进行配对,本质上是“关键点集合的匹配问题”。DETR 则是用注意力机制替代了空间归纳偏置,虽然也能去掉 NMS,但它通过集合匹配直接输出有序集合,训练方式和 CenterNet 完全不同。
另一个常被忽略的对比维度是“误差传播路径”。CornerNet 的检测精度依赖两个角点的独立预测准确性,而 CenterNet 只需要一个点(中心点)的预测质量。从误差累积角度看,CenterNet 的路径更短。这正好解释了为什么在同等网络规模和数据集条件下,CenterNet 的推理延迟和内存占用都比 CornerNet 简洁,训练稳定性也更友好。
当然,CenterNet 的无 NMS 特性也带来一个隐患:它没有显式地建模“一个物体不应该被两个中心点重复检测”这个约束。DETR 里的集合匹配天然带有“唯一分配”约束,所以在遮挡和重叠场景下,DETR 的端到端能力往往优于 CenterNet,但也付出了收敛速度慢的代价。每个方法都是取舍,不能指望一个模型把所有优点占全。
6. 写在最后的几条实操建议
关于 CenterNet,如果只让我留三条经验给后来者,我会选:
第一条,先把标签可视化做好。任何检测任务,训练之前把热图标签、偏移图和尺寸图可视化出来看几遍,花不了多少时间,但能解决大部分“不知道为什么训练不稳”的疑问。CenterNet 的标签质量几乎决定了上限,这一步怎么强调都不过分。
第二条,尽量保持推理输入尺寸和训练输入尺寸一致。CenterNet 虽然对分辨率变化的鲁棒性不错,但如果你训练用 512,推理用 384,小目标的定位精度会明显下降。真要变更分辨率,最好把偏移分支的权重稍微调高一点,并重新跑一遍验证集。
第三条,不要迷信“完全不需要 NMS”。业务落地时,尤其是高重叠或场景目标密集时,加一个轻量 NMS 或者峰值合并操作,往往是性价比最高的纠错手段。设计理念归设计理念,工程上永远以最终指标说话。
CenterNet 是我个人很喜欢的一个检测器思路,因为它的核心思想足够简单深刻,真正把目标检测推进到了“关键点检测 + 几何解码”的框架下。如果你正在做轻量化模型选型、或者是想理解 Anchor-free 方法为什么能跑起来,从 CenterNet 入手是很好的切入点。后续如果再有机会,我也想聊聊在 CenterNet 基础上做多尺度融合和跨类别峰值分离的改进方案,那些话题踩坑更多,但收获也更大。