【Python_点群処理】点群データをメッシュに変換してプロットする方法
はじめに
今回は点群からメッシュを作成して可視化してみます。
メッシュの作成方法はいくつかありますが、今回は点群からドロネー三角形を計算してメッシュを生成します。
ドロネー三角形の詳細については改めて記事を書く予定です。
ドロネー三角形の計算はScipyやmatplotlibで用意されています。
どちらも点群のx、y座標をもとにドロネー三角を計算し、面を形成する3点のインデックスが配列として返されます。np.array([面の数,3])
点群データ test_dataのドロネー三角形を計算して、返ってきた配列の一つが [1,28,12]であった場合、test_dataの1番目と28番目と12番目の点を繋ぐことで面を一つ作ることができます。
この記事では
- matplotlibとscipyを使って点群からメッシュを作成する方法
- Open3Dでメッシュをプロット
- k3dでメッシュをプロット
- plotlyでメッシュをプロット
する方法を紹介します。
今回使用するデータは以下のような2次元サイン波の点群です。
点群データからメッシュを作成する方法
matplotlibを使う場合
from matplotlib.tri import Triangulation
tri_matplot = Triangulation(test_data[:,0], test_data[:,1])
面を生成するインデックスはtri_matplot.triangles
に入っており、以下のような中身になっています。
# tri_matplot.trianglesのOutput
array([[9621, 2021, 4857],
[4857, 2021, 8940],
[ 90, 7348, 2851],
...,
[9874, 781, 7234],
[3010, 7612, 7234],
[7234, 781, 3010]], dtype=int32)
scipyを使う場合
from scipy.spatial import Delaunay
xy_catalog = []
for point in test_data:
xy_catalog.append([point[0], point[1]])
tri_scipy = Delaunay(np.array(xy_catalog))
同様に面を生成するインデックスはtri_scipy.simplices
に入っており、以下のような中身になっています。
# tri_scipy.simplicesのOutput
array([[8131, 4444, 5209],
[4444, 8131, 807],
[8131, 4881, 83],
...,
[3166, 6907, 464],
[5191, 3166, 9884],
[6907, 3166, 5191]], dtype=int32)
Open3Dでメッシュをプロットする方法
元の点群データと面の情報をOpen3Dの形に変換してメッシュをプロットします。
下記結果ではワイヤーフレームを表示しています。
import open3d as o3d
surface = o3d.geometry.TriangleMesh()
surface.vertices = o3d.utility.Vector3dVector(test_data)
surface.triangles = o3d.utility.Vector3iVector(tri_matplot.triangles)
# surface.triangles = o3d.utility.Vector3iVector(tri_scipy.simplices)
o3d.visualization.draw_geometries ([surface], mesh_show_wireframe=True)
K3Dでメッシュをプロットする方法
K3Dを使ってメッシュをプロットします。
点群データはk3d.points()を使いましたが、メッシュを表示する際にはk3d.mesh()を使用します。
import k3d
plot = k3d.plot(camera_auto_fit=True)
point_size=0.1
plot += k3d.points(test_data, point_size=point_size, shader="3d", color = 0xff0000)
plot += k3d.mesh(test_data, tri_matplot.triangles)
# plot += k3d.mesh(test_data, tri_scipy.simplices)
plot.display()
上がワイヤーフレーム非表示、下がワイヤーフレームを表示した時の結果です。
plotlyでメッシュをプロットする方法
plotlyを使ってメッシュを表示します。綺麗に表示するためにz軸や表示サイズなどを設定しています。そのためopen3dやK3Dと比べて使い勝手は良くない印象です。
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Mesh3d(x=test_data[:,0], y=test_data[:,1], z=test_data[:,2],
i= tri_matplot.triangles[:,0], j= tri_matplot.triangles[:,1], k=tri_matplot.triangles[:,2])
)
# fig.add_trace(go.Mesh3d(x=test_data[:,0], y=test_data[:,1], z=test_data[:,2],
# i= tri_scipy.simplices[:,0], j= tri_scipy.simplices[:,1], k= tri_scipy.simplices[:,2]))
fig.update_layout(scene = dict(xaxis= dict(range=[test_data[:,0].min(), test_data[:,0].max()],),
yaxis= dict(range=[test_data[:,1].min(), test_data[:,1].max()],),
zaxis= dict(range= [test_data[:,2].min(), test_data[:,2].max()+20],)),
width=700,
margin=dict(r=20, l=10, b=10, t=10))
fig.show()
ディスカッション
コメント一覧
まだ、コメントがありません