Blender + Pythonでポイントクラウドを可視化する

はじめに

ポイントクラウドデータをいい感じに可視化したい. matplotlibでも3次元データのscatterを描くことができるが,以下のような感じでいまいちな見た目になってしまう.

f:id:ksknw:20191029190640p:plain

もうちょっといい感じの図が描きたい.たとえはこんな感じのやつ. 調べてみると,blenderpythonが使えるらしいので,blenderなんもわからんけどやってみる. データはここで使われているShapenetの一部を用いた.

環境

ちょっと調べてでてくるスクリプトは動かないことが多かった(特にライト周り). 今使っているバージョン付近で大きめのアップデートがあったのか,blender自体がそういうアップデートの方針なのかわからないが,使っているバージョンによっては以下のスクリプトは動かないので注意.

Blenderのインストール

blenderはaptでもインストールできるが,最新版ではなかったのでsnapdというやつを使ってみることにした. 一般にパッケージ管理ソフトを複数混ぜるのは良くない気がするので,あまり良くない方法かもしれない.

sudo apt install snapd 
sudo snap install blender

terminalから

blender

で起動できる.

スクリプト

Blenderの中のScriptingタブからテキストエディタを開くことができる. Blenderから実行するpythonからはbpyというモジュールを使うことができ,これを使ってblenderの中のオブジェクトやカメラなどを操作できる. 全体はここに置いた.

オブジェクトの作成

ポイントクラウドを可視化するために,ポイントクラウドの各点に球を配置する. これは以下の手順でできる.

  1. 各位置にプリミティブを配置する.
  2. プリミティブの大きさを変更する.
  3. マテリアルを設定し,色を指定する.

プリミティブにはcubeやconeなど色々あるが,今回はuv_sphereを使う.

bpy.ops.mesh.primitive_uv_sphere_add(location=(x, y, z))

大きさの変更はオブジェクトを選択してスケールを変更することでできる. このあたりはかなりGUIpythonで操作している感じがある. 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で実行できるらしいが,セグフォでうまくできなかった.

実行すると以下のような図を得る.

f:id:ksknw:20191029190609p:plain

まとめ

Blenderpythonから使ってポイントクラウドを可視化した. GPUが弱いからか,1000点ぐらいのポイントクラウドを可視化するのに3分ぐらいかかっている. いい感じの図を作るセンスがほしい.

参考