基于点云的3D目标检测与分类:从体素、点到Transformer的方法演进与工程落地 📅 发布时间:2026/9/19 16:13:45 👁 浏览次数: 1. 从原始点云到3D框自动驾驶感知的核心命题做自动驾驶感知这几年我最大的体会是摄像头能告诉你前面有个东西但只有激光雷达点云能告诉你那个东西离我到底几米、有多宽、朝向哪边。这个差别在高速跟车、窄路会车、夜间无路灯场景下直接决定刹车时机是提前0.3秒还是晚0.5秒。而基于点云的3D目标检测和分类就是把这一堆散乱的三维坐标点变成带类别标签、带朝向、带尺寸的三维边界框的完整过程。这篇文章我想系统梳理一下这个方向的主流方法脉络从点云的数据特性讲起到检测范式的演进再到分类方法、数据集、评估指标以及我自己在复现和调参过程中踩过的坑。适合刚进入自动驾驶感知方向的工程师、做点云相关课题的研究生以及想从2D检测转向3D检测的开发者。读完你应该能建立起一个完整的技术地图知道每种方法的适用边界在哪里而不是盲目追最新的论文。先说清楚一个前提这里的点云主要指LiDAR点云也就是激光雷达扫描得到的稀疏三维点集。它和深度相机转出来的点云、双目重建的点云在密度、噪声分布、扫描模式上都有本质差异方法选型时不能混为一谈。2. 点云数据特性与检测任务的核心难点2.1 点云到底长什么样一帧典型的64线机械旋转激光雷达点云大概有10万到12万个点。每个点至少包含三维坐标(x, y, z)通常还有反射强度intensity有些还有时间戳和ring index。听起来点很多但撒在几十米到上百米的空间里密度衰减非常快——近处1平方米可能有几百个点50米外可能只有几个点。这种非均匀稀疏性是点云检测的第一个大麻烦。图像是规整的2D网格每个像素都有值点云是散乱的三维集合没有天然的网格结构。你没法直接套用卷积神经网络因为卷积要求输入在局部是规则排列的。第二个特性是旋转不变性的缺失。同一辆车从不同角度看点云分布完全不同。车头对着雷达和车侧对着雷达点的分布模式差异巨大。而图像里同一辆车从不同角度看至少还有纹理和轮廓的连续性可以利用。第三个是遮挡与截断。激光雷达只能看到物体朝向自己的那一面一辆车你永远只能扫到它的前半面或者侧面背面是空的。这意味着基于完整形状的分类思路在点云上根本行不通。2.2 检测任务要输出什么3D目标检测的输出通常是一个7维向量中心点坐标(x, y, z)、尺寸(长l、宽w、高h)、偏航角θyaw。有些方法还会输出速度(vx, vy)用于跟踪或者俯仰角、翻滚角但绝大多数自动驾驶场景下车辆基本在平面上运动所以只预测yaw就够了。分类任务则是在检测框的基础上判断这个框里是什么轿车、卡车、行人、骑行者、交通锥……在KITTI数据集里通常分三类Car、Pedestrian、Cyclist在nuScenes里分得更细有23类。注意检测和分类在点云领域经常是耦合的。很多方法先做类别无关的候选框生成再对每个框做分类和回归精修。也有端到端直接输出带类别的框。理解这个区别对后面选方法很关键。2.3 为什么不能直接把图像的方法搬过来我见过不少刚入门的同学第一反应是把点云投影成鸟瞰图BEV或者前视图然后套YOLO或者Faster R-CNN。这个思路本身没错早期确实有人这么做但它有个致命问题投影会丢失信息。把点云压成BEV图每个像素格子里的高度信息被压缩了。你可以用最大高度、平均高度、高度方差等统计量来编码但一辆车和一根电线杆在BEV上可能占同样的面积高度统计量也接近区分度就下来了。前视图更糟前后遮挡完全无法表达。所以后来大家才转向直接在3D空间做检测或者用体素化保留三维结构。这个演进逻辑是理解整个领域的关键线索。3. 3D目标检测方法的主流范式拆解3.1 基于体素的方法把点云变成3D网格体素化的思路很直观把三维空间切成一个个小立方体比如0.05m×0.05m×0.1m每个立方体里的点用某种方式编码成一个特征向量。这样点云就变成了规则的3D张量可以套3D卷积了。VoxelNet是这个方向的開山之作。它用VFEVoxel Feature Encoding层把每个体素内的点聚合成一个特征然后用3D卷积提取空间特征最后接RPNRegion Proposal Network出检测框。思路清晰但3D卷积计算量巨大推理速度上不去。SECOND做了关键改进用稀疏卷积替代稠密3D卷积。因为点云体素化后99%以上的体素是空的稠密卷积在空体素上浪费了大量计算。稀疏卷积只对非空体素做运算速度提升非常明显。我实测下来SECOND在KITTI上能跑到40FPS基本满足实时性要求。PointPillars走得更远它干脆不做3D体素而是把空间切成一个个柱体pillar在高度方向不切分。每个柱体内的点用一个简化的PointNet提取特征然后压成2D的伪图像后面用2D卷积做检测。这个设计非常巧妙既保留了3D信息又把计算量降到了2D卷积的水平。工业界很多量产方案都用PointPillars或者它的变体因为速度和精度的平衡做得好。方法体素化方式核心卷积KITTI Car 3D AP推理速度VoxelNet3D体素3D稠密卷积约65%慢SECOND3D体素3D稀疏卷积约78%快PointPillars柱体2D卷积约75%很快实操心得体素大小是个关键参数。体素太大小目标行人、锥桶的特征被稀释召回率下降体素太小非空体素数量暴增显存吃不消。我一般从(0.1, 0.1, 0.2)开始试根据目标尺寸分布调整。检测行人为主就把体素调小检测卡车为主可以适当放大。3.2 基于点的方法直接在原始点上做文章体素化不可避免会引入量化误差而且手工设计体素编码方式也有信息损失。于是有人想能不能直接在原始点云上做检测PointNet和**PointNet**是点云深度学习的基石。PointNet用对称函数max pooling解决了点的无序性问题PointNet引入层次化特征提取能在不同尺度上聚合局部特征。但这两个主要是做分类和分割的直接做检测还需要额外的框回归头。PointRCNN是两阶段的点云检测方法。第一阶段用PointNet做前景点分割把属于目标的点挑出来每个前景点生成一个候选框第二阶段对这些候选框做精修和分类。这个思路很像图像里的Faster R-CNN但操作对象是原始点。精度很高但速度偏慢。3DSSD针对PointRCNN速度慢的问题做了优化去掉了上采样层和精修阶段用单阶段的方式做检测速度提升明显精度略有下降但可接受。基于点的方法最大的优势是保留了原始几何信息没有量化损失。但缺点是点云的无序性和稀疏性让卷积操作很难高效实现推理速度通常不如体素方法。3.3 点体素融合取长补短既然体素方法快、点方法准那能不能结合起来PV-RCNN就是干这个的。它先用体素卷积提取特征生成候选框然后把候选框内的原始点采样出来用PointNet做精细的特征提取和框精修。体素分支负责高效召回点分支负责精确回归两者互补。SA-SSD是另一个思路它在体素网络的基础上加了一个辅助任务预测每个体素点到目标中心的偏移量。这个辅助任务让网络学到更结构化的特征检测精度提升明显而且推理时辅助分支可以砍掉不增加部署成本。这类融合方法在KITTI榜单上长期霸榜但工程复杂度也高调参难度大。如果你是做产品落地我建议先从PointPillars这种简单可靠的方案入手有精度需求再考虑融合方案。3.4 基于Transformer的方法新范式的冲击2020年之后Transformer开始渗透到点云检测领域。DETR3D把2D检测里的DETR范式搬到3D用一组可学习的query通过注意力机制从多视角特征里采样直接输出3D框。PETR系列进一步引入了位置编码的3D感知设计让query能感知三维空间位置。这类方法的优势是端到端、无需NMS后处理流程简洁。但训练收敛慢对数据量要求高而且注意力机制的计算复杂度随点云规模增长快。目前在nuScenes等大规模数据集上表现不错但在实际车端部署还有距离。我个人的判断是Transformer方法代表了方向但短期内体素和点方法仍然是工程落地的主力。做研究可以追新范式做产品要优先考虑成熟度和可维护性。4. 点云分类方法的关键技术点4.1 分类和检测的关系点云分类在自动驾驶里通常不是独立任务而是检测流程的一部分。检测框出来后需要对框内的点云片段做类别判断。但也有一些场景是纯分类任务比如路侧感知单元对经过的车辆做车型分类或者对点云场景做语义分割每个点属于什么类别。从技术上讲分类比检测简单因为不需要回归位置和尺寸。但点云分类有它自己的难点类内差异大、类间差异小。同样是轿车三厢和两厢的点云分布不同轿车和SUV的点云轮廓又很接近。再加上遮挡和稀疏分类器很容易混淆。4.2 基于多视图的分类早期方法如MVCNN把3D物体从多个角度投影成2D图像用CNN提取特征后融合。这个思路在ModelNet40等CAD模型数据集上效果好但用在真实LiDAR点云上问题很大真实点云只有单视角你没法从背面投影因为背面根本没有点。所以多视图方法在自动驾驶场景下基本被淘汰了除非你有多帧累积的点云能拼出相对完整的物体形状。4.3 基于体素的分类VoxNet是最早的体素分类网络之一把物体体素化成32×32×32的网格用3D卷积分类。简单直接但分辨率受限细粒度分类效果一般。3D ShapeNets用深度信念网络做体素分类更早现在基本只作为历史参考。体素分类的问题是分辨率越高计算量指数增长分辨率低了细节丢失。在自动驾驶场景下远处目标的点云本来就稀疏体素化后几乎没什么信息了。4.4 基于点的分类PointNet在分类任务上的表现是里程碑式的。它直接吃原始点云用共享MLP提取逐点特征再用max pooling聚合全局特征最后接全连接分类。在ModelNet40上达到89%的准确率而且对点的排列顺序不变对刚体变换也有一定鲁棒性。**PointNet**通过层次化采样和分组能捕捉局部结构分类精度进一步提升到91%以上。DGCNN引入EdgeConv动态构建局部图在分类和分割上都表现优秀。在自动驾驶点云分类中我通常用PointNet的简化版做框内点云分类。输入是检测框内的点通常采样到512或1024个点输出是类别概率。实测下来对Car、Pedestrian、Cyclist三分类准确率能到95%以上但加上Truck、Bus、Motorcycle等细分类别后准确率会掉到85%左右主要混淆发生在Car和Van、Truck和Bus之间。实操心得做点云分类时点的采样策略很关键。FPS最远点采样比随机采样更能保留形状信息但计算慢。实际部署时我常用随机采样加体素下采样的组合先体素下采样去掉冗余再随机采样固定点数速度和效果的平衡比较好。4.5 分类中的特征增强技巧单纯用坐标做分类信息量有限。我一般会加几类额外特征反射强度不同材质的反射率不同金属车身反射强行人衣物反射弱这个特征对分类很有帮助。点密度单位体积内的点数反映物体的表面材质和距离。高度统计最大高度、高度方差、高度直方图对区分轿车和SUV、行人和骑行者很有效。法向量局部表面的朝向对区分平面车门和曲面车顶有用。这些特征拼接起来分类准确率通常能提升3到5个百分点。但要注意特征归一化不同量纲的特征直接拼接会让网络偏向数值大的特征。5. 数据集、评估指标与实操流程5.1 主流数据集怎么选KITTI是点云检测最经典的数据集7481帧训练、7518帧测试标注了三类目标。它的点云是64线雷达采集的场景主要是城市道路和高速公路。优点是标注质量高、社区活跃、榜单透明缺点是规模小、类别少、场景单一。做算法验证和论文对比KITTI是标配。nuScenes是更大规模的数据集1000个场景每场景20秒32线雷达标注23类目标还有360度环视图像。它的评估指标更严格用了mAP和NDSnuScenes Detection Score对速度误差、朝向误差、属性误差都有惩罚。做量产相关的研究nuScenes更有参考价值。Waymo Open Dataset规模更大1150个场景64线雷达标注质量极高。但获取需要申请而且计算资源要求高。Argoverse和Lyft L5也是可选的数据集各有侧重。Argoverse有高精地图和运动预测标注Lyft L5的场景多样性好。数据集帧数/场景数雷达线数类别数特点KITTI14999帧64线3类经典、规模小nuScenes1000场景32线23类大规模、多模态Waymo1150场景64线4类高质量、需申请Argoverse113场景32线15类含地图和预测注意不同数据集的坐标系定义、标注格式、评估协议都不一样。跨数据集训练时一定要做坐标对齐和类别映射否则结果没法比。我见过有人直接把KITTI训练的模型放到nuScenes上测mAP掉了一半很大一部分原因就是坐标系和类别定义没对齐。5.2 评估指标到底怎么看3D检测的核心指标是3D APAverage Precision计算方式和2D检测类似但IoU是在3D空间算的。KITTI的评估协议里Car类的IoU阈值是0.7Pedestrian和Cyclist是0.5。这个阈值设定是有讲究的车辆形状规整0.7的IoU能保证框的贴合度行人和骑行者形状不规则0.5更合理。KITTI还分了三个难度等级Easy、Moderate、Hard根据目标的高度、遮挡程度、截断程度划分。看论文结果时Moderate的3D AP是最常被引用的指标因为它最接近实际场景的难度分布。nuScenes的指标更复杂mAP是各类别AP的平均但匹配时用的是中心点距离而不是IoU因为不同类别的尺寸差异大IoU不公平。NDS是mAP、mATE平移误差、mASE尺度误差、mAOE朝向误差、mAVE速度误差、mAAE属性误差的加权组合。这个指标体系更全面但也更难优化。5.3 从数据到部署的完整流程我以KITTI数据集、PointPillars方法为例走一遍完整流程第一步数据准备。下载KITTI 3D Object Detection数据集解压后得到velodyne点云、label标注、calib标定文件、image图像。用官方提供的工具把标注转成训练需要的格式中心点、尺寸、朝向。第二步点云预处理。把点云限制在检测范围内比如x方向[0, 70.4]米y方向[-40, 40]米z方向[-3, 1]米超出范围的点裁掉。然后做数据增强随机旋转、随机平移、随机翻转、全局缩放。KITTI数据量小增强是必须的否则很容易过拟合。第三步体素化/柱体化。PointPillars把点云切成柱体每个柱体最多保留一定数量的点比如32个用PointNet提取特征得到(C, H, W)的伪图像。第四步网络搭建。主干网络用2D CNN比如ResNet-18的变体提取特征然后接检测头分别预测类别、框回归、朝向分类。朝向通常用两个bin的分类加残差回归避免角度回归的周期性问题。第五步损失函数。分类用Focal Loss解决正负样本不平衡回归用Smooth L1 Loss朝向用bin分类的交叉熵加残差回归的Smooth L1。第六步训练与调参。Adam优化器初始学习率1e-3余弦退火训练80到100个epoch。Batch size根据显存调整一般8到16。关键调参点正负样本匹配的IoU阈值、Focal Loss的alpha和gamma、数据增强的强度。第七步推理与后处理。网络输出大量候选框先按类别置信度过滤再做NMS非极大值抑制最后输出最终的3D框。NMS的IoU阈值一般设0.1到0.3因为3D框在BEV上的重叠比2D框更常见。第八步评估与可视化。用官方评估工具算3D AP和BEV AP用Open3D或CloudCompare可视化检测结果检查漏检和误检的模式。# PointPillars柱体化核心逻辑示意 def points_to_pillars(points, point_cloud_range, voxel_size): # points: (N, 4) [x, y, z, intensity] # 计算每个点所属的柱体索引 pillar_x ((points[:, 0] - point_cloud_range[0]) / voxel_size[0]).astype(np.int32) pillar_y ((points[:, 1] - point_cloud_range[1]) / voxel_size[1]).astype(np.int32) # 过滤超出范围的点 mask (pillar_x 0) (pillar_x grid_size[0]) \ (pillar_y 0) (pillar_y grid_size[1]) # 每个柱体最多保留max_points个点 # 用PointNet提取柱体特征 # 散射回2D伪图像 return pseudo_image实操心得训练PointPillars时数据增强的强度对最终精度影响很大。我试过只用随机翻转和轻微旋转Moderate 3D AP只有72%左右加上全局缩放、随机平移、GT采样增强后能到76%以上。但增强太猛也会导致训练不稳定建议逐步增加增强强度观察验证集指标变化。6. 常见问题与排查技巧实录6.1 训练不收敛怎么办这是最常见的问题。点云检测网络的损失函数通常由分类损失和回归损失组成两者量级差异大容易导致某一项主导梯度。排查顺序先看分类损失是否下降。如果分类损失不降检查正负样本匹配逻辑可能是正样本太少或者匹配阈值设得太高。再看回归损失如果回归损失震荡检查学习率是否太大或者框的编码方式是否有问题。我遇到过一次训练了20个epoch分类损失正常下降但回归损失一直在0.5左右震荡。后来发现是朝向角的编码有问题我用的是直接回归角度值但角度有周期性网络在0和2π附近来回跳。改成bin分类加残差回归后问题解决。6.2 验证集精度远低于训练集典型的过拟合。KITTI只有7481帧训练数据如果不做数据增强过拟合几乎是必然的。解决手段加强数据增强特别是GT采样增强从其他帧复制目标粘贴到当前帧、加Dropout、加权重衰减、减小模型容量。我一般还会用早停策略验证集连续10个epoch不提升就停。还有一个容易被忽略的点数据泄露。KITTI的训练集和验证集如果按连续帧划分相邻帧的点云几乎一样验证集精度会虚高。正确做法是按场景划分确保验证集的场景在训练集中没出现过。6.3 小目标检测效果差行人、锥桶这类小目标点云本来就少体素化后更容易被淹没。我试过几种改进降低体素尺寸但显存吃不消。在损失函数里给小目标更高的权重。用多尺度特征融合在浅层特征图上做小目标检测。用点分支补充体素分支PV-RCNN就是这个思路。实测下来多尺度特征融合性价比最高改动小提升明显。在PointPillars的FPN结构里把浅层特征图也接入检测头行人的AP能提升5个点左右。6.4 推理速度不达标车端部署通常要求10FPS以上也就是每帧100毫秒以内。如果模型推理慢先看瓶颈在哪是体素化耗时还是网络前向耗时还是NMS耗时。体素化用CUDA实现通常很快几毫秒搞定。网络前向是大头可以换更轻的主干网络比如用MobileNet替换ResNet或者做通道剪枝。NMS在候选框多的时候也耗时可以用CUDA版的NMS或者减少候选框数量。我做过一次优化把PointPillars的主干从ResNet-18换成自定义的轻量网络通道数减半推理速度从25FPS提升到45FPS精度只掉了1.5个点。这个 trade-off 在量产场景下完全可以接受。6.5 常见问题速查表问题现象可能原因排查方向解决手段分类损失不降正负样本失衡统计正负样本比例调Focal Loss参数、调匹配阈值回归损失震荡学习率过大/角度编码问题检查学习率曲线、角度分布降学习率、改bin分类验证精度低过拟合/数据泄露对比训练验证曲线、检查划分加增强、按场景划分小目标漏检体素化信息丢失可视化小目标点云多尺度融合、调损失权重推理慢主干网络重/NMS慢分模块计时换轻量主干、CUDA NMS朝向预测不准角度周期性可视化朝向误差分布bin分类残差回归6.6 几个容易踩的坑坑一坐标系搞混。KITTI的雷达坐标系是x向前、y向左、z向上但有些代码库用的是x向前、y向右、z向上。坐标系搞反了训练出来的框全是镜像的。我建议在数据加载后先可视化几帧确认坐标系方向。坑二标注格式转换错误。KITTI的标注是(l, w, h, x, y, z, yaw)但有些代码库期望的是(w, l, h, ...)或者(h, w, l, ...)。顺序搞错框的尺寸就全乱了。转换后一定要用官方工具验证一遍。坑三忽略类别不平衡。KITTI里Car占绝大多数Pedestrian和Cyclist很少。如果不做类别平衡网络会倾向于把所有东西都预测成Car。我通常用类别加权的损失函数或者对稀有类别做过采样。坑四NMS阈值设太大。3D框在BEV上的重叠比2D框严重NMS阈值设0.5的话相邻的两辆车可能被合并成一个。我一般设0.1到0.2具体根据场景调整。坑五忘了做点云范围裁剪。KITTI的点云范围很大但标注只在特定范围内。如果不裁剪网络会学到很多无用的背景点浪费计算资源还影响精度。7. 方法选型与工程落地的个人建议做了几个量产项目后我对方法选型有一些比较务实的看法。如果你刚入门想快速跑通一个baselinePointPillars是最佳起点代码成熟、社区活跃、速度精度平衡好、部署友好。跑通之后再根据需求往两个方向走要精度就上PV-RCNN或SA-SSD要速度就做轻量化。如果是做研究发论文那肯定要追最新的范式Transformer-based的方法、多模态融合、自监督预训练都是热点。但要注意论文里的SOTA和实际能落地的方案之间往往有巨大鸿沟。我见过太多论文方法在KITTI上刷到80%的AP但推理速度只有2FPS根本没法上车。数据方面我的建议是KITTI用来验证算法正确性nuScenes用来验证泛化能力自有数据用来验证落地可行性。三个层次缺一不可。很多问题只有在自有数据上才会暴露比如特定车型的点云分布、特定场景的遮挡模式、传感器的标定误差。最后说一个我踩过的大坑不要忽视标定。LiDAR和IMU的标定、LiDAR和相机的标定如果外参有偏差点云和图像对不齐多模态融合就是灾难。我遇到过一次LiDAR-IMU外参的旋转矩阵差了0.5度导致点云在地图里整体倾斜检测框的位置系统性偏移。标定这件事宁可多花时间做精确也不要凑合。点云3D检测这个方向方法迭代很快但核心的工程问题——数据质量、标定精度、部署效率——这些年其实没怎么变。把基础打牢追新方法才有意义。