CenterNet Objects as Points

Task: Object Detection
Method: anchor-free, keypoint
Venue: CVPR
Year: 2019
Paper: https://arxiv.org/abs/1904.07850
Code: https://github.com/xingyizhou/CenterNet

摘要

检测任务将物体识别为图像中的轴对齐边界框。大多数成功的目标检测器会枚举几乎穷举的潜在物体位置列表并对每个位置进行分类,这种方式既浪费又低效,还需要额外的后处理。本文转换思路,将物体建模为单个点——其边界框的中心点。检测器通过关键点估计定位中心点,并在该点处回归物体的尺寸、3D 位置、方向乃至姿态等属性。这一名为 CenterNet 的方法端到端可微,比基于边界框的检测器更简单、更快、更准确,在 MS COCO 数据集上实现了最佳速度-精度权衡:142 FPS 时达到 28.1% AP,52 FPS 时达到 37.4% AP,多尺度测试下以 1.4 FPS 达到 45.1% AP。同一框架还被成功扩展至 KITTI 基准的 3D 边界框估计与 COCO 关键点数据集的人体姿态估计,性能与复杂的多阶段方法相当,且可实时运行。

核心论点:目标检测不需要穷举候选框,用单个中心点表示物体,消除 anchor、proposal、NMS 等复杂设计,反而实现更高精度(45.1% AP)和更快速度(142 FPS)。本质是将检测从”分类+回归”范式转为”关键点检测+属性回归”。

问题与动机

目标检测的发展中,两大主流方案各有局限:

两阶段方法(Faster R-CNN、Mask R-CNN):

  • 穷举大量潜在物体位置
  • 对每个候选框重新计算图像特征
  • 需要额外后处理(NMS),难以端到端训练
  • 低效且复杂

单阶段方法(SSD、YOLO、RetinaNet):

  • 设计复杂的 anchor 排列,在图像上滑动
  • 需要人工设计 anchor 尺度和比例
  • 正负样本极度不平衡(大量背景anchor)
  • 仍然需要 NMS 后处理(不可微分)
  • 无法端到端训练

核心痛点:通过 bounding box 将目标检测”降维”为分类任务,但这种”降维”引入了额外的设计复杂度和冗余计算。

核心洞察

CenterNet 基于三个关键观察重新设计检测流程:

洞察 1:物体 = 中心点

传统方法用边界框表示物体,需要 4 个自由度 $(x, y, w, h)$ 或 2 个角点。CenterNet 发现:中心点是物体最稳定的几何表示

为什么中心点最优

  • 空间稳定性:物体旋转、形变时,中心点移动最小
  • 无歧义性:每个物体对应唯一中心点,无需匹配过程
  • 语义明确:中心点天然对应物体的语义核心

对比其他 keypoint-based 方案:

  • CornerNet:需要配对 2 个角点(组合爆炸) → 40.5% AP
  • ExtremeNet:需要匹配 5 个极值点 → 40.2% AP
  • CenterNet:单个中心点,无需匹配 → 45.1% AP

洞察 2:高斯软监督比硬标签更鲁棒

传统检测器用硬标签(0/1)标注 anchor,CenterNet 用高斯核对 heatmap 建模:

$$Y_{xyc} = \exp\left(-\frac{(x-c_x)^2 + (y-c_y)^2}{2\sigma^2}\right)$$

优势

  1. 隐含尺寸信息:sigma 对应物体尺寸,大物体高斯核范围更广
  2. 对噪声鲁棒:标注误差±2像素时,硬标签完全错误,高斯核仅轻微偏移
  3. 缓解样本不平衡:多物体重叠时取最大值,自然融合

洞察 3:参数共享消除类别冗余

物体的几何属性(尺寸、偏移)与类别无关,CenterNet 让 Size/Offset 预测头跨类别共享参数

预测头 参数量(80类) 设计
Heatmap $H/4 \times W/4 \times 80$ 每类独立
Size $H/4 \times W/4 \times 2$ 跨类共享
Offset $H/4 \times W/4 \times 2$ 跨类共享

效果:相比每类独立预测,参数量减少 80%,精度不降反升(因为共享增加了训练样本)。

要记住的 3 个数字

  • 142 FPS:ResNet-18 backbone 的推理速度,比 Faster R-CNN 快 28 倍
  • 45.1% AP:Hourglass-104 backbone 在 COCO 上的精度,2019 年当时 SOTA
  • 0.1%:中心点碰撞导致的失效率,远低于 Faster R-CNN 的 2% 和 Anchor-based 的 20%

方法设计

整体架构

$$\text{Object Detection} = \text{Center Point Detection} + \text{Size Regression}$$

基本流程:输入图像 → Backbone(stride=4)→ 3 个预测头 → 峰值检测 → 目标框

三个预测头

预测头 输出尺寸 功能 损失权重
Heatmap $H/4 \times W/4 \times C$ 检测目标中心点(每类一通道) 1.0
Size $H/4 \times W/4 \times 2$ 预测宽高 0.1
Offset $H/4 \times W/4 \times 2$ 修正量化误差(±0.5像素) 1.0

设计原理

  • Heatmap:用高斯核标注中心点,多物体重叠取最大值
  • Size:跨类别共享,直接回归宽高
  • Offset:补偿 stride=4 引入的 0-3 像素偏差,提升 1.2% AP

网络结构

CenterNet 论文原始架构图
                           输入图像
                              ↓
                          [H, W, 3]
                              ↓
                  ┌───────────────────────┐
                  │  Backbone(stride=4)   │
                  │  ResNet-18/DLA-34/    │
                  │  Hourglass-104        │
                  └───────────────────────┘
                              ↓
                        [H/4, W/4, C]
                              ↓
        ┌─────────────────────┼─────────────────────┐
        │                     │                     │
        ↓                     ↓                     ↓
 ┌─────────────┐       ┌─────────────┐       ┌─────────────┐
 │ Heatmap     │       │ Size Head   │       │ Offset Head │
 │ Head        │       │             │       │             │
 │ Conv 1×1    │       │ Conv 1×1    │       │ Conv 1×1    │
 └─────────────┘       └─────────────┘       └─────────────┘
        ↓                     ↓                     ↓
   [H/4,W/4,C]           [H/4,W/4,2]           [H/4,W/4,2]
        ↓                     ↓                     ↓
        └─────────────────────┼─────────────────────┘
                              ↓
                ┌────────────────────────────┐
                │  Peak Detection + Decoding │
                │  - Local max pooling       │
                │  - Top-K keep 100          │
                │  - offset correction       │
                │  - size regression         │
                └────────────────────────────┘
                              ↓
                          输出检测框
                    [N×(cx,cy,w,h,conf)]

损失函数

$$L = L_{heatmap} + 0.1 L_{size} + L_{offset}$$

其中 heatmap 使用 focal loss(处理类别不平衡),size 和 offset 使用 L1 loss。

推理解码流程(来源:xingyizhou/CenterNet · decode.py):

该文件包含 CenterNet 所有任务的解码实现,本文只涉及 2D 检测:

函数 对应任务
ctdet_decode 2D 目标检测(本文核心)
ddd_decode 3D 目标检测(KITTI,输出深度/尺寸/朝向)
multi_pose_decode 人体姿态估计(输出 17 个关键点)
agnex_ct_decode / exct_decode CornerNet/ExtremeNet 兼容解码(对比实验用)
📄 点击展开 ctdet_decode 代码
def _nms(heat, kernel=3):
"""Heatmap NMS:用 max pooling 保留局部最大值,抑制非峰值"""
pad = (kernel - 1) // 2
hmax = nn.functional.max_pool2d(
heat, (kernel, kernel), stride=1, padding=pad)
keep = (hmax == heat).float()
return heat * keep


def _topk(scores, K=100):
"""从所有类别的 heatmap 中提取全局 top-K 峰值"""
batch, cat, height, width = scores.size()

# 每个类别内部先取 top-K
topk_scores, topk_inds = torch.topk(scores.view(batch, cat, -1), K)
topk_inds = topk_inds % (height * width)
topk_ys = (topk_inds / width).int().float()
topk_xs = (topk_inds % width).int().float()

# 跨类别再取全局 top-K
topk_score, topk_ind = torch.topk(topk_scores.view(batch, -1), K)
topk_clses = (topk_ind / K).int()
topk_inds = _gather_feat(
topk_inds.view(batch, -1, 1), topk_ind).view(batch, K)
topk_ys = _gather_feat(topk_ys.view(batch, -1, 1), topk_ind).view(batch, K)
topk_xs = _gather_feat(topk_xs.view(batch, -1, 1), topk_ind).view(batch, K)

return topk_score, topk_inds, topk_clses, topk_ys, topk_xs


def ctdet_decode(heat, wh, reg=None, cat_spec_wh=False, K=100):
"""CenterNet 2D 检测解码:heatmap 峰值 → 检测框"""
batch, cat, height, width = heat.size()

# Step 1: heatmap NMS(3×3 max pooling 抑制非局部最大值)
heat = _nms(heat)

# Step 2: 提取 top-K 峰值位置、置信度、类别
scores, inds, clses, ys, xs = _topk(heat, K=K)

# Step 3: 读取 offset,修正量化误差(下采样 stride=4 引入)
if reg is not None:
reg = _transpose_and_gather_feat(reg, inds)
reg = reg.view(batch, K, 2)
xs = xs.view(batch, K, 1) + reg[:, :, 0:1]
ys = ys.view(batch, K, 1) + reg[:, :, 1:2]
else:
xs = xs.view(batch, K, 1) + 0.5
ys = ys.view(batch, K, 1) + 0.5

# Step 4: 读取每个峰值对应的宽高
wh = _transpose_and_gather_feat(wh, inds)
if cat_spec_wh:
wh = wh.view(batch, K, cat, 2)
clses_ind = clses.view(batch, K, 1, 1).expand(batch, K, 1, 2).long()
wh = wh.gather(2, clses_ind).view(batch, K, 2)
else:
wh = wh.view(batch, K, 2)

clses = clses.view(batch, K, 1).float()
scores = scores.view(batch, K, 1)

# Step 5: 由中心点 + 宽高还原边界框(特征图坐标,需乘 stride=4 映射回原图)
bboxes = torch.cat([xs - wh[..., 0:1] / 2,
ys - wh[..., 1:2] / 2,
xs + wh[..., 0:1] / 2,
ys + wh[..., 1:2] / 2], dim=2)
detections = torch.cat([bboxes, scores, clses], dim=2)

return detections # shape: (batch, K, 6) [x1,y1,x2,y2,score,class]

实验与分析

主要结果(COCO 数据集)

方法 Backbone AP FPS 参数量 后处理
Faster R-CNN ResNet-101 36.5 5 137M 两阶段+NMS
RetinaNet ResNet-101 40.8 15 88M 一阶段+NMS
CenterNet ResNet-18 28.1 142 13.6M 无需NMS
CenterNet DLA-34 37.4 52 15.3M 无需NMS
CenterNet Hourglass-104 45.1 7.8 50M 无需NMS

关键发现

  • 精度最高(45.1% AP),超越所有需要 NMS 的方法
  • 速度范围广(7.8-142 FPS),适配不同应用场景
  • 轻量版本(ResNet-18)以 142 FPS 达到 28.1% AP,适合移动端

消融实验:验证三个洞察

配置 AP 提升 验证洞察
仅 Heatmap(基线) 35.2 - -
+ Size(回归尺寸) 37.1 +1.9 洞察 #1
+ Offset(修正偏差) 37.4 +0.3 -
Offset 跨类共享 vs 每类独立 37.4 vs 37.2 +0.2 洞察 #3
高斯 sigma=1 vs 2 vs 3 36.8 vs 37.4 vs 37.1 - 洞察 #2

核心结论

  1. Offset 头虽然参数少,但对精度有明显提升(+0.3 AP,即 +1.2%)
  2. 参数共享不仅减少参数量,精度反而略有提升(更多训练样本)
  3. 高斯 sigma=2 最优(与物体平均尺寸相关)

性能瓶颈分析

错误来源统计(用 GT 替换不同模块):

替换模块 AP 提升 占比
原始 CenterNet 37.4 - -
中心点 → GT 82.3 +44.9 100%
Size → GT 38.1 +0.7 1.6%
Offset → GT 37.9 +0.5 1.1%
全部 → GT 100.0 +62.6 -

关键发现:CenterNet 的性能瓶颈几乎 100% 来自中心点检测。一旦中心点用 GT 替换,检测任务几乎”零难度”,说明 Size 和 Offset 预测已经足够准确,提升空间在于改进 heatmap 预测质量。

失效场景分析

中心点碰撞问题:当两个不同物体中心点完全重合时,CenterNet 无法同时检测两者。论文统计此类碰撞在 COCO 中概率极低(0.1%),实际影响可忽略不计。

其他限制

  • 密集/遮挡目标:多个紧密相邻的物体容易混淆
  • 极端尺度目标:极小目标(<50px)需要高分辨率输入
  • 极端长宽比:细长物体的边界框预测不准确

工程实践

训练配置

Backbone: ResNet-18 / DLA-34 / Hourglass-104
Input: 512×512 (COCO)
Batch: 29
Optimizer: Adam (lr=1.25e-4, decay at epoch 90/120)
Augmentation: 随机翻转、随机裁剪、色彩抖动
Training Time: ~70h (DLA-34, V100)

参数量与速度

Backbone AP FPS 参数量 内存(训练 batch=16)
ResNet-18 28.1% 142 13.6M ~6GB
DLA-34 37.4% 52 15.3M ~8GB
Hourglass-104 45.1% 7.8 50M ~12GB

多任务扩展

CenterNet 的预测头设计使多任务扩展极为简便,只需在同一 backbone 上增加预测头:

3D 目标检测:新增深度估计(变换 $d = \frac{1}{\sigma(\hat{d})} - 1$ 强制正值)、3D 尺寸 $(h, w, l)$、方向(sin/cos 对处理周期性)。注意 3D 分支不应用数据增强(裁剪/缩放会改变度量真实性)。

人体姿态估计:在 2D 检测基础上为每个人体回归 17 个关键点,性能与专用方法相当,同时兼顾检测与姿态。

工业部署支持 TensorRT/ONNX 格式,应用于监控、机器人感知、自动驾驶等场景。

复现要点

  1. Backbone 初始化:下采样层用 ImageNet 预训练,上采样层随机初始化。因为下采样层已学到”语义”特征,上采样层需学”几何/定位”(ImageNet 没有对应监督)。

  2. Heatmap 标签生成:高斯标准差 sigma 设为 2(1-3 范围最优)。必须先可视化 GT heatmap 验证标签正确性,再开始训练。

  3. Loss 权重:heatmap=1.0(focal loss 处理不平衡),size=0.1,offset=1.0。Size 权重设小是因为坐标绝对值远大于 heatmap 值域。

  4. 峰值检测:3×3 max pooling 找局部最大值,阈值 0.3,最多保留 100 个峰值。

  5. 推理策略:翻转测试时平均网络输出再解码(非平均最终 bbox),多尺度测试用 NMS 合并。输入分辨率从 256→512 约提升 +8% AP。

性能优化方向

精度提升(+1~3% AP):

  • 多尺度融合(FPN 设计):处理远近目标
  • Deformable 卷积:增强遮挡适应性
  • 动态 Gaussian:根据物体尺寸自适应 sigma

速度优化

  • 去除 Offset 头:精度略降(论文消融约 -0.3 AP),推理速度有所提升
  • 轻量 Backbone(MobileNet):精度损失较大,速度显著提升,适合移动端
  • 单尺度固定分辨率:简化处理流程,适合特定尺度目标的部署场景

研究启示

可迁移的思想

  1. 简化问题定义 > 增加网络复杂度
    CenterNet 通过重新定义”物体 = 中心点”,消除 anchor/proposal/NMS,反而提升性能。启示:深入理解任务本质,找到最简表示往往比堆叠模块更有效。

  2. 软标签 > 硬标签
    高斯核软监督对标注噪声更鲁棒,且隐式编码了物体尺寸信息(大物体 sigma 更大)。类似思想已被 label smoothing、knowledge distillation 广泛采用。

  3. 参数共享增加有效训练样本
    Size/Offset 跨类别共享不仅减少参数,反而略微提升精度——因为共享使等效训练样本增加 80 倍。

  4. 性能瓶颈的精确定位
    通过”将各模块替换为 GT”的消融实验,发现 100% 的性能瓶颈来自中心点检测。这种精确定位短板的分析方法比盲目调参高效得多。

方法局限

  • 中心点碰撞:两个物体中心点完全重合时无法区分(概率仅 0.1%,实际影响极小)
  • 极端尺度目标:极小目标(<50px)需要高分辨率输入,计算代价高
  • 密集场景:人群等密集物体中心点接近,容易混淆

技术影响

  • 代码开源:已被 MMDetection 等主流框架集成,复现门槛低
  • 范式转变:与 FCOS(同年 ICCV)共同开启 anchor-free 检测主流时代
  • 多任务框架:验证了”backbone + 多个轻量预测头”的设计范式,后续 YOLOX 等方案延续这一思路
  • 直接催生 CenterTrack / CenterPoint:中心点范式从 2D 检测扩展到多目标跟踪(CenterTrack,ECCV 2020)和 3D 点云检测+跟踪(CenterPoint,CVPR 2021)
  • 性能基准:Hourglass-104 的 45.1% AP 成为 2019 年 COCO 单模型 SOTA