代码地址:mind3d: mindspore 3D toolkit developed by 3D Lab of Southeast University
目录
KPS(K-Closest Points Sampling)
背景
点云目标检测
在3D点云目标检测领域,对于数据输入的处理一般有三种:
多视角
将三维点云投射到多个二维平面形成图像
体素
将三维点云切割成多个小块,这些小块就叫体素,类似像素。这是最自然的一种想法,正如像素通过规律排列形成二维图像,体素也是通过规律排列形成三维体的,并且可以使用3D卷积像图像一样进行操作。
点云
直接输入点云数据(N,D),N是点云文件中点的数量,一般在万级,D则是特征维度,一般是x,y,z加一个强度,也就是4维。
点云目标检测是一种用于在三维点云数据中识别目标的任务。这种任务通常用于机器人、汽车、无人机等自动化系统,帮助它们在环境中识别并避开障碍物。
点云目标检测方法通常是将三维点云数据转换为二维图像或三维模型,然后使用计算机视觉方法(如卷积神经网络)来识别目标。一些方法还使用更高维度的表示,如欧几里得空间或高斯混合模型,来更好地处理点云数据的结构信息。
点云目标检测的挑战在于,三维点云数据通常是稠密的且有噪声,而且目标的形状和尺寸通常不一致。因此,点云目标检测方法需要考虑这些因素,并提供较高的精度和可靠性。
准备工作
安装MindSpore
conda create -n groupfree3d
pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/1.9.0/MindSpore/gpu/x86_64/cuda-11.1/mindspore_gpu-1.9.0-cp38-cp38-linux_x86_64.whl --trusted-host ms-release.obs.cn-north-4.myhuaweicloud.com -i Simple Index
准备数据
ScanNet V2数据集:
格式如下:
${root_dir}
|--meta_data
|--scannet_means.npz
|--scannetv2_test.txt
|--scannetv2_train.txt
|--scannetv2_val.txt
|--scannet_train_detection_data
|--...
|--train_data.pkl
|--val_data.pkl
算法模型
Backbone
文中使用了pointnet++为基础定义了模型的backbone。在pointnet++模型中,原作者针对不同的任务类型。
提出了两种不同的网络架构,在分类任务中仅仅使用了sa模块对点云进行了特征提取的操作;在分割任务中则在sa模块的基础上加入了fp操作,实现了一种上采样的效果。
而在Group-Free-3D中,作者首先让输入点云经过四层sa模块,提取特征,然后使用两次fp模块做上采样,得到相当于原始输入点数一半M的点云特征
KPS(K-Closest Points Sampling)
对于这M个点我们选取K个种子点,文中使用了KPS作为默认的采样方法
KPS的基本思想是,在给定的点云中选取一个基准点,并从点云中找出与基准点距离最近的 k 个点。基准点则是选取ground truth对象框的中心点。
kps 算法可以用于各种不同的应用中,例如三维建模、点云处理等。它的一个优点是可以快速地从点云数据中抽取出所需数量的点,而不需要对整个点云进行扫描。
虽然 kps 算法在很多情况下都很有效,但是它也有一些局限性。例如,如果点云数据中存在噪声或偏差,那么选取的 k 个最近点可能并不是代表整个点云的最优点。此外,在处理非均匀分布的点云数据时,kps 算法的效果也可能不尽如人意。
class KPSModule(nn.Cell):
def __init__(self, seed_feature_dim=288, num_proposal=256):
super(KPSModule, self).__init__()
self.seed_feature_dim = seed_feature_dim
self.num_proposal = num_proposal
self.points_obj_cls = PointsObjClsModule(self.seed_feature_dim)
def construct(self, xyz, features):
transpose = ops.Transpose()
points_obj_cls_logits = self.points_obj_cls(features) #(B,1,N)
points_obj_cls_scores = ops.Sigmoid()(points_obj_cls_logits)
points_obj_cls_scores = ops.Squeeze(1)(points_obj_cls_scores)
sample_inds = ops.Cast()( ops.TopK(sorted=True)(points_obj_cls_scores, self.num_proposal)[1], ms.int32)
new_xyz = pointnet2_util.index_points(xyz, sample_inds)
new_features = transpose(pointnet2_util.index_points(transpose(features, (0, 2, 1)), sample_inds), (0, 2, 1))
return new_xyz, new_features, sample_inds, points_obj_cls_logits
Transformer
transformer中的核心部分就是注意力模块,原始的transformer论文中用到了多头的注意力模块,以及masked后的多头注意力模块。
而我们在图像和点云的处理中不需要对特征进行mask,因此GroupFree-3D中主要用到的也就是普通的多头注意力模块。
文中作者按照输入的不同,将这些注意力模块分成了self-attention和cross-attention。
self-attention模块是transformer中的基础模块之一,由于它的三个输入query,key,value都是来自于同一个输入,所以是对自身做attention操作,所以被称为self-attention module。
self-attention modules
本文的cross-attention模块中,query,key,value则不相同,query来自于经过KPS采样过后的特征,而key和value则是来自于pointnet++中第二个fp层的输出特征。
由于其query,key,value的取值并非来自于同一组特征,所以作者称之为cross-attention module。
cross-attention module
transformer本身具有聚合全局信息的优势,但同时也会忽略token本身的位置信息,因此对于具有时序的输入,通常需要加入positional encoding,为transformer提供时序或位置信息
文中的spatial encoding也是起到类似的作用
在GroupFree-3D文中,作者是改进了spatial eoding,具体来说,在每个decoder中,都会生成3D box的位置和类别信息。然后作者利用所生成的位置信息来辅助优化spatial encoding,并将得到的编码与输出相加,作为下一层的输入。
在代码中,GroupFree-3D中的spatial embedding具体是由两个1d卷积,以及一个BN,ReLU组成的模型
self.conv1 = nn.Conv1d(input_channel, num_pos_feats, kernel_size=1, has_bias=True, weight_init="xavier_uniform", bias_init="normal")
self.bn1 = nn.BatchNorm2d(num_pos_feats)
self.conv2 = nn.Conv1d(num_pos_feats, num_pos_feats, kernel_size=1, has_bias=True, weight_init="xavier_uniform", bias_init="normal")
self.relu = nn.ReLU()
另一个改进是将每个阶段的检测结果整合到一起,然后使用非极大值抑制来生成最终的目标检测结果。而其他的方法中,往往直接将最后一个层的输出做最终的结果
参考文献
[1] Liu Z, Zhang Z, Cao Y, et al. Group-free 3d object detection via transformers[C]//Proceedings of the IEEE/CVF International Conference on Computer Vision. 2021: 2949-2958.