"); //-->
一、CenterPoint 是一个怎样的 3D 检测模型?本文以地平线 Open Explorer(OE)中的 CenterPoint 参考算法为主线,系统梳理 CenterPoint 的模型结构设计、Head 与 box 语义拆分方式,以及在工具链中从训练、导出到编译部署的完整工程语义。文末通过 nuScenes → KITTI 的一次实际配置修改,作为参考算法“应用级改造”的示例,帮助理解这些设计在真实项目中的影响范围。
CenterPoint 是一种 anchor-free、center-based 的 3D 目标检测方法。 它的核心思想并不是“直接预测 3D 框”,而是:
在 BEV 平面 上预测目标中心点(center)
围绕 center 回归目标的几何属性
因此,CenterPoint 的输出天然拆分为多个 语义明确的回归分量,例如:
中心偏移(x, y)
高度(z)
尺寸(w, l, h)
朝向(yaw)
速度(vx, vy,可选)
这也是为什么在 CenterPoint 中,Head 的设计和 box 语义是强绑定的,而不是“随便接几个卷积头”。
二、CenterPoint 的 Head 设计与 box 语义拆分在 OE 的 CenterPoint 配置中,Head 通常通过 common_heads 定义,例如:
common_heads = dict( reg=(2, 2), height=(1, 2), dim=(3, 2), rot=(2, 2), vel=(2, 2), )
这里的每一项并不只是“网络输出通道数”,而是明确对应 box 的几何语义拆分:
几个关键点需要强调:
rot 使用 sin / cos 表达这是为了避免角度回归的周期不连续问题,因此训练回归维度中,yaw 始终占用 2 个通道。
Head 的 insertion order 很重要 CenterPoint 在 deploy 模式下会按 Head key 的顺序扁平化输出,这直接影响导出 HBIR 和最终推理输出 tensor 的语义顺序。
在 CenterPoint 中,经常会看到如下配置:
postprocess = dict( box_size=9, )
需要明确的是:
3.1 nuScenes 场景:box_size = 9box_size 表示的是 postprocess 之后,最终输出给下游使用的 box 物理维度,而不是训练阶段的回归维度。
在 nuScenes 数据集中,CenterPoint 通常开启 velocity,因此最终输出 box 语义为:
[x, y, z, w, l, h, yaw, vx, vy]
这 9 个量分别来自:
reg → x, y
height → z
dim → w, l, h
rot → yaw(由 sin/cos 反解)
vel → vx, vy
因此,box_size=9 是一个语义必然结果,而不是经验值。
3.2 训练回归维度(code_size)与 box_size 并不相同一个容易混淆的点是:
训练阶段回归维度(code_size)
推理阶段输出维度(box_size)
以 nuScenes 为例:
训练回归维度 = 10
reg(2) + height(1) + dim(3) + rot(2) + vel(2)
推理输出维度 = 9
yaw 从 sin/cos 合并为 1 个角度
在训练或评估阶段:
输入:example["points"](raw point cloud)
处理流程:
pre_process → reader → backbone → neck → head → target/loss 或 postprocess
其中 pre_process 会完成体素化、点云归一化以及 pillar 特征编码,这些过程包含:
动态点数
非规则张量
不适合直接导出为静态 IR
在导出 HBIR 或部署推理时:
不再接收 raw 点云
输入变为:
features + coors
流程变为:
reader → backbone → neck → head → flatten outputs
原因很明确:
BPU / IR 编译需要 静态、确定形状的输入
点云体素化包含动态结构,不利于导出
将点云预处理放到外部流水线(CPU / DSP)更可控,也更利于性能调优
在 OE 示例中,deploy_inputs 通常形如:
features: [1, C, P, M]
coors: [M, 4],格式为 [batch_idx, z, y, x]
这两者必须与 CenterPointPreProcess 的输出严格一致,否则导出或推理阶段会出现维度或 scatter 错误。
五、编译阶段的输出语义:output_layout 与 transpose_dim在模型编译配置中,常见如下设置:
compile_cfg = dict(
output_layout="NHWC",
transpose_dim=dict(
outputs={"global": [0, 2, 3, 1]}
),
)这里需要区分两个概念:
真正生效的,是 transpose_dim
工具链会在输出节点插入 transpose
output_layout 更多是 语义标注
也就是说:
是否从 NCHW 转为 NHWC,取决于 transpose_dim,而不是 output_layout 字符串本身。
工程上建议: output_layout 与 transpose_dim 保持一致,避免下游推理或解析代码误读输出格式。
六、参考算法的一次应用修改示例:nuScenes → KITTI在理解了 CenterPoint 的模型结构与输出语义之后,再来看一个非常典型的应用场景:将 nuScenes 的 CenterPoint 配置修改为 KITTI 使用。
6.1 目标差异KITTI 不定义 velocity
最终推理输出 box 语义应为:
[x, y, z, w, l, h, yaw]
即:
推理 box_size = 7
训练回归维度仍为 8(rot 使用 sin/cos)
这类修改必须同步覆盖以下模块:
Head(移除 vel)
Target / Loss(不再生成或监督 velocity)
PostProcess / BBoxCoder(不再 decode vel)
deploy flatten 输出顺序
下游解析与评测逻辑
一个实用的自检原则是:
训练回归维度 = len(code_weights) = target anno_box dim推理输出维度 = **postprocess.box_size**
二者必须分别自洽,否则一定存在隐患。
七、小结CenterPoint 在地平线工具链中并不是一个“只改配置就能安全迁移”的模型:
box 语义来自 Head 设计
训练与推理的维度并不等价
deploy 模式下的输入、输出和编译布局都有严格约束
一个看似简单的 with_velocity 开关,实际影响的是 跨模块的系统行为
理解 从模型结构 → 语义拆分 → 工具链部署 的完整链路,才能正确使用参考算法。
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。