README.md 7.6 KB
Newer Older
K
Kaipeng Deng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
# PointNet++ 分类和语义分割模型

---
## 内容

- [简介](#简介)
- [快速开始](#快速开始)
- [参考文献](#参考文献)
- [版本更新](#版本更新)

## 简介

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


网络结构如下所示:

<p align="center">
<img src="image/pointnet2.jpg" height=300 width=800 hspace='10'/> <br />
用于点云分类和分割的 PointNet++ 网络结构
</p>

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

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

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

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



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


## 快速开始

### 安装

**安装 [PaddlePaddle](https://github.com/PaddlePaddle/Paddle):**

在当前目录下运行样例代码需要 PaddelPaddle Fluid [develop每日版本](https://www.paddlepaddle.org.cn/install/doc/tables#多版本whl包列表-dev-11)或使用PaddlePaddle [develop分支](https://github.com/PaddlePaddle/Paddle/tree/develop)源码编译安装. 

为了使自定义算子与paddle版本兼容,建议您**优先使用源码编译paddle**,源码编译方式请参考[编译安装](https://www.paddlepaddle.org.cn/install/doc/source/ubuntu)


### 编译自定义OP

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

自定义OP编译方式如下:

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

    成功编译后,`exr_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 test/test_farthest_point_sampling_op.py
    python test/test_gather_point_op.py
    python test/test_group_points_op.py
    python test/test_query_ball_op.py
    python test/test_three_interp_op.py
    python test/test_three_nn_op.py
    ```
    单测运行成功会输出提示信息,如下所示:

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

    OK
    ```

**说明:** 更多关于自定义OP的编译说明,请参考[自定义OP编译](./ext_op/README.md)


### 数据准备

**ModelNet40 数据集:**

PointNet++ 分类模型在 [ModelNet40 数据集](https://shapenet.cs.stanford.edu/media/modelnet40_ply_hdf5_2048.zip)上进行训练,我们提供了数据集下载脚本:

```
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 数据集](https://shapenet.cs.stanford.edu/media/indoor3d_sem_seg_hdf5_data.zip)上进行训练,我们提供了数据集下载脚本:

```
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) | 87.4 | [model]() |
| MSG(Multi-Scale Group)  | 89.2 | [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.8 | [model]() |

## 参考文献

- [PointNet++: Deep Hierarchical Feature Learning on Point Sets in a Metric Space](https://arxiv.org/abs/1706.02413), Charles R. Qi, Li Yi, Hao Su, Leonidas J. Guibas.
- [PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation](https://www.semanticscholar.org/paper/PointNet%3A-Deep-Learning-on-Point-Sets-for-3D-and-Qi-Su/d997beefc0922d97202789d2ac307c55c2c52fba), Charles Ruizhongtai Qi, Hao Su, Kaichun Mo, Leonidas J. Guibas.

## 版本更新

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