如何手把手教你复现PointNet实现3D点云检测?
摘要:作者:SkyXZ CSDN:SkyXZ~-CSDN博客 博客园:SkyXZ - 博客园 PointNet论文Arxiv地址:[1612.00593] PointNet: Deep Learning on Point Sets for 3D
作者:SkyXZ
CSDN:SkyXZ~-CSDN博客
博客园:SkyXZ - 博客园
PointNet论文Arxiv地址:[1612.00593] PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation
传统的目标检测算法已经非常成熟,例如 YOLO 系列、DETR、Faster R-CNN 等,它们主要处理的是规则的二维图像数据。在图像中,像素按照规则网格排列,不同网格之间排列的不同会导致图像结果完全不同,这种有序性非常适合卷积神经网络进行特征提取。然而,3D 的点云完全不同。它是一组离散、无序且稀疏分布的空间点,没有固定的拓扑结构和排列顺序,也就是说点与点之间的邻居关系不是固定的。想象一下,你有14个乒乓球,他们随机地散落在桌子上,但共同组成了一个雨伞的形状。
这些小球就像点云中的点:它们位置无序,没有行列坐标;即使你把小球拿起来打乱顺序再放回去,雨伞的形状依然不变,而理想情况下,一个点云处理模型也应该具有这样的“顺序不变性”——输入顺序变了,输出识别结果不变。然而传统基于卷积的网络并不具备这种能力,卷积依赖规则栅格来共享权重和提取局部特征,直接用在点云上不仅效率低下,还会让提取到的特征对点输入顺序非常敏感,并且难以捕捉物体的整体形状和局部几何关系。为了解决这些问题,斯坦福大学提出了一种开创性的思路,他们通过共享多层感知机(MLP)对每个点独立提取特征,再使用全局对称函数将这些特征汇总,从而将无序的点云信息转化为顺序不敏感的全局特征,实现了对点云的端到端学习与识别,这也是本文将要介绍的核心算法PointNet。
PS:💻 项目完整代码已上传至Github:,这篇文章是我的学习总结,如果你在阅读中有任何问题、建议或错误指出,也欢迎在评论区与我讨论,我们共同进步!
一、白话解析PointNet架构设计及各组件原理
在传统的检测算法中,模型通常依赖规则栅格和卷积运算来捕捉局部邻域特征,需要在输入端人为地建立点与点之间的空间关系;而 PointNet 则直接在点集上进行特征学习,平等的对待桌面上的每一个“小球”,认为他们同等重要,在这个理论下,PointNet网络通过三个步骤来解决点云检测的问题:先把点云“摆正”,再给每个点“贴标签”,最后把信息“汇总起来”:
先把点云“摆正”(T-Net)
前面我们提到过,点云数据具有无序性和空间姿态不确定性,对于同一辆车来说,雷达从不同角度扫描得到的点云可能完全不一样,甚至整片点云都会发生旋转或平移,而PointNet的第一步便是让这些点先“坐好”,其用一个叫 T-Net 的小网络来预测一个\(3×3\)或更高维的变换矩阵 \(T\),并将输入点云 ${x_i \in \mathbb{R}^3} \(映射到一个更“规范”的坐标系中\) x^′_i=T⋅x_i.$,这样,不s管车是转了个方向还是稍微偏移,后面处理点云的步骤都在一个“标准姿态”下进行,后续特征提取过程就能对空间扰动更稳健。
给每个点“贴标签”(共享 MLP)
点云里每个点都可能包含一些形状信息,但这些点是无序的,就像一堆散落在桌上的小球,传统的卷积神经网络习惯让像素按行按列排好队来逐个卷积得到特征顺序,可点云不讲规矩,所以PointNet不强行整理"队伍",而是平等对待点云信息中的每一个点,其将点云信息中的每个点都单独通过同一组多层感知机(MLP)来进行特征映射,我们设 MLP 为函数$ h(\cdot)\(,其对每个点独立计算:\)f_i=h(x_i^′),i=1,…,n.$,由于 MLP 权重是共享的,网络会平等对待每一个点,而不关心他们的输入顺序,因此不管点的顺序怎么换,其得到的结果都会是一样的 。
把信息“汇总起来”(最大值池化MaxPooling)
在上一步中我们将每个点都经过了MLP进行处理得到了每个点单独的特征维度,但由于每个点的顺序都是乱的,如果只是简单的对特征进行相加或者拼接得到的结果便会依赖于点云的数据,这时候斯坦福的研究人员便想到了使用最大值池化MaxPooling,也就是对每个特征维度\(j\),我们从所有点的特征里挑一个最大值出来\(g_j=max(f_{ij}),j=1,…,k\),组成一个固定维度的最大值特征向量,而由于最大值运算与输入顺序无关,因此这一步保证了整个网络具有数学意义上的“顺序不变性”。
