如何在open3d.visualization.O3DVisualizer类中添加另一个面板或窗口?

0 投票
0 回答
20 浏览
提问于 2025-04-12 05:44

背景

我正在尝试为concept-graphs映射系统的映射脚本添加一个图形用户界面(gui)。现在代码看起来很乱,但你可以在这里查看

这个映射系统需要输入RGB图像、深度图像和位姿,然后逐步构建一个基于物体的3D地图,同时还编码了一些语义特征。我希望能够可视化整个地图构建的过程,这样我就可以在构建的同时检查地图和调试问题。

所以我查看了一些Python示例,发现multiple_windows.py这个示例似乎有我想要的功能,可以可视化物体的点云和边界框等。我可以做到这一点,到目前为止效果很好。

问题

问题是我还想显示更多信息。我希望在地图旁边的面板中看到:当前的RGB图像、当前的深度图像、当前的标注图像、当前的帧、当前的物体数量等等。

我希望它能像文档中的dense_slam_gui.py示例那样。

我尝试了很多方法,但似乎无法在o3d.visualization.O3DVisualizer中添加一个面板,也无法添加另一个窗口或其他可以同时更新的东西。如果不是同一个窗口也没关系,我只想在地图旁边的某个地方看到这些信息,这样可以帮助我改进映射系统。

我的代码

这里有一些相关的代码片段。

这是我创建应用程序的方式(如你所见,我尝试了添加另一个窗口或面板的各种方法,但到目前为止所有尝试都导致了一些错误)

def run(self):
    app = o3d.visualization.gui.Application.instance
    app.initialize()

    self.main_vis = o3d.visualization.O3DVisualizer(
        "Open3D - Multi-Window Demo")
    self.main_vis.add_action("Take snapshot in new window",
                             self.on_snapshot)
    self.main_vis.add_action("Pause/Resume updates", lambda vis: self.toggle_pause())
    self.main_vis.set_on_close(self.on_main_window_closing)
    
    app.add_window(self.main_vis)
    # app.add_window(self.images_window)
    
    # # Setup the secondary window for images
    # # self.setup_image_display_window()
    # # self.image_window = app.create_window("RGB and Depth Images", 640, 480)
    # self.image_window = gui.Application.instance.create_window("RGB and Depth Images", 640, 480)
    # # self.image_window.create_window()
    # # self.image_window = o3d.visualization.Visualizer("RGB and Depth Images", 640, 480)
    # self.layout = o3d.visualization.gui.Vert(0, o3d.visualization.gui.Margins(10))
    # self.image_window.add_child(self.layout)

    # # Create image widgets
    # self.rgb_widget = o3d.visualization.gui.ImageWidget()
    # self.depth_widget = o3d.visualization.gui.ImageWidget()

    # # Add image widgets to the layout
    # self.layout.add_child(self.rgb_widget)
    # self.layout.add_child(self.depth_widget)
    # app.add_window(self.image_window)

    self.snapshot_pos = (self.main_vis.os_frame.x, self.main_vis.os_frame.y)
    threading.Thread(target=self.update_thread).start()
    app.run()

这是我进行更新线程的方式:

    def update_thread(self):
        # This is NOT the UI thread, need to call post_to_main_thread() to update
        # the scene or any part of the UI.
        
        ... lots of code, basically the whole mapping script ...
        
            def my_update_cloud():                
                
                # Remove previous objects
                for obj_name in self.prev_obj_names:
                    self.main_vis.remove_geometry(obj_name)
                self.prev_obj_names = []
                
                # Remove previous bounding boxes
                for bbox_name in self.prev_bbox_names:
                    self.main_vis.remove_geometry(bbox_name)
                self.prev_bbox_names = []
                
                # Add the new objects and bounding boxes
                for obj_num, obj in enumerate(self.objects):
                    obj_label = f"{obj['curr_obj_num']}_{obj['class_name']}"
                    
                    obj_name = f"obj_{obj_label}"
                    bbox_name = f"bbox_{obj_label}"
                    
                    self.prev_obj_names.append(obj_name)
                    self.main_vis.add_geometry(obj_name, obj['pcd'])
                    
                    self.prev_bbox_names.append(bbox_name)
                    self.main_vis.add_geometry(bbox_name, obj['bbox'] )
                    
            if self.is_done:  # might have changed while sleeping
                break
            o3d.visualization.gui.Application.instance.post_to_main_thread(
                self.main_vis, my_update_cloud)

我想做的事情

首先,我只想能够更新显示当前的RGB和深度图像,也许还有当前的帧编号?我想象的效果是:

    def update_images(self):
        # Convert numpy images to Open3D images and update widgets
        o3d_rgb_image = o3d.geometry.Image(self.curr_image_rgb)
        o3d_depth_image = o3d.geometry.Image((self.curr_depth_array / self.curr_depth_array.max() * 255).astype(np.uint8))  # Example normalization

        self.rgb_widget.update_image(o3d_rgb_image)
        self.depth_widget.update_image(o3d_depth_image)
        
# and then in the main update thread loop I would do        
self.curr_image_rgb = image_rgb
self.curr_depth_array = depth_array
o3d.visualization.gui.Application.instance.post_to_main_thread(
    self.image_window, self.update_images())

我希望你能理解我想要实现的目标。如果有人能给我指个方向,我将非常感激。我已经在网上搜索并询问了很多,但都没有找到解决办法。

谢谢你们的时间和帮助。

0 个回答

暂无回答

撰写回答