赞
踩
已知:
N个点,每个点的信息x,y,z。
MLP: MLP(Multi-Layer Perceptron),即多层感知器,是一种趋向结构的人工神经网络,映射一组输入向量到一组输出向量。
简单的可以用全连接网络实现,复杂的可以用卷积网络实现。
对每个点进行MLP操作,即:3~> MLP(3,C1) ~>C1其中3、C1是MLP的输入和输出维度,此时这个点的特征数由原来的3变成了C1 。
将点云的每个点都经过以上操作,得到:N * 3~>MLP(3 * N,C1) ~>N * C1
小结:没个点的特征由3变成了64,又称超维特征、冗余特征。
将MLP得到的结果进行max pool操作,max pool的目的是为了:pointNet网络改变点的输入顺序不会影响最终输出的结果。
MLP得到的结果可以看作是N * C1的矩阵,max pool操作是对N * C1矩阵的C1列进行max操作,得到1 * C1的矩阵。即N * C1~>1 * C1 。
小结:max pool 是pointNet的算法核心。mean或min也能做到但max更好。
将max pool的结果经过一个分类器,得到最后的分类结果,pointnet网络的作用是点云的分类。分类器一般用MLP网络来实现。
(1)PointNet考虑到了全局性特征的方向拼接处理,但是忽视了点云局部特征的捕获。
(2)PointNet本身已经具备对点云的全局特征提取能力。
分割:将每个点进行分类,就可以做分割操作!!
网络结构:全局特征+每点自身的高纬度特征 ~> 分类器
从PointNet到PointNet++理论及pytorch代码
PointNet++详解与代码
基于PyTorch实现PointNet++
参考文献
【1】https://blog.csdn.net/cg129054036/article/details/105545895
每一组set abstraction layers主要包括3个部分:
def farthest_point_sample(xyz, npoint):
"""
Input:
xyz: pointcloud data, [B, N, C]
npoint: number of samples
Return:
centroids: sampled pointcloud data, [B, npoint, C]
"""
在源点集,人工设定半径r,以每个采样点为球心画球,目的是分组。为了方便batch操作,每一个局部区域内的点的数量是一致的,都为K,如果某个圆内的点的数量小于K, 则可以重复采样圆内的点,达到数量K;如果某个区域内的点的数量大于K, 则随机选择K个点,即可。group操作得到的结果如下图所示,可以形成很多小的局部区域。
输入输出shape:tensor[B, N, 3] ~> tensor[B, npoint, nsample, 3] ,或者 tensor[B, N, D] ~> tensor[B, npoint, nsample, 3+D]
def sample_and_group(npoint, radius, nsample, xyz, points, returnfps=False):
"""
Input:
npoint:
radius:
nsample:
xyz: input points position data, [B, N, 3]
points: input points data, [B, N, D]
Return:
new_xyz: sampled points position data, [B, npoint, nsample, 3]
new_points: sampled points data, [B, npoint, nsample, 3+D]
"""
源点云tensor(B, N, C0) ~> sapling andgrouping ~> tensor(B, M, K, C1) ~> 每个group区域通过PointNet进行特征提取 ~> tensor(B, M, C1)
上面就是一次set abstraction操作了,PointNet++是有3次set abstraction操作的:
注意: 这里有一个细节问题, 可以看到C1和C2后面都加了3, 这是在学到特征的基础上又加了位置信息(x, y, z), 重新作为新的特征来送入PointNet网络。
在提取了点云的特征(C3,)之后, 接下来就和图像里的分类任务一样了,C3维的特征作为输入,然后通过通过两个全连接层和一个分类层(分类层的是输出节点等于类别数的全连接层),输出每一类的概率。损失函数采用的是交叉熵损失函数,对应PyTorch中的nn.CrossEntropy() 。
分割任务需要对点云中的每个点进行分类,而PointNet++中的set abstraction由于sampling操作减少了输入点云中的点的数量,如何进行上采样使点云数量恢复输入时的点云数量呢?
在图像分割任务中,为了恢复图像的分辨率, 往往采用反卷积或者插值的方式来操作呢, 在点云中该如何恢复点云的数量呢?
其实,在PointNet++中的set abstraction模块里,当前点云Q和下采样后的点云Q’的中的点位置信息一直是保存的,点云的上采样就是利用了这一特性。这里利用二维图直观的解释一下,下方左图中红色的倒三角形表示下采样后的点云Q’, 蓝色的点云表示下采样之前的点云Q, 点云里的上采样就是用PointNet学习后的点云Q’的特征表示下采样之前点云Q的特征。采用的方式是k近邻算法,论文中k=3。如图所示,对于Q中的每一个点O,在Q’中寻找其最近的k个点,基于距离加权(距离O近,其权重大; 距离O远, 其权重大)求和这k个点的特征来表示点O的特征,具体计算方式为:
上采样得到了C’维的特征, 而且点的数量已经恢复到了下采样之前的数量; 将C’维的特征与set abstraction中相同点数量的点云(对称位置)特征(C维)进行进行concat操作,进而进行多个 Conv1d + Bn + ReLU操作,来得到新的特征。
经过三次上采样操作后,点云恢复了初始输入点云中点的数量, 再经过一次conv1d + bn + relu层 和一个对点的分类层,最终得到对每个点的分类。如下图:
上述文章主要介绍了PointNet++的SSG(single scale grouping), 为了解决点云中密度分布不均匀的问题,作者提出了MSG(multi-scale grouping)和MRG(multi resolution grouping). 下面这张图是作者论文里的图(在ModelNet40数据集上的实验), 测试了PointNet, SSG, MSG, MRG的性能,横坐标表示的是在预测时点云中点的数量,纵坐标表示的是准确率。从图中可以看到, 在点的数量较多时,SSG, MRG, MSG性能相近,明显高于PointNet; 但随着点云中的点的数量下降,准确率明显下滑的有两条线,有轻微下降趋势的有四条线。明显下滑的两条线是没有采取DP策略的。 即使是PointNet网络在采取了DP策略后,其性能在点的数量小于600也会明显高于SSG.。由此可见,DP在解决点云密度不均匀时发挥了重要作用, 而MSG, MRG貌似显得没那么重要 ? 这里就简单介绍一下MSG的思想。
点云分布不一致时,每个子区域中如果在生成的时候使用相同的半径r,会导致有些区域采样点过少。
作者提到这个问题需要解决,并且提出了两个方法:Multi-scale grouping (MSG) and Multi-resolution grouping (MRG)。下面是论文当中的示意图。MSG、MRG详细讲解请参考https://blog.csdn.net/cg129054036/article/details/105545895
MSG、MRG详细讲解请参考https://blog.csdn.net/cg129054036/article/details/105545895
MSG是指在每次Set Abstraction的时候, 在对某个中心点centroid进行group操作的时候采用不同尺寸(例如0.1, 0.2, 0.4, SSG只有0.2)的半径, 来得到不同大小的局部区域,分别送到不同的PointNet网络中,最终把这些学习到的不同尺度的特征进行concat操作来代表当前中心点centroid的操作。
点云不同于图像,图像中有随机裁剪、缩放、颜色抖动等数据增强方式。在点云里,应该如何做数据增强呢?
点云的数据增强主要包括: 随机旋转,随机平移,随机抖动等, 具体实现代码参考: https://github.com/zhulf0804/Pointnet2.PyTorch/blob/master/data/provider.py
参考
DP指的是在训练时随机丢弃一些输入点(DP means random input dropout during training),这样的训练方式对于预测低密度点云较为有效(相对于输入点云), 即在高密度点云中训练的模型,在低密度点云中进行预测,可以达到和训练集中旗鼓相当的效果。具体来说,人工设置超参数p(论文中p=0.95), 从[0, p]中随机出一个值dr(drouout ratio), 对于点云中的每一个点,随机产生一个0-1的值, 如果该值小于等于dr则表示该点被丢弃。这里有一个细节,某些点被丢弃之后,每个batch中的点的数量就不相同了,为了解决这个问题,所有被丢掉的点使用第一个点代替,这样就维持了每个batch中点的数量相同。
参考
Input data
tensor(B, N, 6)
->
Set Abstraction.sample
input tensor(B, N, 6)
output tensor(B, 512, 3)
->
Set Abstraction.group
input tensor(B, 512, 3)
output tensor(B, 512, 32, 6)
->
Set Abstraction.PointNet
input tensor(B, 512, 32, 6)
output tensor(B, 512, 32, 128)
->
max Pooling
input tensor(B, 512, 32, 128)
output tensor(B, 512, 128)
->
Set Abstraction.sample
input tensor(B, 512, 128)
output tensor(B, 128, 3)
->
Set Abstraction.group
input tensor(B, 128, 3)
output tensor(B, 128, 64, 128 + 3)
->
PointNet(B, 128, 64, 256)
input tensor(B, 128, 64, 128 + 3)
output tensor(B, 128, 64, 256)
->
max Pooling
input tensor(B, 128, 64, 256)
output tensor(B, 128, 256)
->
Set Abstraction.sample
input tensor(B, 128, 256)
output tensor(B, 1, 3)
->
Set Abstraction.group
input tensor(B, 1, 3)
output tensor(B, 1, 128, 256 + 3)
->
Set Abstraction.PointNet
input tensor(B, 1, 128, 256 + 3)
output tensor(B, 1, 128, 1024)
->
max Pooling
input tensor(B, 1, 128, 1024)
output tensor(B, 1, 1024)
->
Features(B, 1, 1024)
Features(B, 1024) -> FC(B, 512) -> FC(B, 256) -> Output(B, n_clsclasses)
Features(B, 1, 1024) 全局特征
->
FP.unsapmling 上采样
input tensor(B, 1, 1024)
output tensor(B, 128, 1024)
->
FP.concat 特征拼接
input tensor(B, 128, 1024)
output tensor(B, 128, 1024+256) 全局特征+每个点的超维特征
->
FP.PointNet
input tensor(B, 128, 1024+256)
output tensor(B, 128, 256)
->
FP.unsampling
input tensor(B, 128, 256)
output tensor(B, 512, 256)
->
FP.concat
input tensor(B, 512, 256)
output tensor(B, 512, 256+128)
->
FP.PointNet
input tensor(B, 512, 256+128)
output tensor(B, 512, 128)
->
FP.unsampling
input tensor(B, 512, 128)
output tensor(B, N, 128)
->
FP.concat
input tensor(B, N, 128)
output tensor(B, N, 128+6)
->
FP.PointNet
input tensor(B, N, 128+6)
output tensor(B, N, 128)
->
Conv1d(B, N, 128)
->
Conv1d(B, N, n_segclasses)
我们的分层结构是由一系列点集抽象层(Set Abstraction Levels)组成,参考 Fig2。在每一个层次,一组点被处理和抽象,并产生一组新的点集(具有更少的点)。点集抽象层包含三个关键层:Sampling Layer,Grouping Layer and PointNet Layer. Sampling Layer 从输入点集中采样一部分点,这些点就是局部邻域的中心。Grouping Layer 根据邻域中心,选择局部的邻域点集。 PointNet Layer 使用一个迷你的网络(Mini-PointNet)编码局部邻域的特征。
如 Fig1 中的扫描点云一样,不同的区域密度也是不一样的(近处稠密,远处稀疏),这是个很常见的现象。
斯坦福大学在读博士生祁芮中台:点云上的深度学习及其在三维场景理解中的应用_哔哩哔哩_bilibili
【1】深蓝学院
【2】https://blog.csdn.net/weixin_43321489/article/details/127778251
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。