📝

Open3Dの視点のあれこれ(ViewControl編)

2024/02/26に公開

1. はじめに

「詳解 3次元点群処理 Pythonによる基礎アルゴリズムの実装」というとても良い本があるが、この本を読む前にいくつか必要だった前提知識

Open3Dを使っている人との情報交換用で間違っていることが書いてあったら是非教えていただけると助かります。

2. 基礎知識

2.1 Open3Dは右手系、左手系

  • Open3Dは右手系
  • デフォルトでは、X(赤/水平)、Y(緑/高さ)、Z(青/奥行き)となる。Zが高さになっているので注意する。

2.2 ViewControlの仕組み

Open3Dのカメラの取り扱い ViewControl編 に詳しく書かれている。(ありがとうございます) fovはまだよく理解できていない。(変えどころがわからない)

2.3 Coordinate Frame

Coordinate Frame (日本語だとなんだろう、座標枠?)
点群を表示するときに一緒に出すと良い。RGBの順で赤(R)がX,緑(G)がY,青(B)となっている。
なんとなく、XYZで、水平(X)、奥行き(Y)、高さ(Z)とイメージしたいところだが、Open3Dのデフォルトは高さがY(何か理由があるんだろうけどなんで?)

(あとで絵をつける)

2.4 単位ベクトル(Unit Vector)

frontとかで指定するのは、単位ベクトル(Unit Vector)で、ノルムが1(\sqrt{X^2 + Y^2 + Z^2} = 1) となるような値を指定する(と思う)、各要素の値は -1 ~ 1の範囲で xが1なら赤の先端、xが-1なら反対側を向くようになっている。x,z 45度なら、[0.71,0,0.71]で良いように思う。

..と思ったんだけど、X少し移動させるときは = [0.2,0.0,0.0]とかでノルムが1にはならないけどこれは考え方が間違えているのだろうか?

3. ViewControlを使った視点の制御

3.1 サンプルデータ

#!/usr/bin/env python

import open3d.data
import open3d as o3d
import numpy as np

# サンプルデータのファイルのパス(~/open3d_data/以下にデータがダウンロードされる)
bunny_path = open3d.data.BunnyMesh().path

# 点群として読み込む
point_cloud = o3d.io.read_point_cloud(bunny_path)

# 点群をnumpyのarrayとして取り出す
points = np.asarray(point_cloud.points)

# 最小値・最大値を求める。
x_min, y_min, z_min = np.min(points, axis=0)
x_max, y_max, z_max = np.max(points, axis=0)

# サイズを計測
size_x = x_max - x_min
size_y = y_max - y_min
size_z = z_max - z_min

# 座標の矢印を作成、大きさをZ軸の大きさに拡大する。
coordinate_frame = o3d.geometry.TriangleMesh.create_coordinate_frame(size=size_z)

# 移動する距離を計算、各軸の点群の最小値 + 寸法の半分 (0,0,0)が中心になるように
move_x = (x_min + size_x/2) * -1
move_y = (y_min + size_y/2) * -1
move_z = (z_min + size_z/2) * -1

# 移動用の行列を作成
# [1,0,0,x]
# [0,1,0,y]
# [0,0,1,z]
# [0,0,0,1]
move_matrix = np.eye(4)
move_matrix[:3, 3] = [move_x,move_y,move_z]

# 移動
point_cloud.transform(move_matrix)

3.2 デフォルト

o3d.visualization.draw_geometries([point_cloud, coordinate_frame])

デフォルト

以下 up=[0,0,0], front=[0,0,0]を変更してさまざまな視点から点群を表示する。

3.3 横

o3d.visualization.draw_geometries([point_cloud, coordinate_frame],
                                  lookat=[0,0,0],
                                  front=[0,0,-1],
                                  zoom=1,
                                  up=[0,1,0])

真後ろ

o3d.visualization.draw_geometries([point_cloud, coordinate_frame],
                                  lookat=[0,0,0],
                                  front=[1,0,0],
                                  zoom=1,
                                  up=[0,1,0])

X正

o3d.visualization.draw_geometries([point_cloud, coordinate_frame],
                                  lookat=[0,0,0],
                                  front=[-1,0,0],
                                  zoom=1,
                                  up=[0,1,0])

X反対

3.4 真上から

o3d.visualization.draw_geometries([point_cloud, coordinate_frame],
                                  lookat=[0,0,0],
                                  front=[0,1,0],
                                  zoom=1,
                                  up=[1,0,0])

真上からX

o3d.visualization.draw_geometries([point_cloud, coordinate_frame],
                                  lookat=[0,0,0],
                                  front=[0,1,0],
                                  zoom=1,
                                  up=[-1,0,0])

真上から-X

o3d.visualization.draw_geometries([point_cloud, coordinate_frame],
                                  lookat=[0,0,0],
                                  front=[0,1,0],
                                  zoom=1,
                                  up=[0,0,1])

真上からY

o3d.visualization.draw_geometries([point_cloud, coordinate_frame],
                                  lookat=[0,0,0],
                                  front=[0,1,0],
                                  zoom=1,
                                  up=[0,0,-1])

真上から-Z

3.5 真下から

o3d.visualization.draw_geometries([point_cloud, coordinate_frame],
                                  lookat=[0,0,0],
                                  front=[0,-1,0],
                                  zoom=1,
                                  up=[1,0,0])

真下から1

o3d.visualization.draw_geometries([point_cloud, coordinate_frame],
                                  lookat=[0,0,0],
                                  front=[0,-1,0],
                                  zoom=1,
                                  up=[-1,0,0])

真下から2

3.6 斜め

o3d.visualization.draw_geometries([point_cloud, coordinate_frame],
                                  lookat=[0,0,0],
                                  front=[0.71,0,0.71],
                                  zoom=1,
                                  up=[0,1,0])

005_真上から1

o3d.visualization.draw_geometries([point_cloud, coordinate_frame],
                                  lookat=[0,0,0],
                                  front=[0.577,0.577,0.577],
                                  zoom=1,
                                  up=[0,1,0])

デフォルト

o3d.visualization.draw_geometries([point_cloud, coordinate_frame],
                                  lookat=[0,0,0],
                                  front=[0.577,0.577,0.577],
                                  zoom=1,
                                  up=[1,0,0])

013_名前45度別バージョン

3.7 おかしな視点を設定した場合

o3d.visualization.draw_geometries([point_cloud, coordinate_frame],
                                  lookat=[0,0,0],
                                  front=[0,1,0],
                                  zoom=1,
                                  up=[0,1,0])

012_斜め45度

Discussion