本日はOpen3Dを用いて、3D点群の法線ベクトルを計算するプログラムを紹介したいと思います。
Open3Dの環境構築の関しては、以下の記事をご覧ください。
Open3Dによる点群の法線推定
メッシュ(ポリゴン)ではない3D点群が法線(ベクトル)を持つのかと疑問に思われた方もいるかもしれません。
一般に3D点群の点の法線は、各点に接する平面を推定し、その平面が持つ法線ベクトルを計算することで計算が行われます。
よくある手法は、ある点Aの法線ベクトルを求めるために、点Aの周囲の数十点をK近傍法などに基づいて抽出し、この点集合から点A周辺の面形状を推定し、点Aの法線ベクトルを算出するというものです。
3D点群データの中で、点の周囲の面形状も考慮した解析を行いたいような場合においては、点に法線ベクトルを持たせることが重要になってきます。
Open3Dでは、点群を入力に3D点群を推定する関数が用意されていますので、これを使って点群の法線を推定してみましょう。
3D点群データセット
今回は以下のG-PCDデータセットのポイントクラウドを用いて実験を行いたいと思いますので、もし試したい方がいましたら以下からダウンロードください。
外部サイト:G-PCD: Geometry Point Cloud Dataset ‒ MMSPG ‐ EPFL
Bunny、Cube、Sphere、Dragon、Vaseの色無し3D点群が提供されています。今回はこちらの3D点群ファイル(PLY形式)をOpen3Dで表示してみましょう。
3D点群の法線推定プログラム
環境
- OS:Windows 10
- Python 3.6.10
- Open3D ver. 0.10.0.1
ソースコード
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np
import open3d as o3d
if __name__ == "__main__":
# Loading point cloud
print("Loading point cloud")
ptCloud = o3d.io.read_point_cloud("G-PCD\dragon.ply")
# Estimation of normal vector of points
ptCloud.estimate_normals(
search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.1, max_nn=30))
# Visualization
o3d.visualization.draw_geometries([ptCloud], point_show_normal=True)
# Checking normal vectors
print(np.asarray(ptCloud.normals))
print(np.asarray(ptCloud.normals[0]))
# Saving point cloud
o3d.io.write_point_cloud("output.ply", ptCloud)
コードの解説
点の法線推定
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Estimation of normal vector of points
ptCloud.estimate_normals(
search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.1, max_nn=30))
上記の箇所で点の法線推定を行っています。
リファレンスによると、estimate_normals関数は、法線を計算したい点の隣接する点を見つけ、共分散分析に基づき主軸を推定することで、法線ベクトルを推定するとのことです。
radiusは検索範囲、max_nnは考慮する近傍の最大点数とのことです。おそらく値を大きくした方が法線推定精度は高まりそうですが、計算時間とのトレードオフになりそうです。
点の法線の表示
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Visualization
o3d.visualization.draw_geometries([ptCloud], point_show_normal=True)
上記の箇所で、点群とその法線を表示することができます。
ポイントは、point_show_normal=Trueの部分で、ここがFalseの場合には法線ベクトルは表示されず、点群のみが表示されます。
法線ベクトルの数値へのアクセス
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Checking normal vectors
print(np.asarray(ptCloud.normals))
print(np.asarray(ptCloud.normals[0]))
法線ベクトルはptCloud.normalsの中に保存されます。点数×3(x,y,z)の配列となっており、上記のコードの通り配列としてアクセスすることが可能です。
法線ベクトル推定結果
プログラムを実行すると、以下のように黒の線で法線ベクトルの方向が表示されました。ほぼサーフェスに対して垂直になるように法線が表示されていて、まずまず法線推定精度は高そうです。

まとめ
本日はOpen3Dを用いて、点の法線ベクトルを推定する方法を紹介しました。Open3Dを使うことで、非常に容易に点の法線ベクトルを推定できることがわかります。
