PointNet
这篇文章是点云神经网络的鼻祖,它提出了一种网络结构,可以直接从点云中学习特征。如何设计出符合点云特点的网络是一个难点。该文章在分类、语义分割两种任务上做出了对比,并给了理论和实验分析。
点云的特点其实非常好理解:
- 排列不变性:重排一遍所有点的输入顺序,所表示的还是同一个点云数据,网络的输出应该相同。
- 点集之间的交互性:点与点之间有未知的关联性。
- 变换不变性:对于某些变换,例如仿射变换,应用在点云上时,不应该改变网络对点云的理解。
只要网络抓住这三个特点,那么它至少就能作为一个能用的 encoder 。PointNet 是这么处理这三个问题的:
- 排列不变性:该文章使用了对称函数(Symmetry Function),它的特点是对输入集合的顺序不敏感。这种函数非常多,如 maxpooling,加法,向量点积等。PointNet 采用的是 maxpooling 方法来聚合点集信息。
- 交互性:实际上,对称函数的聚合操作就已经得到了全局的信息,此时将点的特征向量与全局的特征向量 concat 起来,就可以让每个点感知到全局的语义信息了,即所谓的交互性。
- 变换不变性:只需要对输入做一个标准化操作即可。PointNet 使用网络训练出了 D 维空间的变换矩阵。
此时我们再来看看网络结构:
分类网络:输入的是 n 个三维坐标(实际上可以更多维度),预测了一个变换矩阵做了变换,然后使用 MLP 对每个点做一个 embedding,之后再在 feature 空间中预测了变换矩阵做变换,然后又做了 embedding,最后 maxpooling 得到全局特征。用全局特征过一个 MLP 来做 label prediction。
分割网络:相比分类,分割需要每个点捕捉全局信息后才能知道自己是哪一类,于是把每个点的 feature 和全局 feature 做一个 concat,过 MLP,之后对每个点做 label prediction。
(不过,对于 feature 变换,论文特别指出需要配合一个正则化项 loss,详情请看论文)
容易发现,PointNet 实际上只解决了最基本的如何满足点云性质问题,并只捕捉到了全局信息,这些做法是远远不够的。
pointnet的基于网上现有的只有基于tf的部署也是那种将框架下载下来基于C++部署,
现在提供另外一种部署方式C++调用python的部署方式。
网上很多关于点云得部署也有,有基于Tensorrt得部署。目前我们来尝试最简单的部署。。。
首先我们下载pointnet代码:
接下来我们使用C++调用python实现在Qt里面显示点云得分割
C++
#include <Python.h>
#include <numpy/arrayobject.h>
#include <opencv2/opencv.hpp>
using namespace std;
int main()
{
Py_Initialize(); //初始化,创建一个Python虚拟环境
if (Py_IsInitialized())
{
Py_SetPythonHome(L"D:\\Annconda2021\\envs\\pointnet");//指定python.exe位置
Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('D:/PointNet/pointnet.pytorch/utils/')");
PyObject* pModule = NULL;
PyObject* pFunc = NULL;
pModule = PyImport_ImportModule("test_python"); //参数为Python脚本的文件名
if (pModule)
{
pFunc = PyObject_GetAttrString(pModule, "PointSeg"); //获取函数
PyEval_CallObject(pFunc, NULL); //执行函数
}
else
{
printf("nnnnnn...\n");
}
}
else
{
printf("Python loss...\n");
}
Py_Finalize();
}
结果展示: