PointNet以及PointNet++学习笔记
PointNet以及PointNet++学习笔记
0 动机
3D点云数据是一个的数组,是点的个数,6是表示一个点的纬度,即一个3D点表示为,分别是三维坐标和法向量。
点云数据具有无序性。无序性是指,现有一组表示一只狗的点云数据,将该数据输入系统不需要按照固定顺序输入。也就是说,先输入表示头的点和先输入表示尾巴的点,最后的结果都是一样的。
点云是非结构化的数据,直接CNN很难处理。
PointNet的任务就是解决如何对点云数据进行特征提取的问题。
1 PointNet
1.1 处理无序性的基本思想
点云数据的无序性本身没有办法改变,那么就需要模型自身不管点云的顺序如何变化都会始终输出相同的结果。也就是模型需要具有置换不变性。
思考这样一个问题,有一个函数,这个函数应该怎样设置,才可以使得变量x的顺序任意变化都不会改变函数的值?
简单的设计有:
f(x_1,x_2,...,x_n)&=&max\{x_1,x_2,...,x_n\}\\ f(x_1,x_2,...,x_n)&=&x_1+x_2+...+x_n)
但是如果直接使用Max函数的话,的点云只能得到的特征,这显然损失了大量信息和特征。
那么应该怎么改进呢?
可以先对点云数据进行升维操作,再进行Max。也就是将的点云升维至,然后Max得到的特征。
怎么在神经网络中升维呢?使用多层感知机MLP。
1.2 PointNet的基本框架
分类网络区域就是1.1节图像的具体版。
语义分割网络区域的一点区别就是,将全局特征与初始升维的点云特征进行拼接,然后对每个点进行mlp处理,即对每个点进行分类。
1.3 PointNet的问题
没有局部特征的融合。局部样本点之间应该是存在某些联系,但是PointNet,并没有考虑这点。
2 PointNet++
PointNet++的目的就是将局部特征融合进行模型中。
具体分为两步,第一步是怎么选取局部区域,第二步是怎么对局部区域进行卷积操作提取特征。
2.1 分组(grouping)
第一步,选取局部区域。
怎么确定一个局部区域?假设局部区域是一个圆,那么需要知道这个圆的圆心位置,以及圆的半径。
圆心位置怎么确定?
基于一个朴素的思想,那就是用尽可能少的圆来覆盖所有点。于是使用最远点采样选取圆心。
最远点采样的步骤:
- 随机采样第一个点
- 计算距离该点最远的点
- 计算剩余点到采样点的距离,是采样点的索引,是剩余点的索引。选择对应的索引的点作为下一个采样点。重复该步骤。
在PointNet++中,只有圆心位置是计算得到的,圆心个数和半径都是预设好的。实际计算中选择多种半径和采样点个数,会使特征更加丰富。
在PointNet++中,这个划分局部区域的操作叫做分组(grouping)。
用数据举个例子:
- PointNet++输入了1024个点,每个点有6个元素:
- 分组(grouping)后输出:(128个圆心,每个圆包含16个点)
可以发现128X16明显比1024大。这是因为在分组过程中,有的圆包含的点少于16个,有的圆多余16个。
分组操作强制要求每个圆必须包含16个点。于是不足16个点的圆会复制距离圆心最近的点,直到个数达到16.而多余16个的圆,会根据点到圆心的距离进行排序,选取距离最小的16个点。
至此,圆的圆心、半径、位置、包含点都已经解释清楚。而这些圆就是组,不同半径、个数表示不同尺度的组。
2.2 对组进行特征提取
按照之前的例子,组的数据结构可以写作。这和正常用于卷积的图像貌似没什么区别。
于是使用卷积对组进行特征提取:
- 进行维度变换,卷积中第二位是channel,而PointNet++将点的坐标特征当作channel。于是将组变为了
- 进行卷积,(例如:in=6,out=64),则提取出的特征就是。这与MLP的升维操作类似
- 对于每个组,只需要一个特征,于是使用PointNet的max操作处理16个点,使得特征变为
后续还有多次卷积的操作,待了解
2.3 PointNet++框架
2.4 PointNet++的问题
作者发现随着初始采样点的个数减小,PointNet++的性能会直线下降。
这是因为样本点个数减小,会导致特征个数的减少。既然特征个数减少了,那就增加特征的长度。于是将不同半径的结果拼在一起。