4. 目标检测与特征提取:基于PointPillars的3D目标检测、目标状态向量定义

好,咱们进入正题。这一章聊的是目标检测和特征提取,说白了就是怎么从一堆点云里把车、行人、骑行者这些目标给“揪”出来,并且给它们贴上标签。

我个人习惯把这一步叫做“从无序到有序”。点云本身是杂乱无章的,但我们要把它变成结构化的目标信息。这里最经典的方法之一,就是PointPillars。

4.1 为什么是PointPillars?

你可能会问,点云检测方法那么多,VoxelNet、SECOND、PointRCNN……为什么我偏偏要讲PointPillars?

原因很简单:快,而且准。

我在项目中遇到过这样的场景:车上的计算平台算力有限,但要求检测延迟必须控制在50毫秒以内。VoxelNet虽然精度不错,但3D体素化后计算量太大,跑起来有点吃力。PointPillars呢?它把3D空间压缩成了2D的“柱子”(Pillar),然后用2D卷积来处理。你想想看,这计算量一下子就降下来了。

嗯,这里要注意:PointPillars并不是简单地丢弃了高度信息。它把每个柱子内的点云特征(比如高度、反射强度)都保留了下来,作为额外的通道输入到网络中。所以它既保留了3D信息,又享受了2D卷积的高效。

核心思想:将点云划分为垂直的柱子(Pillars),在每个柱子内提取点云特征,然后投影到2D平面,用2D卷积神经网络进行检测。

4.2 PointPillars 的工作流程

咱们一步步拆解。整个过程可以分为三个大阶段:

  1. 点云到Pillar的转换
  2. 特征提取与伪图像生成
  3. 2D卷积检测头

下面这张图可以帮你快速建立整体认知:

PointPillars 3D目标检测流程 原始点云 (x, y, z, intensity) N个点,无序 Pillar特征提取 划分网格 → 堆叠Pillar PointNet提取特征 伪图像生成 (H, W, C) 特征图 类似图像格式 2D卷积检测头 SSD-like 检测框架 分类 + 回归 3D检测框 + 类别

4.3 具体实现细节

4.3.1 点云到Pillar的转换

首先,我们把点云所在的3D空间,在x-y平面上划分成一个个均匀的网格。每个网格就是一个Pillar。比如,网格大小可以设为0.16m x 0.16m。

然后,对于每个Pillar,我们只保留它里面的点。如果一个Pillar里的点太多(比如超过100个),就随机采样一部分。如果太少,就用0填充。

这里有个坑:每个Pillar里的点数量可能差异很大。我曾经遇到过这种情况:路面上空旷的地方,一个Pillar里可能只有两三个点;但到了密集的灌木丛或者车旁边,一个Pillar里可能挤了几百个点。如果不做采样或填充,网络训练会非常不稳定。

我的经验:每个Pillar最多保留100个点,少于5个点的Pillar直接丢弃。这样既能保证特征丰富度,又能控制计算量。

4.3.2 特征提取

对于每个Pillar里的点,我们不仅要保留它原始的(x, y, z, intensity)信息,还要加上一些相对位置信息。比如:

  • 该点相对于Pillar中心的偏移量 (x_c, y_c, z_c)
  • 该点相对于整个点云中心的偏移量 (x_p, y_p, z_p)

这样一来,每个点就变成了一个9维的向量。然后,我们用一个小型的PointNet网络来提取每个Pillar的特征。PointNet的输出是一个固定长度的特征向量,代表了这个Pillar的整体信息。

说白了,这一步就是把每个Pillar里的点云“压缩”成一个特征向量。

4.3.3 伪图像生成

所有Pillar的特征向量组合起来,就形成了一个伪图像。这个伪图像的高度和宽度就是x-y方向上的网格数量,通道数就是特征向量的维度。

举个例子:假设x方向有400个网格,y方向有400个网格,特征向量维度是64。那么伪图像的尺寸就是 (400, 400, 64)。

你看,这不就跟一张普通的RGB图像很像了吗?只不过通道数从3变成了64。接下来,我们就可以用2D卷积神经网络来处理它了。

4.4 目标状态向量定义

检测出目标之后,我们需要用一个向量来描述它的状态。这个向量就是目标状态向量。它包含了我们关心的所有信息。

我一般把状态向量定义为7维:

维度 符号 含义 说明
1 x 目标中心x坐标 通常在世界坐标系下
2 y 目标中心y坐标 同上
3 z 目标中心z坐标 地面高度
4 l 目标长度 车辆:4-5m;行人:0.5-1m
5 w 目标宽度 车辆:1.8-2m;行人:0.5-0.8m
6 h 目标高度 车辆:1.5-2m;行人:1.5-1.8m
7 θ 目标朝向角 范围:[-π, π]

如果要做跟踪,我们还需要加上速度信息。这时候状态向量就变成了9维:

维度 符号 含义 说明
8 vx x方向速度 单位:m/s
9 vy y方向速度 单位:m/s

注意:朝向角θ的定义非常关键。我见过不少新手把朝向角和偏航角搞混。在自动驾驶中,我们通常用朝向角来表示车头指向的方向,范围是[-π, π]。而且,朝向角是周期性的,π和-π其实是同一个方向。这在做回归损失计算时是个麻烦事,需要特殊处理。

4.5 损失函数与训练

PointPillars的损失函数和SSD类似,包含分类损失和回归损失两部分。

分类损失用Focal Loss,用来解决正负样本不平衡的问题。回归损失用Smooth L1 Loss,用来回归位置、尺寸和朝向。

这里有个细节:朝向角的回归。我们不能直接回归θ的绝对值,因为θ有周期性。常用的做法是回归sin(θ)和cos(θ),或者回归相对于某个anchor的偏移量。

我个人习惯用后者。具体来说,对于每个anchor box,我们回归它相对于ground truth的偏移量:

Δx = (x_gt - x_a) / d_a
Δy = (y_gt - y_a) / d_a
Δz = (z_gt - z_a) / h_a
Δl = log(l_gt / l_a)
Δw = log(w_gt / w_a)
Δh = log(h_gt / h_a)
Δθ = sin(θ_gt - θ_a)

其中,d_a = sqrt(l_a^2 + w_a^2)

这样处理之后,回归目标就变得平滑了,网络也更容易收敛。

4.6 避坑指南

最后,分享几个我在实际项目中踩过的坑:

  • 点云范围的选择:不要贪大。我曾经把检测范围设到100米,结果远处的点太稀疏,检测效果很差,还拖慢了速度。后来我改成前向70米,侧向40米,效果好了很多。
  • Pillar大小的选择:太小了计算量大,太大了检测精度下降。0.16m是一个比较常用的值,但如果你主要检测行人,可以适当缩小到0.1m。
  • 数据增强:点云的数据增强很重要。我常用的方法包括:全局旋转、全局缩放、随机丢弃点、以及GT采样(把其他场景中的目标复制到当前场景中)。

总结一下:PointPillars的核心思想是把3D点云转换成2D伪图像,然后用2D卷积来做检测。目标状态向量定义了我们要跟踪的对象的属性,包括位置、尺寸、朝向和速度。这两者结合起来,就构成了目标跟踪的基础。

可可精品资料库