Skip to content

Latest commit

 

History

History
 
 

PointNet++

PointNet++ 分类和语义分割模型


内容

简介

PointNet++ 是 Charles R. Qi, Li Yi, Hao Su, Leonidas J. Guibas 等人提出的,针对3D数据进行分类和语义分割的模型。该模型基于PointNet进行了拓展, 使用分层点集特征学习来提取点云数据的特征,首先通过对输入point进行分组和采样提取局部区域模式,然后使用多层感知器来获取点特征。PointNet++ 还将点特征传播用于语义分割模型,采用基于距离插值和跨级跳转连接的分层传播策略,对点特征进行向上采样,获得所有原始点的点特征。

网络结构如下所示:


用于点云分类和分割的 PointNet++ 网络结构

集合抽象层是网络的基本模块,每个集合抽象层由三个关键层构成:采样层、分组层和特征提取层。

  • 采样层:采样层使用最远点采样(FPS)的方法,从输入点中选择一组点,它定义了局部区域的中心。与随机抽样的方法相比,在质心数目相同的情况下,FPS可以更好的覆盖整个点集。

  • 分组层:分组层通过寻找中心体周围的“邻近”点来构造局部区域集。在度量空间采样的点集中,点的邻域由度量距离定义。这种方法被称为“query ball”,它使得局部区域的特征在空间上更加一般化。

  • 特征提取层: 特征提取层使用 mini-PointNet 对分组层给出的各个区域进行特征提取,获得局部特征。

注意: PointNet++ 模型构建依赖于自定义的 C++ 算子,目前仅支持GPU设备在Linux/Unix系统上进行编译,本模型不能运行在Windows系统或CPU设备上

快速开始

安装

安装 PaddlePaddle:

在当前目录下运行样例代码需要 PaddelPaddle Fluid develop每日版本或使用PaddlePaddle develop分支源码编译安装.

为了使自定义算子与paddle版本兼容,建议您优先使用源码编译paddle,源码编译方式请参考编译安装

编译自定义OP

注意: 请使用4.8及以上版本的gcc进行自定义OP的编译,否则可能引入兼容性问题。

请确认Paddle版本为PaddelPaddle Fluid develop每日版本或基于Paddle develop分支源码编译安装,推荐使用源码编译安装的方式

自定义OP编译方式如下:

进入 `ext_op/src` 目录,执行编译脚本
```
cd ext_op/src
sh make.sh
```

成功编译后,`ext_op/src` 目录下将会生成 `pointnet2_lib.so` 

执行下列操作,确保自定义算子编译正确:

```
# 设置动态库的路径到 LD_LIBRARY_PATH 中
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`python -c 'import paddle; print(paddle.sysconfig.get_lib())'`

# 回到 ext_op 目录,添加 PYTHONPATH
cd ..
export PYTHONPATH=$PYTHONPATH:`pwd`

# 运行单测 
python tests/test_farthest_point_sampling_op.py
python tests/test_gather_point_op.py
python tests/test_group_points_op.py
python tests/test_query_ball_op.py
python tests/test_three_interp_op.py
python tests/test_three_nn_op.py
```
单测运行成功会输出提示信息,如下所示:

```
.
----------------------------------------------------------------------
Ran 1 test in 13.205s

OK
```

说明: 更多关于自定义OP的编译说明,请参考自定义OP编译

数据准备

ModelNet40 数据集:

PointNet++ 分类模型在 ModelNet40 数据集上进行训练,我们提供了数据集下载脚本:

cd dataset/ModelNet40
sh download.sh

数据目录结构如下所示:

  dataset/ModelNet40/modelnet40_ply_hdf5_2048
  ├── train_files.txt
  ├── test_files.txt
  ├── shape_names.txt
  ├── ply_data_train0.h5
  ├── ply_data_train_0_id2file.json
  ├── ply_data_test0.h5
  ├── ply_data_test_0_id2file.json
  |   ...

Indoor3DSemSeg 数据集:

PointNet++ 分割模型在 Indoor3DSemSeg 数据集上进行训练,我们提供了数据集下载脚本:

cd dataset/Indoor3DSemSeg
sh download.sh

数据目录结构如下所示:

  dataset/Indoor3DSemSeg/
  ├── all_files.txt
  ├── room_filelist.txt
  ├── ply_data_all_0.h5
  ├── ply_data_all_1.h5
  |   ...

训练

分类/分割模型默认使用单卡训练,在启动训练前请指定单卡GPU,并将动态库的路径添加到 LD_LIBRARY_PATH 中:

# 指定0号卡进行GPU训练
export CUDA_VISIBLE_DEVICES=0

# 设置动态库的路径到 LD_LIBRARY_PATH 中
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`python -c 'import paddle; print(paddle.sysconfig.get_lib())'`

分类模型:

可通过如下方式启动 PointNet++ 分类模型的训练:

# 开始训练
python train_cls.py --model=MSG --batch_size=16 --save_dir=checkpoints_msg_cls

我们同时提供了训练分类模型的“快速开始”脚本:

sh scripts/train_cls.sh

语义分割模型:

可通过如下方式启动 PointNet++ 语义分割模型的训练:

# 开始训练
python train_seg.py --model=MSG --batch_size=32 --save_dir=checkpoints_msg_seg

我们同时提供了训练语义分割模型的“快速开始”脚本:

sh scripts/train_seg.sh

模型评估

分类/分割模型默认使用单卡评估,首先指定单卡GPU,并将动态库的路径添加到 LD_LIBRARY_PATH 中:

# 指定0号卡进行GPU评估
export CUDA_VISIBLE_DEVICES=0

# 设置动态库的路径到 LD_LIBRARY_PATH 中
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`python -c 'import paddle; print(paddle.sysconfig.get_lib())'`

分类模型:

可通过如下方式启动 PointNet++ 分类模型的评估:

# 对给定权重进行评估
python eval_cls.py --model=MSG --weights=checkpoints_cls/200

我们同时提供了评估分类模型的“快速开始”脚本:

sh scripts/eval_cls.sh

分类模型的评估结果如下所示:

model Top-1 download
SSG(Single-Scale Group) 89.3 model
MSG(Multi-Scale Group) 90.0 model

语义分割模型:

可通过如下方式启动 PointNet++ 语义分割模型的评估:

# 对给定权重进行评估
python eval_seg.py --model=MSG --weights=checkpoints_seg/200

我们同时提供了评估语义分割模型的“快速开始”脚本:

sh scripts/eval_seg.sh

语义分割模型的评估结果如下所示:

model Top-1 download
SSG(Single-Scale Group) 86.1 model
MSG(Multi-Scale Group) 86.6 model

参考文献

版本更新

  • 11/2019, 新增 PointNet++ 分类和语义分割模型。