以前に比べ、ポイントクラウドもスマートフォン等で手軽にスキャンできるようになったが、本格的にポイントクラウドを活用する場合、ノイズも多く含まれているため、データをうまく補正する作業が必要となります。
補正処理するためのツールとしては、MeshLab などが代表的であるが、何かのアプリケーションの一部として処理したい場合や、独自のアルゴリズムで補正処理したい場合には、MIT ライセンスでもある Open3D ライブラリの活用はとても有効だと思います。現時点での最新バージョンは、 0.12.0 ですが、TensorFlow や PyTorch 用の Open3D-ML といったオプション等も開発され、今後がますます楽しみです。但し、Open3D-ML を使いたい場合は自分でビルドする必要がありますが、 Linux 以外の環境では、ビルドにかなり苦労するため、本記事は基本機能のみの Open3D で行います。
Open3D のバージョンは、0.12.0 (古いバージョンだと書き方が異なるので注意)を 前提としています。
1. Open3D 公式サイト: http://www.open3d.org/
- 実行環境: Windows 10 , Python 3.7 ( Miniforge ※ Anaconda は、リポジトリの商用利用規約が変更されたため今後は Miniforge で Python 仮想環境をつくることをお勧めします。ちなみに、Mac の M1 チップに最適化された TensorFlow を使う場合なども、Miniforge を使うため、今後 Miniforge のシェアも増えるのではないかと思います。
- 3.8 以降も動作するが、Open3D 以外のライブラリの中には、まだ 3.7 以外対応していないものが多い為、3.7ではじめるのが無難です。
2. ソースコード: https://github.com/intel-isl/Open3D
- Open3D は、C++ など Python 以外でも扱えるが、Python とサポートしている関数名が
微妙に異なる部分も多い。そのため、example の中の Pythonコード は、とても参考になります。 - Google Colaboratory でも試すことはできるが、レンダリング等で一部制約があるため、とりあえずすぐに行いたい場合は、ローカル環境で行うほうが Open3D の入門としては苦労がないように思います。
3. インストール方法:
- conda create -n open3d python=3.7 のようにして、Open3D 専用の仮想環境を準備します。
- conda activate open3d
- conda install -c open3d-admin open3d
4. PCD 形式のポイントクラウドの読み込み
とりあえず、ポイントクラウドの標準的なフォーマットである PCD ファイルとして、Open3D の example 内にあるテストデータを読み込む場合は、次のようになります。
pcd0 = o3d.io.read_point_cloud("../test_data/fragment.pcd")
5. テスト用ポイントクラウドの読み込み( NumPy を使用する方法について)
さきほどの例は PCD フォーマットの場合ですが、実践的には、独自にスマホでポイントクラウドをスキャンするアプリを開発した場合など、PCD 形式での出力が難しい場合があります。そんなとき、NumPy を用いた読み込み方法を知っておくと様々なフォーマットに柔軟に対応できるため、ここでその一例を紹介します。
以下は、float32 形式で、x,y,zの座標値が float32 のバイナリで作られたファイルから Open3D で扱えるようにするための例です。とりあえず、NumPy で取り込むのがベストです。取り込む際は、例のように、データタイプも指定し簡単にパースすることができます。取り込んだあと、reshape している理由については後ほど説明します。
import numpy as np
fn = 'ファイル名'
p0 = (np.fromfile(fn, dtype='f')).reshape(-1, 3)
ちなみに、dtype の f は float32(4バイト)の意味であるが, d と指定した場合は、float64(8バイト)毎にパースされます。また、取り込むデータがビックエンディアンである場合は、dtype='>f' のようにします。そのほか、区切り文字の指定など、たいていのデータは NumPy で処理できます。
NumPy 形式で取り込んだあとは、Open3D のインスタンスを作り、次のようにセットします。
pcd0 = o3d.geometry.PointCloud()
pcd0.points = o3d.utility.Vector3dVector(p0[~np.isnan(p0).any(axis=1)])
Open3D では、ポイントクラウドは Vector3d 形式である必要があるため、事前に reshape(-1,3) を行い、それを、utility を使って変換したものをセットします。なお、上記の例では、p0 の中に、nan が含まれている場合があったため x,y,z いずれかが nan であるデータは除外した上で取り込んでいます。
最後に、これを表示したい場合は、次のように記述する。表示したい Open3D オブジェクトを [ ] 内に列挙すると複数のポイントクラウドを重ねて表示することもできます。
o3d.visualization.draw_geometries([pcd0])
続きは、次回。