Open3Dを用いた3D処理入門｜点群処理、メッシュ化

## Open3Dの概要とインストール
### Open3Dの概要
`Open3D`は3Dデータを取り扱うソフトウェアの開発にあたって用いられるオープンソースのライブラリです。`OpenCV`は`C++`や`Python`から使用することができます。

`Open3D`には下記のような特徴があります。

```
・3D data structures
・3D data processing algorithms
・Scene reconstruction
・Surface alignment
・3D visualization
・Physically based rendering (PBR)
・3D machine learning support with PyTorch and TensorFlow
・GPU acceleration for core 3D operations
・Available in C++ and Python
```

![Open3D_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936087/54bf7c05-2ec8-4cc9-9de6-5e8a045d85b7.png)

https://www.open3d.org/docs/release/introduction.html


### Open3Dのインストール
Open3Dは下記を実行することでPyPIから入手することができます。

```
$ pip install open3d
```

https://www.open3d.org/docs/release/getting_started.html



## OpenCVの実行例
https://www.open3d.org/docs/release/tutorial/geometry/index.html

当節では以下、上記のチュートリアルを元に`Open3D`を用いた点群処理について確認します。基本的にチュートリアルと同じコードを用いていますが、ライブラリの読み込みや重複するコードなどが省略されているのでそのまま動くようにコードを追記しました。


### Open3Dを用いた点群処理
https://www.open3d.org/docs/release/tutorial/geometry/pointcloud.html

以下、上記に基づいて`Open3D`を用いた点群処理のサンプルコードについて確認します。

```python
import numpy as np
import open3d as o3d


ply_point_cloud = o3d.data.PLYPointCloud()
pcd = o3d.io.read_point_cloud(ply_point_cloud.path)

print(pcd)
print(np.asarray(pcd.points))
print(np.asarray(pcd.points).shape)

o3d.visualization.draw_geometries([pcd],
                                  zoom=0.3412,
                                  front=[0.4257, -0.2125, -0.8795],
                                  lookat=[2.6172, 2.0475, 1.532],
                                  up=[-0.0694, -0.9768, 0.2024])
```

・実行結果
```
PointCloud with 196133 points.
[[0.65234375 0.84686458 2.37890625]
 [0.65234375 0.83984375 2.38430572]
 [0.66737998 0.83984375 2.37890625]
 ...
 [2.00839925 2.39453125 1.88671875]
 [2.00390625 2.39488506 1.88671875]
 [2.00390625 2.39453125 1.88793314]]
 (196133, 3)
```

![Open3D_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936087/8632532f-c161-4334-93ef-22750c946618.png)

実行したスクリプトは「`o3d.data.PLYPointCloud`や`o3d.io.read_point_cloud`を元に`pcd`に保存したオブジェクトが196,133個の点を持ち、`np.asarray(pcd.points)`によって`NumPy`形式で取得できる」と大まかに理解すると良いと思います。

また、`o3d.io.read_point_cloud`は「ファイルからの点群読み込み」、`o3d.visualization.draw_geometries`は「点群の可視化」に用いられるメソッドであることも合わせて抑えておくと良いです。


### Open3Dを用いたメッシュ化
https://www.open3d.org/docs/release/tutorial/geometry/mesh.html

以下、上記に基づいて`Open3D`を用いたメッシュ化のサンプルコードについて確認します。

```python
import numpy as np
import open3d as o3d


knot_mesh = o3d.data.KnotMesh()
mesh = o3d.io.read_triangle_mesh(knot_mesh.path)

print(mesh)

print('Vertices:')
print(np.asarray(mesh.vertices))
print(np.asarray(mesh.vertices).shape)

print('Triangles:')
print(np.asarray(mesh.triangles))
print(np.asarray(mesh.triangles).shape)

o3d.visualization.draw_geometries([mesh])
```

・実行結果
```
TriangleMesh with 1440 points and 2880 triangles.
Vertices:
[[  4.51268387  28.68865967 -76.55680847]
 [  7.63622284  35.52046967 -69.78063965]
 [  6.21986008  44.22465134 -64.82303619]
 ...
 [-22.12651634  31.28466606 -87.37570953]
 [-13.91188431  25.4865818  -86.25827026]
 [ -5.27768707  23.36245346 -81.43279266]]
(1440, 3)
Triangles:
[[   0   12   13]
 [   0   13    1]
 [   1   13   14]
 ...
 [1438   11 1439]
 [1439   11    0]
 [1439    0 1428]]
(2880, 3)
```

![Open3D_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936087/c3be772b-f7b7-46b3-ae36-56f1a2aef5fe.png)

また、上記のコードで可視化を行う前に下記のように`mesh.compute_vertex_normals()`を実行することで法線ベクトル(Surface Normal)の推定を行うことができることも合わせて抑えておくと良いです。

```python
import numpy as np
import open3d as o3d


knot_mesh = o3d.data.KnotMesh()
mesh = o3d.io.read_triangle_mesh(knot_mesh.path)

mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh])
```

・実行結果
![Open3D_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936087/eac4fc63-b0ab-4831-9171-eed20958458d.png)