引#
以下の図のように、メッシュモデル(およびそれのワールド座標系でのポーズ)が与えられており、指定されたカメラポーズでレンダリングされたカラー付きポイントクラウドデータを取得したいというアプリケーションがあります。
私のアプリケーションは、予測された既知のポーズのメッシュと実際の観測されたポイントクラウドをスケール付きで対応付けることです。メッシュの対応する領域のポイントクラウドを先にレンダリングしてから対応付けることで、遮蔽がある場合でも精度が向上すると考えています。
関連#
- How to capture depth image from a point cloud? · Issue #1152 · isl-org/Open3D · GitHub 既知のポイントクラウドをレンダリングするために、
open3d
のcapture_depth_float_buffer
関数を使用します。ただし、どのようにポイントクラウドに再投影するかについては関心がありません。私の検証によると、後続のステップが重要です。 - 3d - How do I generate a partial view of a mesh as a point cloud in Python? - Stack Overflow 同じ問題で、
open3d
のcapture_screen_image
およびcapture_depth_image
関数を使用します。この方法では、離散化された深度画像(0〜255)が保存されるため、スケールが完全に失われます。また、これらの関数のカメラパラメータとcreate_from_rgbd_image
を使用してポイントクラウドを投影する際のカメラパラメータが一致しないため、変形が発生します。 - 私は
capture_depth_float_buffer
とcreate_from_rgbd_image
を使用して再投影テストを行いましたが、スケールと変形の問題が同様に存在することがわかりました。
解決策#
open3d
のcapture_depth_point_cloud
を使用して直接レンダリングします。
def render_mesh_depth(mesh, depth):
center_mesh = np.mean(np.array(mesh.vertices), axis=0)
depth_data_center = np.mean(depth_data, axis=0)
mesh.vertices = o3d.utility.Vector3dVector(np.array(mesh.vertices) - center_mesh + depth_data_center)
# カメラのポーズを設定する
camera_pose = np.array([
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
])
# レンダラーとレンダリングオプションを作成する
vis = o3d.visualization.Visualizer()
vis.create_window(visible=False) # 見えないレンダリングウィンドウを作成する
vis.add_geometry(mesh)
# カメラパラメータとビューポートを設定する
ctr = vis.get_view_control()
cam_params = ctr.convert_to_pinhole_camera_parameters()
cam_params.extrinsic = camera_pose
ctr.convert_from_pinhole_camera_parameters(cam_params)
# 深度画像をレンダリングする
vis.capture_depth_point_cloud("o3d_tmp.ply", do_render=True, convert_to_world_coordinate=True)
vis.destroy_window()
# 深度画像からポイントクラウドを生成する
pcd = o3d.io.read_point_cloud("o3d_tmp.ply")
os.remove("o3d_tmp.ply")
return pcd
途中でopen3d
のバグに遭遇しました Visualizer.get_view_control() gives a copy. · Issue #6009 · isl-org/Open3D · GitHub。open3d
のバージョン0.17.0
では、get_view_control
関数で取得したview_control
は機能しません。バージョンを0.16.0
に変更すると正常に動作します。
追加#
現時点では、一時ファイルに保存してから読み込み、削除する必要があります。capture_depth_float_buffer
を使用するとこの問題は発生しませんが、スケールと変形の問題があります。レンダリングと再投影に使用されるカメラパラメータが一致しない可能性があると思われます。VisualizerRender.cppのソースコードを参考に解決策を考えることができます。