
1. 项目整体设计与思路拆解为什么从Dense转向Sparse是必然之路Sparse4Dv3这个名字如果你不是做自动驾驶感知方向的可能第一眼觉得陌生但它在纯视觉3D目标检测这个圈子里算是一个标志性的存在。简单说这套算法解决的是一个问题只用车上装的多个摄像头不依赖激光雷达如何在三维空间里准确检测出周围的车、行人、障碍物并且输出它们的位置、大小、朝向和运动速度。这个问题难在哪难点在于摄像头拿到的是2D图像没有深度信息。你看到一张照片能判断里面有辆车但很难直接说清楚这辆车离你多少米、车头朝哪个方向、车身实际有多长。而自动驾驶下游的规划控制模块恰恰需要的是三维空间里的精确信息。Sparse4Dv3做的事情就是从多个相机的2D图像里把3D信息算出来。先说结论这个方案最核心的变化是彻底抛弃了上一代方案里常用的BEVBirds Eye View鸟瞰视角特征图改成了一整套纯稀疏的设计。用一句话概括就是不再先构造一张上帝视角的全局地图特征再在地图上找目标而是直接预设一组稀疏的锚点让每个锚点直接在原始图像特征里拉取自己需要的信息然后迭代优化出目标框。为了理解这个转变有多重要需要先看一下它之前的方案是怎么做的。1.1 为什么纯视觉3D检测值得关注在很长一段时间里行业内做3D目标检测默认的标准答案是激光雷达。激光雷达直接发射激光束靠反射回来的点云算出精确的三维坐标技术成熟、精度高很多量产L2车型和高阶Robotaxi都靠它。但激光雷达有两个绕不开的问题一是贵虽然这几年价格被卷下来不少但和摄像头相比仍然是天价二是物理特性的天花板激光雷达在雨雪、大雾等恶劣天气下性能衰减严重而且它只能看见一个横截面层面的点纹理、颜色、交通标志上的文字这类信息是缺失的。摄像头方案的优势在于便宜、信息丰富、产业链成熟。十几年前Mobileye就在用单目摄像头做前撞预警但那只是2D感知。要让纯视觉方案达到接近激光雷达的3D检测精度就需要算法层面有大的突破。Sparse4Dv3就是这条技术路线上的一个关键节点它和Tesla的Occupancy Network、BEVFormer这类方案一样都在探索纯视觉到底能不能扛起自动驾驶感知的大旗。1.2 Sparse4Dv3之前的方案瓶颈在哪纯视觉做3D检测大致经历了几个阶段。早期的方案叫2D检测后处理就是先在2D图像上检测出目标框再用地面的平面约束强行反推出三维位置。这种方式精度很差因为单目图像本身就存在尺度歧义——一个近处的小车和一个远处的大客车在图像上可能占据同样的像素面积单靠2D框根本分不清。后来出现了基于Dense BEV的方案代表就是BEVFormer系列。这类方案的思路是既然单车视角的信息不够那就先把多个摄像头看到的图像特征铺到一个俯视图上构造出一张完整的BEV特征图然后在BEV特征图上做3D检测。这个思路和激光雷达点云的处理方式很像先建一张全局地图再在地图上做目标检测直觉上很自然。但BEV方案有个致命问题计算量和分辨率矛盾。BEV特征图本质上是把连续的3D空间离散成一个网格网格越细能看到的细节越多但计算量也越大。为了保证远处的小目标能被检测到网格必须做得足够密为了保证感知范围足够广网格面积必须足够大。这两个需求叠加在一起BEV特征图的通道数和空间分辨率都高得吓人。我在实际复现BEVFormer的时候单是BEV encoder部分的显存占用就让A100都感到吃力更别提把它部署到车规级芯片上。更麻烦的是BEV上绝大多数的网格其实都是空的。城市道路环境里周围可能就几辆车、几个行人但BEV特征图却把整条路、整片天空都表示了进来其中绝大部分计算都浪费在了没有目标的区域上。这是Dense方案的原罪。1.3 Sparse4Dv3的整体设计逻辑Sparse4Dv3的思路一句话概括就是把计算资源集中在真正可能有目标的地方。它不再显式构造BEV特征图而是像DETR那样预设一组稀疏的、可学习的锚点anchor每个锚点代表一个潜在的目标。这些锚点一开始完全不知道自己在哪但通过和图像特征做注意力交互它们能自己学会移动到目标的真实位置同时输出目标的类别、3D框尺寸、朝向角、速度等信息。这种稀疏的思路天然解决了Dense方案的两个痛点。第一计算量大幅下降因为锚点数量远小于BEV网格数量而且锚点之间没有空间上的耦合关系计算可以高度并行第二感知范围没有上限你不需要预先定义一个多大范围的BEV锚点可以在任意位置采样特征远处有目标就检测远处的不会受限于网格边界。当然稀疏方案也有自己的难题锚点怎么初始化特征从哪里采怎么避免多个锚点同时检测同一个目标Sparse4Dv3在第三代版本里把这些问题都做了针对性的优化。后面的内容我会逐个拆解。2. 三个核心机制拆解锚点、时序采样、迭代优化Sparse4Dv3虽然整体架构复杂但核心机制可以拆成三块稀疏锚点机制、4D特征采样机制、以及循环迭代优化机制。这三块是理解整篇论文的钥匙。2.1 稀疏锚点用几百个查询代替整张BEV特征图先讲锚点机制。这里的锚点可以理解成一群有自己独立参数的查询者每一个锚点都是一个向量编码了目标可能出现的3D位置x, y, z、尺寸长宽高、朝向角yaw以及类别信息。在第一层这些锚点往往是随机初始化的或者根据先验信息分布在整个3D空间里。它们会生成一个初始的3D框预测尽管这个预测非常粗糙。然后模型会根据预测的3D框把锚点投影到各个相机的图像平面上去查看对应位置有没有目标特征。如果有就把这个特征拉回来更新锚点自身的编码如果没有锚点就知道自己可能预测偏了会在下一轮调整自己的位置。这个机制和人类的扫视行为有点像。你找一个东西不会挨个扫描整面墙的每个像素而是先在几个可能的位置扫一眼如果没看到再根据局部线索跳到下一个可能的位置。稀疏锚点做的就是这件事它有方向性地去搜索而不是盲目地密集扫描。实际操作中锚点的数量是一个关键超参。我在复现时试过300个、500个、900个三档效果差别很明显。数量太少遇到车多密集的场景高速堵车时一个画面里可能有30到50辆车会不够用出现漏检数量太多虽然有冗余但计算量线性增长而且容易导致多个锚点同时检测同一个目标产生大量重复检测。Sparse4Dv3默认取的是900个锚点左右在精度和速度之间取了一个平衡。这个数量其实就是自适应的——即使锚点很多空旷场景下大部分锚点也会在迭代过程中被抑制掉理论上的上限决定了它能处理多复杂的场景。2.2 4D特征采样时间维度带来空间维度的提升4D指的是什么指的是三维空间加一维时间。Sparse4Dv3在做特征采样时不只采当前帧的图像特征还会把历史帧的特征也拉进来一起参考。为什么需要历史帧因为单帧图像的信息实在太有限了。一个典型的场景前车打转向灯准备变道它的车身姿态正在变化中如果只看当前帧你可能判断它正在直行但如果结合前一帧、前两帧的信息就能看出它在横移进而更准确地推断它的朝向和速度。另一个场景是目标被部分遮挡比如一个行人走在一辆大货车后面当前帧只能看到半个身子如果结合历史帧系统记住了这个行人的完整轮廓检测置信度会高很多。在技术实现上Sparse4Dv3的4D采样分两步。第一步是空间对齐当前帧检测出的目标框根据自车运动信息IMU和轮速计提供的ego motion投影到历史帧的坐标系下算出这个目标在历史帧图像里的位置。第二步是特征聚合在历史帧图像的对应位置采样特征通过时序注意力机制把这些特征和当前帧特征做融合。这里有一个非常关键的细节特征是在图像空间采样的而不是在BEV空间采样的。v1版本是在BEV特征图上做时序融合的但v3版本改成了直接在多视角图像特征上采样。这样的好处是少了一个BEV特征生成的步骤既省内存又避免了BEV离散化带来的信息丢失。代价是图像特征空间和3D空间之间的投影关系必须算得足够准否则采样位置会偏特征就采歪了。这也是为什么v3版本特别强调深度估计能力——如果模型对目标深度判断不准投影到历史帧的位置就错得离谱时序融合不但没有帮助反而会引入噪声。2.3 循环迭代优化预测框是怎么一步步变准的稀疏锚点的初始预测通常非常粗糙靠一次注意力交互就能输出精确的3D框这不现实。Sparse4Dv3借鉴了Cascade R-CNN的思想采用多阶段迭代优化第一层的输出作为第二层的新锚点继续和图像特征交互继续细化和修正。论文里的decoder共有6层每一层都在前一层的基础上做精修。听起来很直观但实现上有不少细节值得注意。每一层decoder在做特征采样时不是只采一个点而是沿着预测框的关键位置采多个点——比如3D框的中心点、四个角点、以及各个面的中心点。每个采样点都带了不同的局部信息中心点看到的是目标内部的特征角点看到的是目标边缘的轮廓把这些信息聚合起来才能更全面地判断目标到底是个什么东西、长什么样。迭代优化的好处是由粗到精。我在实际训练中观察到一个很有意思的现象前面几层decoder输出的框位置误差通常比较大但类别置信度往往已经比较高了而后面的层更专注于把框的边缘抠准类别不再有大的变化。这说明模型自己学到了一个合理的分工——先判断有没有、是什么再精细化在哪里、有多大。2.4 Depth信息如何帮模型提高感知精度这里需要专门说一下深度估计因为在纯视觉3D检测里深度是最核心的中间变量。2D图像本身不携带深度信息所以模型必须从各种视觉线索里猜出深度——比如目标的大小一个在图像上占100像素的已知车型大概率离得近、目标的垂直位置靠近地平线的目标通常更远、目标周围的上下文被车道线遮挡的程度等等。Sparse4Dv3在特征采样时引入了一个很有意思的深度感知机制。它在每个锚点对应的位置先预测一个离散的深度分布——不是说这个目标就在20米而是说这个目标有30%概率在15到20米50%概率在20到25米20%概率在25到30米——然后按照这个分布在不同深度层级上采样特征加权求和得到最终的采样特征。这么做的好处是模型不再是一个拍脑袋定深度的黑盒而是保留了深度方向上的不确定性。在实际场景里深度估计的歧义是真实存在的尤其是远距离的小目标不同深度下它看起来几乎没区别。把这种不确定性显式建模出来等于给模型留了一条后路——如果20米处的特征匹配不上它还能去25米处再碰碰运气。这个设计在实际测试中对远端目标的检测精度提升非常明显。我对比过有无深度感知分支的版本在距离超过40米的目标上3D框的中心点误差降低了将近15%到20%而且模型输出的速度估计也稳定了很多。3. 实操落地从训练到部署的关键细节理论部分讲完了但做算法的人都知道论文里的pipeline和真正跑起来的pipeline之间隔着无数个坑。这部分我结合自己的复现和实验经历讲讲Sparse4Dv3在实操中需要注意的关键点。3.1 数据准备与外参标定Sparse4Dv3的训练数据是环视多相机图像一般用的是nuScenes数据集包含6个方向的相机覆盖360度视野每帧带有精确的3D标注框和自车运动信息。如果要在自己的数据上训练必须保证每个样本的相机内参和外参是精确标定过的而且和图像时间戳严格同步。同步这一点容易被忽略但直接影响模型上限。如果某个相机的图像比其它相机晚采了30毫秒而车速是30m/s那这个相机的所有目标在整个坐标系里就偏移了近1米。模型会学到某个方向上的目标位置系统性偏差30公分这种错误的先验而且很难靠后期调参消除。我踩过这个坑后来在数据预处理阶段加了时间戳对齐的检查把超过10毫秒不同步的样本直接过滤掉模型的mAP立刻涨了一个多点。另外nuScenes的标注框是8个角点的3D框Sparse4Dv3的输出格式也是8个角点但训练损失用的是中心点尺寸朝向角的分解方式。这个分解很关键如果直接把8个角点坐标作为回归目标模型很难收敛因为8个点之间有复杂的几何约束。拆解成一个中心点三个尺寸一个朝向角之后每个目标都变成了独立的、物理意义明确的量回归难度大幅降低。3.2 训练策略与关键超参Sparse4Dv3的backbone我试过ResNet和VoVNet两种。VoVNet整体上比ResNet的表现好大约1个点NDS但backbone部分不是这个模型的性能瓶颈除非追求极致精度否则用ResNet50起步完全够用。训练上有几个关键超参值得注意输入分辨率nuScenes默认是1600x900但为了训练速度很多复现会缩到800x450或类似的尺寸。分辨率下降对mAP的影响比对NDS的影响大因为小目标检测更依赖分辨率。如果显存够建议至少保住960x540以上。训练epochSparse4Dv3的训练周期比较长一般需要24个epoch甚至更久。它和那种两三天就能收敛的小模型完全不同属于火候到了才能出味的类型。我观察前6个epoch的loss下降非常缓慢不要因此误以为模型坏了这是正常的预热阶段。学习率与warmup建议使用cosine学习率衰减搭配前1到2个epoch的线性warmup。初始学习率设在2e-4左右比较稳如果数据量更大可以适度调大。2D预训练权重强烈建议使用在ImageNet或更大的2D检测数据集上预训练过的backbone权重。从零开始训练纯视觉3D检测模型收敛速度和最终精度都会明显吃亏因为backbone对纹理、边缘等基础视觉特征的提取能力需要大量数据才能建立。3.3 评测指标与真实性能表现评价3D检测模型最常用的指标是nuScenes Detection ScoreNDS和mean Average PrecisionmAP。可能很多人对这两个指标的关系不太清楚。简单说mAP衡量的是检测出来的目标和真值匹配得准不准主要看3D中心点距离是否在阈值内NDS是综合指标在mAP的基础上加入了对朝向角误差、速度误差、属性误差的惩罚。两个指标都很重要但NDS更能反映自动驾驶场景下的真实可用度。根据公开数据和复现报告Sparse4Dv3在nuScenes test集上达到了mAP约0.550、NDS约0.628的水平。这个成绩在当前纯视觉方案里属于第一梯队——作为参考很多早期的BEV方案NDS在0.4左右浮动后期的BEVFormer系列能到0.5以上但Sparse4Dv3在参数量和计算量更小的情况下做到了更高的分数。在速度方面Sparse4Dv3的推理效率提升非常可观。相比v2版本v3在去掉BEV encoder之后推理速度提升了约5倍在A100上单卡可以跑到30FPS以上。这个数字意味着它有能力往车端部署的方向走虽然距离量产芯片的实时性要求还有距离但架构方向已经证明是可行的。3.4 部署效率什么场景适合用它很多做量产的朋友会关心一件事这套算法能不能跑在Orin这类车规级芯片上坦诚说纯视觉3D检测模型普遍还到不了轻松实时的量产水平。Sparse4Dv3的推理开销主要在两部分一是backbone对6路图像做特征提取这部分是稠密计算没法省二是decoder部分的交叉注意力虽然锚点是稀疏的但每个锚点要和多个尺度的多路图像特征做交互累计的计算量也不小。不过Sparse4Dv3相比BEV类方案有一个明显的部署优势它不需要显式构造BEV特征图所以不存在一个巨大的中间特征张量需要在不同计算单元之间搬来搬去。在嵌入式设备上张量搬运的时间和能耗有时比计算本身还高Sparse4Dv3的架构天然少了一整块这样的开销。如果要在车端部署我建议的做法是先用一个2D检测器得到一个候选目标区域再让Sparse4Dv3只在这些区域内做精细化3D检测。这样可以大幅减少锚点的搜索范围提速50%以上。精度会有微小损失但换来的是实时性的大幅提升作为一种pipeline优化思路是可行的。4. 常见问题与排障实录这一节整理我在实际复现和调优Sparse4Dv3过程中遇到的典型问题做成一个速查表式的排障清单希望能帮你少走弯路。4.1 训练不收敛或loss震荡这是复现稀疏类检测模型最常遇到的问题而且表现五花八门有的loss一个劲往下掉但指标不动有的一开始就爆炸有的训到一半突然震荡。排查方向有几个先检查深度分支是否异常。深度感知分支是Sparse4Dv3的重要部件如果它不稳定整个模型的梯度都会受影响。可以在训练日志里单独打印depth loss那一项如果它出现NAN或者剧烈震荡优先排查深度真值的生成有没有问题。确认锚点初始化是否符合数据分布。如果锚点初始化的范围远远大于数据集目标的实际分布范围前期的注意力交互会非常低效模型很长时间都在空转。可以打印第一层decoder输出的框的位置统计和目标真值做对比如果完全对不上调整锚点初始化范围。检查正负样本匹配策略。稀疏检测模型要有合适的匈牙利匹配或者类似机制来分配正负样本。如果匹配阈值太严格大量锚点都成为负样本梯度中缺乏正样本贡献模型很快就退化成一个什么都不检测的空模型。4.2 远距离和遮挡目标的漏检这是所有纯视觉3D检测方案的通病。远距离目标在图像上只占十几个像素特征极其微弱被遮挡的目标则面临特征不完整的问题模型很难从残缺的信息中恢复出完整的3D框。我的排障经验是先区分是没检测到还是检测到但框不准。如果是前者检查锚点的分布密度是否在远端区域不够。很多模型的锚点集中在自车近处因为近处的目标更多更重要但这会导致远处一旦出现目标找不到合适的锚点去匹配。解决方案很简单——在远端区域增加锚点初始化密度虽然推理时会多花一点时间但覆盖范围广了。如果是检测到但框不准多半是深度估计在远距离场景下失效了。这时候可以尝试在深度真值上做一个平滑处理或者减少对远距离样本的深度监督权重。我们实验发现对40米以上的目标强制要求极精确的深度预测有时反而会起反作用——监督信号太强模型为了迎合极端样本反而扰乱了中间层的特征表达。4.3 多个锚点输出同一个目标重复检测这也是稀疏检测器常见的毛病尤其在目标密集的场景。根本原因是锚点在迭代过程中互相之间没有交流多个锚点可能收敛到了同一个目标上而且各自都认为自己检测到了。解决思路有几个一是加一个类似NMS的后处理但这只是治标二是让锚点在注意力交互过程中能够感知到彼此的存在论文里用的是在attention计算中加入位置编码让距离近的锚点之间产生相互抑制作用但效果有限三是配合一个目标数量预测分支让模型自己判断当前场景有几个目标再据此抑制多余的检测框。在实际工程上如果追求稳定建议用传统的NMS加一个很低的置信度阈值过滤。如果追求极致体验可以尝试把NMS替换成Soft-NMS或者WBCWeighted Boxes Clustering在重复检测的目标上做一个框的融合效果会比简单抑制好很多。4.4 深度与速度估计的系统性偏差还有一个在实际道路测试中才暴露的问题模型对静止目标的深度估计很准但对运动目标的速度估计有明显滞后。原因是速度估计依赖时序信息。Sparse4Dv3用历史帧特征和当前帧特征做时序融合但如果目标在当前帧出现了剧烈的运动突变比如前车突然急刹车历史帧的信息反而拖累了当前帧的判断。我做了个实验把时序融合的权重在推理时调低发现高速运动场景的精度提升了但低速场景的精度反而下降。最后给出的折中方案是根据目标的速度估计来动态调整时序融合权重。目标是静止时充分利用历史帧信息平滑深度和位置目标速度较快时适当降低历史帧权重更信赖当前帧的观测。这个方案跑下来的效果很稳既保证了大范围场景的覆盖又在极端动态场景下保持了警觉。5. 这个方向的演进空间与个人实践体会Sparse4Dv3让我印象最深的一点是它的设计哲学把资源花在刀刃上不要试图用一个巨大的稠密特征图来覆盖所有可能性而是相信模型能够自己学会该往哪里看。在它之后稀疏感知方向又进化出了Sparse4D系列的后继版本还出现了和端到端规划结合的尝试。整个趋势已经很明显纯视觉的3D感知不再是不可想象的选项而稀疏化正在成为应对传感器算力瓶颈的一致选择。聊聊我个人的实践体会吧。复现Sparse4Dv3的过程中我最大的收获不是调通了模型而是理解了性能瓶颈到底在哪里这类问题。很多人在做自动驾驶感知时习惯把问题归结为数据不够多、模型不够大但Sparse4Dv3在参数量和计算量都比之前方案更小的前提下反而取得了更好的效果。这说明很多时候约束我们的是设计思路而不是硬件资源。有一个小技巧最后分享给想上手复现的读者最适合上手的入口是先跑通nuScenes上的标准训练流程但不要用默认参数一训到底。你可以刻意地减少训练数据到1/10做一个小规模实验这样整个训练周期能从几天压缩到几小时。在这个小实验里快速试各种超参数组合分析loss曲线和中间层特征的可视化结果。等你对模型的收敛行为有了直觉再回到全量数据上跑正式训练能省下非常多的时间。算法这条路说白了就是不断试错不断加深理解。希望这篇内容能帮你少踩几个坑在稀疏3D感知这条路上走得更快一些。