(CVPR 21) SpinNet: Learning a General Surface Descriptor for 3D Point Cloud Registration

SpinNet是一种针对3D点云的旋转不变特征提取方法,通过SpatialPointTransformer消除点云在XYZ轴的自由度,实现旋转不变性。该方法包括球形体素化、XY平面旋转和圆柱形卷积等步骤,以提高特征的泛化性能。在3DMatch和ETH数据集上的实验表明,SpinNet在特征匹配和注册任务上表现出优越性能,但计算效率较低。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
SpinNet核心优势:

  1. 提取的点云表面特征具有旋转不变性(由标题便知)。
  2. 泛化性能好:仅在3DMatch上训练,在ETH上提取特征评估得到的FMR相比其他方法更高。

SpinNet核心构成:

  1. Spatial Point Transformer (这里的transformer要与NLP中的区分开…)
    1.1 Alignment with a Reference Axis
    1.2 Spherical Voxelization
    1.3 Transformation on the XY-Plane
    1.4 Cylindrical Volume Formulation
  2. 特征提取器
    2.1 Point-based Layers
    2.2 3D Cylindrical Convolutional Layers

整体感知:SpinNet是以一个点ppp及其空间邻域中的其他点构成一个local patch作为网络输入,其第一部分Spatial Point Transformer的目的是要消除这个patch中的点在XYZ 3个方向上的自由度(为了达到旋转不变性),将local patch转化成canonical representation. 接着应该就是使用一些特殊的神经网络结构构成的特征提取器对local patch提取特征,形成特征向量。

网络流程:
图1

准备输入:给定点云中一个点ppp,构造一个球形邻域Ps={pi:∣∣pi−p∣∣2≤R}{P^s} = \{ {p_i}:||{p_i} - p|{|^2} \le R\}Ps={pi:pip2R} 作为一个local patch. 如网络流程图最左端所示。

1.1 Alignment with a Reference Axis (Ps→Prs→P^rs{P^s} \to P_r^s \to \hat P_r^sPsPrsP^rs)

首先对Ps{P^s}Ps通过[1]中的方法计算得到一个reference axis np{n_p}np,接着通过旋转矩阵
Rz{R_z}Rz将此时Ps{P^s}Ps的Z轴旋转至与reference axis np{n_p}np重合(对齐)。

Prs=RzPsP_r^s = {R_z}{P^s}Prs=RzPs

这样做是为了首先消除Ps{P^s}Ps在Z轴上的自由度。

再将PrsP_r^sPrs中所有点减去其中心点ppp,相当于作一个归一化操作:

P^rs=Prs−Rzp\hat P_r^s = P_r^s - {R_z}pP^rs=PrsRzp

如网络流程图第二、三张小图所示。

1.2 Spherical Voxelization

球形体素化,具体做法是和CGF[2]一致的,在径向radial、轴向elevation、方位角方向Azimuth对P^rs\hat P_r^sP^rs进行等分:
在这里插入图片描述
如网络流程图第四个小图所示。

在radial、elevation、azimuth上分别等分成J、K、L份,用Vjkl{V_{jkl}}Vjkl代表每一个voxel体素. vjkl{v_{jkl}}vjkl为每一个体素的中心点。

接着利用体素Vjkl{V_{jkl}}VjklP^rs\hat P_r^sP^rs进行统计查询,或者说将P^rs\hat P_r^sP^rs中的所有点均匀的分布在每一个Vjkl{V_{jkl}}Vjkl体素中。具体做法是统计每一个体素中心vjkl{v_{jkl}}vjkl邻域的点,对每一个体素Vjkl{V_{jkl}}Vjkl内重新构建一个更小的patch.

Pjkl={p^i:∣∣p^i−vjkl∣∣2≤Rv,p^i∈P^rs}{P_{jkl}} = \{ {\hat p_i}:||{\hat p_i} - {v_{jkl}}|{|^2} \le {R_v},{\hat p_i} \in \hat P_r^s\}Pjkl={p^i:p^ivjkl2Rv,p^iP^rs}

对于体素Vjkl{V_{jkl}}Vjkl内的Pjkl{P_{jkl}}Pjkl,保留kv{k_v}kv个点(若多于kv{k_v}kv则随机取kv{k_v}kv个点,少于则重复取点直至Pjkl{P_{jkl}}Pjkl内有kv{k_v}kv个点)

1.3 Transformation on the XY-Plane

接着便是消除XY上的自由度,这里的做法是将所有体素Vjkl{V_{jkl}}Vjkl绕Z轴旋转至与YOZ平面对齐,具体做法就是对所有Vjkl{V_{jkl}}Vjkl作用一个一个旋转矩阵Rjkl{R_{jkl}}Rjkl,如网络流程图第五个小图所示。
在这里插入图片描述
这个Rjkl{R_{jkl}}Rjkl的含义是一个绕Z轴旋转的矩阵,首先,绕Z轴旋转θ\thetaθ的旋转矩阵:
在这里插入图片描述
所以可以很显然的看到,Rjkl{R_{jkl}}Rjkl的作用就是将所有体素Vjkl{V_{jkl}}Vjkl绕Z轴旋转至与YOZ平面对齐。文章中提到此操作消除了P^rs\hat P_r^sP^rs在XY方向上的自由度。

1.4 Cylindrical Volume Formulation

球形体素化 -> 圆柱形体素化(如网络流程图最后一个小图所示)
为什么需要转化成圆柱形,根据文章,圆柱形体素可以使用圆柱卷积,并且是SO(2)SO(2)SO(2)等价的,并且这样做也保留了圆形体素的拓扑信息。

这一步没有任何操作,只是将原来的Vjkl{V_{jkl}}Vjkl(球形体素)视作圆柱形体素。

至此,Spatial Point Transformer操作已经完成,从输入一个local patch Ps{P^s}Ps到生成生成一个由J×K×LJ \times K \times LJ×K×L个体素构成的圆柱形CCC,其中:

C∈RJ×K×L×kv×3C \in {R^{J \times K \times L \times {k_v} \times 3}}CRJ×K×L×kv×3.

2.1 Point-based Layers

接着是对CCC进行特征提取,首先对每个圆柱形体素内根据体素中心vjkl{v_{jkl}}vjkl构造出来的一个球形邻域RjklPjkl{R_{jkl}}{P_{jkl}}RjklPjkl,使用shared MLP(其实就是PointNet对每一个RjklPjkl{R_{jkl}}{P_{jkl}}RjklPjkl求一个global feature)进行初始特征提取:

fjkl=A(MLPs(RjklPjkl)){f_{jkl}} = A(MLPs({R_{jkl}}{P_{jkl}}))fjkl=A(MLPs(RjklPjkl))

其中A(⋅)A( \cdot )A()是max pooling layer.

映射出的初始特征为D维,因此经过此操作后,得到所有的圆柱形体素初始特征:

F∈RJ×K×L×DF \in {R^{J \times K \times L \times D}}FRJ×K×L×D

2.2 3D Cylindrical Convolutional Layers

整个SpinNet比较难理解的就是这里的圆柱形卷积,受到[3]的启发,作者在这里提出了一种圆柱形卷积来进一步对F∈RJ×K×L×DF \in {R^{J \times K \times L \times D}}FRJ×K×L×D进行高维特征提取,得到final descriptor ∈R32\in {R^{32}}R32.

在这里插入图片描述
圆柱形卷积的特点是由于圆柱形的输入是空间连续的,因此不需要显式的padding.

文章中的公式会比较难以理解,这里直接从代码角度来理解:

首先在经过 Cylindrical Convolution之前,网络的输入大小是

F∈RB×J×K×L×DF \in {R^{B \times J \times K \times L \times D}}FRB×J×K×L×D(多了一个B代表batch size)

,抽象到具体数字,在3DMatch数据集上的默认值是

F∈RB×9×40×80×16F \in {R^{B \times 9 \times 40 \times 80 \times 16}}FRB×9×40×80×16(16是经过PointNet+MaxPooling后的初始特征维度)

这里为了保持与代码中维度一致,以便进行Conv操作,对维度改变顺序:

F∈RB×16×9×40×80F \in {R^{B \times 16 \times 9 \times 40 \times 80}}FRB×16×9×40×80

接着进行以下操作:
在这里插入图片描述
可以看到就是普通的Conv3d+Conv2d,而圆柱卷积不需要padding的这个特性是通过主动给输入上下左右进行“伪padding”实现的,示意图如下:
在这里插入图片描述
可以看到,为了模仿圆柱形的连续性质(头尾相连),作了以上padding操作。

经过以上连续的Conv3d与Conv2d后,特征维度从输入的16→32→64→128→64→3216 \to 32 \to 64 \to 128 \to 64 \to 321632641286432,最终输出维度为[B,32,K,L][B,32,K,L][B,32,K,L],再在K,L二维上做一个max_pool2d,得到最终的descriptor ∈[B,32]\in [B,32][B,32].

Loss

Loss采用标准的Contrastive Loss,即整体网络是Siamese的,anchor与pos经过特征提取后,由归一化后的特征构成距离矩阵dists∈[B,B]{\rm{dists}} \in {\rm{[B,B]}}dists[B,B], 取对角线元素作furthest_positive,再在每一行取最小的非对角线元素作closest_negative,两者构成contrastive loss:

Loss=max(furthestLoss = max(furthestLoss=max(furthest_potive−pospotive - pospotivepos_margin,0)+max(negmargin, 0) + max(negmargin,0)+max(neg_margin−closestmargin - closestmarginclosest_negative,0)negative, 0)negative,0)

Summary

训练过程暂时没跑,但加载了作者的pretrain model作了evaluation,整体感受是SpinNet虽然具有文章中所述的旋转不变性、泛化性好等优势,但整个过程实在是太慢了,整体感受是从准备数据,到提取特征、再到Registration需要花费的时间很多。

印象中对src与tgt各提5000个点的特征,从局部领域的建立到网络前向传播再到RANSAC已经要达到1分钟左右的时间了,且不说SpinNet特征比FPFH好多少,但起码FPFH这种手工特征提5000个点的特征只需要不到1s…

并且在球形体素化过程中,3个方向分别需要等分多少份、步长距离这些都是需要人为设定的超参数,算是比较多的,因此若想将SpinNet应用在真实配准场景,应该还需要大量调参过程。

Reference
[1] Sheng Ao, Yulan Guo, Jindong Tian, Yong Tian, and Dong Li. A Repeatable and Robust Local Reference Frame for 3D Surface Matching. PR, 2020.
[2] Marc Khoury, Qian-Yi Zhou, and Vladlen Koltun. Learning Compact Geometric Features. In ICCV, 2017.
[3] Sunghun Joung, Seungryong Kim, Hanjae Kim, Minsu Kim, Ig-Jae Kim, Junghyun Cho, and Kwanghoon Sohn. Cylindrical Convolutional Networks for Joint Object Detection and Viewpoint Estimation. In CVPR, 2020.

Done

### SpinNet 的使用方法与应用场景 #### 使用方法概述 SpinNet 是一种基于深度学习的方法,其核心目标是从 3D 点云中提取旋转不变的特征并生成通用表面描述符。这种方法特别适用于点云配准任务和其他涉及几何分析的应用场景[^1]。 为了安装和运行 SpinNet 所需的相关依赖项,可以通过以下命令完成环境配置: ```bash pip install "git+git://github.com/erikwijmans/Pointnet2_PyTorch.git#egg=pointnet2_ops&subdirectory=pointnet2_ops_lib" ``` 此命令会下载 Pointnet2_PyTorch 库及其操作库 `pointnet2_ops` 并将其集成到 Python 环境中[^2]。 #### 示例代码展示 以下是 SpinNet 的基本实现框架示例: ```python import torch from spinnet_model import SpinNetModel # 假设已定义模型类 def load_spinnet(): model = SpinNetModel() checkpoint_path = 'path_to_checkpoint.pth' # 替换为实际路径 state_dict = torch.load(checkpoint_path, map_location=torch.device('cpu')) model.load_state_dict(state_dict) return model.eval() def process_point_cloud(point_cloud_data): """ 处理输入点云数据以获取旋转不变特征。 :param point_cloud_data: 输入点云数据 (NxC tensor) :return: 提取的特征向量 """ device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') model = load_spinnet().to(device) with torch.no_grad(): input_tensor = torch.tensor(point_cloud_data).float().unsqueeze(0).to(device) # 转化为张量 features = model(input_tensor)[0].cpu().numpy() # 获取特征 return features if __name__ == "__main__": sample_point_cloud = [[...], [...]] # 替换为实际点云坐标列表 extracted_features = process_point_cloud(sample_point_cloud) print(f"Extracted Features Shape: {extracted_features.shape}") ``` 上述代码展示了如何加载预训练好的 SpinNet 模型以及处理点云数据的过程。注意,在实际应用中可能需要调整输入数据格式以匹配模型的要求。 #### 应用场景说明 SpinNet 可广泛应用于多种领域中的点云数据分析任务,具体包括但不限于以下几个方面: - **点云配准**:通过学习局部区域的旋转不变特征,SpinNet 能够有效提升点云之间的对齐精度[^4]。 - **三维重建**:在复杂环境中构建高精度的三维模型时,该算法可提供可靠的表面描述符支持。 - **机器人导航与感知**:帮助自主移动设备理解周围空间结构,并实现实时定位功能[^3]。 尽管如此,需要注意的是某些情况下其他 SOTA 方法可能会表现更优;例如 Predator 和 FCGF 在特定条件下能够达到更高的准确性水平。 ---
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值