首页 > 其他分享 >PointNet++改进策略 :模块改进 | x-Conv | PointCNN, 结合局部结构与全局排列提升模型性能

PointNet++改进策略 :模块改进 | x-Conv | PointCNN, 结合局部结构与全局排列提升模型性能

时间:2024-09-11 10:52:48浏览次数:15  
标签:PointCNN Conv ++ MLP 卷积 改进 特征 点云

目录

Pasted image 20240910094800

前言

这篇论文介绍了一种名为 PointCNN 的方法,旨在从点云(point cloud)数据中学习特征。传统卷积神经网络(CNN)在处理规则网格数据(如图像)时非常有效,但由于点云是无序且不规则的,直接在其上应用卷积操作会导致形状信息丢失,并对点的排列顺序敏感。

为了解决这一问题,论文提出了一种 X-Conv 操作。该方法通过学习一种 X-transformation 来重新排列点云中的点并加权输入特征。然后,将典型的卷积操作应用于转换后的特征。这种方法将传统的 CNN 扩展到点云特征学习,并命名为 PointCNN

实验表明,PointCNN 在多个基准数据集上达到了与当前最先进方法相当甚至更好的性能。这些数据集包括 3D 形状分类(如 ModelNet40)、分割任务(如 ShapeNet Parts 和 ScanNet),以及 2D 草图分类任务(如 TU-Berlin 和 Quick Draw)。

论文的关键贡献在于提出了适用于点云的卷积操作,并展示了其在多种任务上的有效性。

Pasted image 20240910094823

PointCNN实现细节

PointCNN 是一种针对点云数据进行特征学习的卷积神经网络架构。它的设计初衷是为了克服传统卷积神经网络(CNN)在处理点云数据时遇到的挑战。点云数据是不规则且无序的,因此直接将传统的卷积操作应用在点云上会导致形状信息的丢失,并且对点的排列顺序非常敏感。

PointCNN 的核心思想是引入一种叫做 X-Conv 的操作,这种操作通过学习一个 X-transformation 变换矩阵来同时加权和排列输入点云的数据,使得卷积操作可以更有效地应用于点云。具体来说,X-transformation 将点云的点映射到一个潜在的、或许是规范化的顺序中,然后在变换后的特征上应用卷积操作。

相比于直接对点云进行卷积,PointCNN 通过 X-Conv 操作保留了点云的局部结构信息,同时对点的排列顺序具有不变性。这使得它在点云的各种任务中表现出色,例如3D形状分类、分割任务和草图分类等。

简而言之,PointCNN 是一个能够处理不规则点云数据的通用卷积网络架构,解决了点云数据中的排列问题,并在多个任务上达到了与最先进方法相当甚至更好的性能。
Pasted image 20240910094835

1. X X X-Conv 操作

X X X-Conv 是 PointCNN 的核心操作,它通过学习一个 X X X-转换矩阵,对输入点及其特征进行加权和排序,然后进行卷积操作。整个 X X X-Conv 的过程如下:

输入
  • K K K: 表示点邻域中的 K K K 个点。
  • p p p: 表示当前代表点。
  • P P P: 当前点 p p p 的 K K K 个邻域点的坐标,表示为 P = ( p 1 , p 2 , … , p K ) T P = (p_1, p_2, \dots, p_K)^T P=(p1​,p2​,…,pK​)T。
  • F F F: 邻域点的特征矩阵,表示为 F = ( f 1 , f 2 , … , f K ) T F = (f_1, f_2, \dots, f_K)^T F=(f1​,f2​,…,fK​)T,其中 f i ∈ R C 1 f_i \in \mathbb{R}^{C_1} fi​∈RC1​。
输出
  • F p F_p Fp​: 聚合到代表点 p p p 的输出特征。
步骤
  1. 局部坐标系变换:首先将邻域点的坐标转换为相对于代表点 p p p 的局部坐标系,即 P ′ ← P − p . P' \leftarrow P - p. P′←P−p.
  2. 升维操作:通过多层感知机(MLP),将每个邻域点的坐标升维到 C δ C_\delta Cδ​ 维空间,得到 F δ F_\delta Fδ​,即 F δ ← MLP δ ( P ′ ) . F_\delta \leftarrow \text{MLP}_\delta(P'). Fδ​←MLPδ​(P′).
  3. 特征拼接:将升维后的坐标特征 F δ F_\delta Fδ​ 与原始特征 F F F 进行拼接,形成新的特征矩阵 F ∗ F^* F∗,其形状为 K × ( C δ + C 1 ) K \times (C_\delta + C_1) K×(Cδ​+C1​): F ∗ ← [ F δ , F ] . F^* \leftarrow [F_\delta, F]. F∗←[Fδ​,F].
  4. X X X-转换矩阵的学习:通过一个 MLP 网络,从局部坐标 P ′ P' P′ 中学习到一个 K × K K \times K K×K 的 X X X-转换矩阵: X ← MLP ( P ′ ) . X \leftarrow \text{MLP}(P'). X←MLP(P′).
  5. 加权和排序:对拼接后的特征矩阵 F ∗ F^* F∗ 进行加权和排序,得到 F X F_X FX​: F X ← X × F ∗ . F_X \leftarrow X \times F^*. FX​←X×F∗.
  6. 卷积操作:最后,将加权后的特征 F X F_X FX​ 与卷积核进行卷积操作,输出结果特征 F p F_p Fp​: F p ← Conv ( K , F X ) . F_p \leftarrow \text{Conv}(K, F_X). Fp​←Conv(K,FX​).

该过程可以总结为如下公式: F p = X -Conv ( K , p , P , F ) = Conv ( K , MLP ( P − p ) × [ MLP δ ( P − p ) , F ] ) . F_p = X\text{-Conv}(K, p, P, F) = \text{Conv}(K, \text{MLP}(P - p) \times [\text{MLP}_\delta(P - p), F]). Fp​=X-Conv(K,p,P,F)=Conv(K,MLP(P−p)×[MLPδ​(P−p),F]).

2. PointCNN 网络架构

PointCNN 使用 X X X-Conv 操作递归地应用在点云的不同层级上,实现了层级特征表示。输入到 PointCNN 的是点集 { ( p 1 , f 1 ) , ( p 2 , f 2 ) , … , ( p N , f N ) } \{(p_1, f_1), (p_2, f_2), \dots, (p_N, f_N)\} {(p1​,f1​),(p2​,f2​),…,(pN​,fN​)},其中 p i p_i pi​ 是点的坐标, f i f_i fi​ 是与点关联的特征。

层级卷积

类似于传统 CNN 的层级卷积,PointCNN 通过多层的 X X X-Conv 逐步减少点的数量,并增大特征维度。层级的每一层通过聚合局部点的特征,得到新的代表点及其特征。对于输入点云 F 1 = { ( p 1 , i , f 1 , i ) } F_1 = \{(p_{1,i}, f_{1,i})\} F1​={(p1,i​,f1,i​)},我们可以递归应用 X X X-Conv,生成新的表示 F 2 = { ( p 2 , i , f 2 , i ) } F_2 = \{(p_{2,i}, f_{2,i})\} F2​={(p2,i​,f2,i​)},其中 ∣ F 2 ∣ < ∣ F 1 ∣ |F_2| < |F_1| ∣F2​∣<∣F1​∣ 且特征维度更高。

每一层的输出可表示为: F l + 1 = X -Conv ( K , P l , F l ) , F_{l+1} = X\text{-Conv}(K, P_l, F_l), Fl+1​=X-Conv(K,Pl​,Fl​), 其中 P l P_l Pl​ 是第 l l l 层的代表点坐标, F l F_l Fl​ 是第 l l l 层的特征矩阵, K K K 是邻域点数。

分类与分割任务
  • 分类网络:PointCNN 将通过若干 X X X-Conv 层逐步将输入点聚合为较少的代表点,并最终通过全连接层实现分类。在分类网络中,最后一个 X X X-Conv 层的输出是一个全局表示,通常只保留一个代表点,并应用全连接层进行分类。

  • 分割网络:在分割任务中,PointCNN 采用类似于 U-Net 的架构, X X X-Conv 不仅在卷积部分应用,也在 DeConv 部分应用,以逐步将全局信息传播到高分辨率的点云表示上。

3. 数据增强

为了提高模型的泛化能力,PointCNN 使用了随机采样和输入点集顺序打乱的数据增强策略。在训练时,PointCNN 随机采样 N ∼ N ( 1024 , 12 8 2 ) N \sim \mathcal{N}(1024, 128^2) N∼N(1024,1282) 个点作为输入,并在每个批次中对输入点的顺序进行打乱。这对于训练一个对点集输入顺序不敏感的模型至关重要。

4. 效率优化

在实现中, X X X-Conv 的复杂度为 O ( K 3 ) O(K^3) O(K3),并且使用了深度可分离卷积来进一步减少计算复杂度。整个操作过程均为可微分的,因此 PointCNN 可以使用反向传播进行训练。

标签:PointCNN,Conv,++,MLP,卷积,改进,特征,点云
From: https://blog.csdn.net/u012901740/article/details/142082200

相关文章

  • OpenCV结构分析与形状描述符(17)判断轮廓是否为凸多边形的函数isContourConvex()的使用
    操作系统:ubuntu22.04OpenCV版本:OpenCV4.9IDE:VisualStudioCode编程语言:C++11算法描述测试轮廓的凸性。该函数测试输入的轮廓是否为凸的。轮廓必须是简单的,即没有自相交。否则,函数的输出是不确定的。cv::isContourConvex函数是OpenCV提供的一个用于判断轮廓是否......
  • OpenCV结构分析与形状描述符(16)判断两个凸多边形是否相交的函数intersectConvexConvex(
    操作系统:ubuntu22.04OpenCV版本:OpenCV4.9IDE:VisualStudioCode编程语言:C++11算法描述查找两个凸多边形的交集。intersectConvexConvex是一个在OpenCV中用于判断两个凸多边形是否相交的函数。此函数可以帮助我们确定两个二维凸多边形是否在平面上有重叠区域。函......
  • 南沙C++信奥老师解一本通题:1203:扩号匹配问题
    ​【题目描述】在某个字符串(长度不超过100)中有左括号、右括号和大小写字母;规定(与常见的算数式子一样)任何一个左括号都从内到外与在它右边且距离最近的右括号匹配。写一个程序,找到无法匹配的左括号和右括号,输出原来字符串,并在下一行标出不能匹配的括号。不能匹配的左括号用"$"标......
  • C++题目收集2
    这是本专栏的的第二篇收录集,我们一起来看一看那些有意思的题目,拓宽自己的思路。本期的题目有一些难,所以数目少一点。题目一:约瑟夫环#include<iostream>#include<vector>intjosephus(intn,intm){std::vector<int>people(n);for(inti=0;i<n;++i)......
  • 《C++ Primer Plus》学习day3
    C++11新增的内容:char16_t和char32_tchar16_t:无符号,16位,使用前缀u表示char_16字符常量和字符串常量;char32_t:无符号,32位,使用前缀U表示char32_t常量浮点类型C++有三种浮点类型:float、double、longdouble头文件cfloat中对对浮点数进行了限制:比如最低有效位......
  • C++入门 一(命名空间,缺省参数,超详细!!!)
    文章目录C++与C语言的区别命名空间(Namespace)缺省参数C++与C语言的区别C++在保留了C语言所有特性的基础上增加了面向对象编程的支持,并引入了更多的高级特性和工具来提高代码的可读性、可维护性和可扩展性。而C语言则更加简洁和底层,适用于对性能要求极高或对内存管理......
  • c++引用
    c++指针和引用的区别指针和引用在C++中都用于间接访问变量,但它们有一些区别:指针是一个变量,它保存了另一个变量的内存地址;引用是另一个变量的别名,与原变量共享内存地址。指针(除指针常量)可以被重新赋值,指向不同的变量;引用在初始化后不能更改,始终指向同一个变量。指针可以为......
  • C++入门知识
    命名空间为什么会有命名空间?解决C语言中命名冲突的问题。(std是所有c++库的命名空间)解决方法:采用域作用限定符(::):指定编译器搜索的位置。编译器默认的搜索顺序:先局部再全局。命名空间域大体有4种域:全局域、局部域、命名空间域、类域。命名空间域的特点:1.不会影响生命......
  • 挑战不可能篇1——洛谷28分钟14道CCF GESP C++ 一级上机题&洛谷14道题题解
    扯谈今天继续挑战不可能:洛谷28分钟14道题这我个人认为不简单,算上编译、提交、命名等杂七杂八的东东之后,只剩下了大约1分钟/题。本次挑战的是CCFGESPC++一级上机题.这竟然能成功!下面附上每一题第一题第二题第三题第四题第五题第六题第七题第八题第九题第十题......
  • 【C++ Primer Plus习题】14.3
    大家好,这里是国中之林!❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看←问题:解答:main.cpp#include<iostream>#include"queuetp.h"usingnamespacestd;intmain(){ Queue......