通过draw_geometries
和draw_geometries_with_custom_animation
函数可以很方便的使用Open3d的可视化功能,所有的都可以通过GUI去完成。在可视化窗口按 h 键,可以看到相关的帮助信息。详细的请参考:可视化。
本教程重点介绍了更高级的可视化功能,以自定义可视化窗口的行为。请参考/Python/Advanced/customized_visualization.py实现以下例程。
def custom_draw_geometry(pcd):
# The following code achieves the same effect as:
# o3d.visualization.draw_geometries([pcd])
vis = o3d.visualization.Visualizer()
vis.create_window()
vis.add_geometry(pcd)
vis.run()
vis.destroy_window()
这个函数实现了与draw_geometries
函数同样的功能。
Visualizer
类具有几个变量,比如ViewControl
和RenderOption
。以下函数读取储存在json文件中的预定义的RenderOption
。
def custom_draw_geometry_load_option(pcd):
vis = o3d.visualization.Visualizer()
vis.create_window()
vis.add_geometry(pcd)
vis.get_render_option().load_from_json("../../TestData/renderoption.json")
vis.run()
vis.destroy_window()
要去改变相机的视角,必须先获取可视化控件的实例。使用change_field_of_view
函数改变视场。
def custom_draw_geometry_with_custom_fov(pcd, fov_step):
vis = o3d.visualization.Visualizer()
vis.create_window()
vis.add_geometry(pcd)
ctr = vis.get_view_control()
print("Field of view (before changing) %.2f" % ctr.get_field_of_view())
ctr.change_field_of_view(step=fov_step)
print("Field of view (after changing) %.2f" % ctr.get_field_of_view())
vis.run()
vis.destroy_window()
视角可以设置为[5,90]度。注意函数change_field_of_view
在当前的FoV下添加了指定的FoV。默认的可视化具有60°的FoV。调用以下代码。
custom_draw_geometry_with_custom_fov(pcd, 90.0)
这将会在默认的60°上添加90°的FoV,当超过最大的FoV时,FoV将会被设置为90°。
下面的代码
custom_draw_geometry_with_custom_fov(pcd, -90.0)
将会把FoV设置为5°,因为60 - 90 = -30低于5°。
def custom_draw_geometry_with_rotation(pcd):
def rotate_view(vis):
ctr = vis.get_view_control()
ctr.rotate(10.0, 0.0)
return False
o3d.visualization.draw_geometries_with_animation_callback([pcd],
rotate_view)
函数draw_geometries_with_animation_callback
将Python的回调函数rotate_view
注册为主循环的空闲函数。当可视化窗口处于空闲状态的时候,他将沿着X轴旋转。这样就定义了动画行为。
def custom_draw_geometry_with_key_callback(pcd):
def change_background_to_black(vis):
opt = vis.get_render_option()
opt.background_color = np.asarray([0, 0, 0])
return False
def load_render_option(vis):
vis.get_render_option().load_from_json(
"../../TestData/renderoption.json")
return False
def capture_depth(vis):
depth = vis.capture_depth_float_buffer()
plt.imshow(np.asarray(depth))
plt.show()
return False
def capture_image(vis):
image = vis.capture_screen_float_buffer()
plt.imshow(np.asarray(image))
plt.show()
return False
key_to_callback = {}
key_to_callback[ord("K")] = change_background_to_black
key_to_callback[ord("R")] = load_render_option
key_to_callback[ord(",")] = capture_depth
key_to_callback[ord(".")] = capture_image
o3d.visualization.draw_geometries_with_key_callbacks([pcd], key_to_callback)
回调函数也能够在按键事件产生的时候注册。上面的脚本注册了四个按键。比如按下K键将会把背景设置为黑色。
def custom_draw_geometry_with_camera_trajectory(pcd):
custom_draw_geometry_with_camera_trajectory.index = -1
custom_draw_geometry_with_camera_trajectory.trajectory =\
o3d.io.read_pinhole_camera_trajectory(
"../../TestData/camera_trajectory.json")
custom_draw_geometry_with_camera_trajectory.vis = o3d.visualization.Visualizer(
)
if not os.path.exists("../../TestData/image/"):
os.makedirs("../../TestData/image/")
if not os.path.exists("../../TestData/depth/"):
os.makedirs("../../TestData/depth/")
def move_forward(vis):
# This function is called within the o3d.visualization.Visualizer::run() loop
# The run loop calls the function, then re-render
# So the sequence in this function is to:
# 1. Capture frame
# 2. index++, check ending criteria
# 3. Set camera
# 4. (Re-render)
ctr = vis.get_view_control()
glb = custom_draw_geometry_with_camera_trajectory
if glb.index >= 0:
print("Capture image {:05d}".format(glb.index))
depth = vis.capture_depth_float_buffer(False)
image = vis.capture_screen_float_buffer(False)
plt.imsave("../../TestData/depth/{:05d}.png".format(glb.index),\
np.asarray(depth), dpi = 1)
plt.imsave("../../TestData/image/{:05d}.png".format(glb.index),\
np.asarray(image), dpi = 1)
#vis.capture_depth_image("depth/{:05d}.png".format(glb.index), False)
#vis.capture_screen_image("image/{:05d}.png".format(glb.index), False)
glb.index = glb.index + 1
if glb.index < len(glb.trajectory.parameters):
ctr.convert_from_pinhole_camera_parameters(
glb.trajectory.parameters[glb.index])
else:
custom_draw_geometry_with_camera_trajectory.vis.\
register_animation_callback(None)
return False
vis = custom_draw_geometry_with_camera_trajectory.vis
vis.create_window()
vis.add_geometry(pcd)
vis.get_render_option().load_from_json("../../TestData/renderoption.json")
vis.register_animation_callback(move_forward)
vis.run()
vis.destroy_window()
这个函数读取了相机轨迹,然后自定义了动画函数move_forward
以遍历相机轨迹。在这个函数中,彩色图像和深度图像分别使用Visualizer.capture_depth_float_buffer
和Visualizer.capture_screen_float_buffer
去捕获,然后保存成文件。
捕获的彩色图像序列
捕获的深度图像序列