保存当前相机视角和恢复当前相机视角
想要实现 open3d 提供的可视化接口 ctrl+c 复制视角,ctrl+v 恢复视角的功能
尝试过很多方法,找到了最简单的方法 来自https://github.com/isl-org/Open3D/issues/3627。
import numpy as np
import open3d as o3d
import open3d.visualization.gui as gui
from pickle import load, dump
ToGLCamera = np.array([
[1, 0, 0, 0],
[0, -1, 0, 0],
[0, 0, -1, 0],
[0, 0, 0, 1]
])
FromGLGamera = np.linalg.inv(ToGLCamera)
def model_matrix_to_extrinsic_matrix(model_matrix):
return np.linalg.inv(model_matrix @ FromGLGamera)
def create_camera_intrinsic_from_size(width=1024, height=768, hfov=60.0, vfov=60.0):
fx = (width / 2.0) / np.tan(np.radians(hfov)/2)
fy = (height / 2.0) / np.tan(np.radians(vfov)/2)
# fx = fy # not sure why, but it looks like fx should be governed/limited by fy
return np.array(
[[fx, 0, width / 2.0],
[0, fy, height / 2.0],
[0, 0, 1]])
def save_view(vis, fname='saved_view.pkl'):
try:
model_matrix = np.asarray(vis.scene.camera.get_model_matrix())
extrinsic = model_matrix_to_extrinsic_matrix(model_matrix)
width, height = vis.size.width, vis.size.height
intrinsic = create_camera_intrinsic_from_size(width, height)
saved_view = dict(extrinsic=extrinsic, intrinsic=intrinsic, width=width, height=height)
with open(fname, 'wb') as pickle_file:
dump(saved_view, pickle_file)
except Exception as e:
print(e)
def load_view(vis, fname="saved_view.pkl"):
try:
with open(fname, 'rb') as pickle_file:
saved_view = load(pickle_file)
vis.setup_camera(saved_view['intrinsic'], saved_view['extrinsic'], saved_view['width'], saved_view['height'])
# Looks like the ground plane gets messed up, no idea how to fix
except Exception as e:
print("Can't find file", e)
def main():
gui.Application.instance.initialize()
vis = o3d.visualization.O3DVisualizer("Demo to Load a Camera Viewpoint for O3DVisualizer", 1024, 768)
gui.Application.instance.add_window(vis)
vis.point_size = 8
vis.show_axes = True
# Add saving and loading view
vis.add_action("Save Camera View", save_view)
vis.add_action("Load Camera View", load_view)
# Create Random Geometry
pcd = o3d.io.read_point_cloud('D:\W_M_NIUST\WM_Project\MyProject/scene0423_00_crop_0.ply')
# pc = np.random.randn(100, 3) * 0.5
# pcd = o3d.geometry.PointCloud()
# pcd.points = o3d.utility.Vector3dVector(pc)
vis.add_geometry("Random Point Cloud", pcd)
vis.reset_camera_to_default()
gui.Application.instance.run()
if __name__ == "__main__":
main()
在o3d>0.16版本中,setup_camera()函数多了一个参数 boundingbox,我们改写如下
vis.setup_camera(intrinsic, extrinsic, width, height, pcd.get_axis_aligned_bounding_box())