Blender + Pythonでポイントクラウドを可視化する
はじめに
ポイントクラウドデータをいい感じに可視化したい. matplotlibでも3次元データのscatterを描くことができるが,以下のような感じでいまいちな見た目になってしまう.
もうちょっといい感じの図が描きたい.たとえはこんな感じのやつ. 調べてみると,blenderでpythonが使えるらしいので,blenderなんもわからんけどやってみる. データはここで使われているShapenetの一部を用いた.
環境
ちょっと調べてでてくるスクリプトは動かないことが多かった(特にライト周り). 今使っているバージョン付近で大きめのアップデートがあったのか,blender自体がそういうアップデートの方針なのかわからないが,使っているバージョンによっては以下のスクリプトは動かないので注意.
Blenderのインストール
blenderはaptでもインストールできるが,最新版ではなかったのでsnapdというやつを使ってみることにした. 一般にパッケージ管理ソフトを複数混ぜるのは良くない気がするので,あまり良くない方法かもしれない.
sudo apt install snapd sudo snap install blender
terminalから
blender
で起動できる.
スクリプト
Blenderの中のScriptingタブからテキストエディタを開くことができる. Blenderから実行するpythonからはbpyというモジュールを使うことができ,これを使ってblenderの中のオブジェクトやカメラなどを操作できる. 全体はここに置いた.
オブジェクトの作成
ポイントクラウドを可視化するために,ポイントクラウドの各点に球を配置する. これは以下の手順でできる.
- 各位置にプリミティブを配置する.
- プリミティブの大きさを変更する.
- マテリアルを設定し,色を指定する.
プリミティブにはcubeやconeなど色々あるが,今回はuv_sphereを使う.
bpy.ops.mesh.primitive_uv_sphere_add(location=(x, y, z))
大きさの変更はオブジェクトを選択してスケールを変更することでできる. このあたりはかなりGUIをpythonで操作している感じがある. bpy.context.object で作成したばかりのオブジェクト(選択済みになっているもの)を取得できる. 選択したオブジェクトのスケールを変更することで,球の大きさを変更できる.
sphere = bpy.context.object sphere.scale = (0.02, 0.02, 0.02)
最後にマテリアルを追加することで,球の色を変更する. この機能を使うと,金属にするとか,水滴にするとかができる(と思う)が,今回は色を変更するだけ.
mat = bpy.data.materials.new("BLUE") mat.diffuse_color = (.33, .43, .95, 1) # RGBA sphere.data.materials.append(mat)
照明の配置
前述の通り、検索して出てくる多くのスクリプトが動かなかった。 これを参考にして,4方位から照らすようにした.
light_data = bpy.data.lights.new(name="light", type='AREA') light_data.energy = 500 light_object = bpy.data.objects.new(name="light", object_data=light_data) bpy.context.collection.objects.link(light_object) bpy.context.view_layer.objects.active = light_object light_object.location = loc light_object.rotation_euler = rot
その他
カメラの配置はblender上で頑張って操作して決めた. renderのオプションなどは呪文として書いた.よくわかってない. 雰囲気的に床があったほうが良さそうだったので,適当に巨大な板を下に置いた.
bpy.ops.mesh.primitive_plane_add(location=(0, 0, -1)) plane = bpy.context.object plane.scale = (100, 100, 1)
ということで以下のようなものを書いた.
実行
Blenderの中から実行しても良いし,コマンドラインから実行してもよい. jupyter notebookの中からも実行できるらしいが,まだやっていない (おそらく/snap/blender/33/2.80/python以下にipythonを入れればできそう).
コマンドラインから実行する場合は以下.
blender --python visualize_points_blender.py
--backgroundオプションをつけるとbackgroundで実行できるらしいが,セグフォでうまくできなかった.
実行すると以下のような図を得る.
まとめ
Blenderをpythonから使ってポイントクラウドを可視化した. GPUが弱いからか,1000点ぐらいのポイントクラウドを可視化するのに3分ぐらいかかっている. いい感じの図を作るセンスがほしい.
参考
- https://www.shapenet.org/
- A Scalable Active Framework for Region Annotation in 3D Shape Collections
- [1707.02392] Learning Representations and Generative Models for 3D Point Clouds
- BlenderのプリミティブオブジェクトをPythonで操作する -- PythonによるBlender 3DCGモデリング(2) --
- blugjpまとめサイト - dataとcontextとopsについて
- rendering - Can you add a light source in blender using python - Stack Overflow