起因
MMDetection3D可视化使用Open3D写的,它每显示一帧数据,都要重新关闭上一帧图形窗口,当前帧再重新生成一个,非常慢,严重影响浏览dataset的效率。
再加上自己有浏览一个文件夹下多个点云的需求,所以学习了下Open3D的官方文档,打算自己实现试一下。
功能很简单,就是逐帧显示一个文件夹下的所有点云,用按键控制切换上一帧和下一帧。
这个例子来源于Open3D官方Visualization教程中的Non-blocking visualization,同时又参考了
https://github.com/isl-org/Open3D/issues/715和https://stackoverflow.com/questions/65112433/open3d-how-to-update-point-cloud-during-window-running。
本来觉得应该会挺快,结果遇到了两个大坑。
- 官方给的例子中,用的是vis.update_geometry(pcd),亲测不行,点云不刷新,要用vis.add_geometry(pcd),这个地方坑了我了好久;
- register_key_callback(key, key_callback_function)中的key,必须是大写的,小写的按键callback按下收不到。
代码如下:
def show_pointcloud_dir(file_path):
g_idx = 0
vis = o3d.visualization.VisualizerWithKeyCallback()
filelist = [os.path.join(file_path, f) for f in os.listdir(file_path)]
def show_pointcloud(vis):
nonlocal g_idx
points = np.fromfile(filelist[g_idx], np.float32).reshape(-1, 4) # xyzi
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points[:, :3])
# point_color = (0.5, 0.5, 0.5)
# points_colors = np.tile(np.array(point_color), (points.shape[0], 1))
# pcd.colors = o3d.utility.Vector3dVector(points_colors)
vis.clear_geometries()
vis.add_geometry(pcd) # fuck bug, vis.update_geometry(pcd)没有用!
vis.update_renderer()
vis.poll_events()
def key_forward_callback(vis):
nonlocal g_idx
g_idx += 1
if g_idx >= len(filelist):
g_idx = len(filelist) - 1
show_pointcloud(vis)
return True
def key_back_callback(vis):
nonlocal g_idx
g_idx -= 1
if g_idx < 0:
g_idx = 0
show_pointcloud(vis)
return True
vis.create_window()
vis.get_render_option().point_size = 2 # set points size
vis.register_key_callback(ord(' '), key_forward_callback) # space
vis.register_key_callback(ord('B'), key_back_callback) # fuck bug, 字母必须是大写!
vis.run()
if __name__ == "__main__":
show_pointcloud_dir('pointcloud_path')
一个有用的tip
显示出点云后,按h键后在命令行会打印出各种操作提示,其中按下0,1,2,3,4可以根据xyz改变点云颜色,挺有用的。
其他两个相关工具
Web visualizer and Jupyter
通过浏览器远程看dataset也很有用。
Open3D-ML
这是个专门用于机器学习的库,demo非常炫酷,用到自己dataset上应该很有用。
共勉!