我的编程空间,编程开发者的网络收藏夹
学习永远不晚

在PyQt5窗口中嵌入open3d窗口显示点云图形

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

在PyQt5窗口中嵌入open3d窗口显示点云图形

 本文方法来自:PYQT5内嵌外部exe程序(win7)_pyqt5嵌入外部窗口_这杯可乐有点甜的博客-CSDN博客

open3d在绘制点云等图形时,通常需要创建一个窗口。本文实现了将open3d创建的窗口显示在Qt窗口内,以便于后续通过Qt控件和槽函数调用open3d强大的绘图和处理功能。

运行结果如下图所示:

 

实现过程:

1.首先,导入需要的库:

import sysimport open3d as o3dfrom PyQt5.QtWidgets import QApplication,QMainWindow,QWidgetfrom PyQt5.QtGui import QWindowfrom PyQt5.QtCore import QTimerimport win32gui

其中win32gui为Pywin32库。

2.设计界面:

用Qt Designer绘制界面,如图:

 保存并编译.ui文件,得到对应的.py文件。

3.嵌入窗口:

新建一个python文件,继承刚刚所写的界面的类。

创建一个open3d的Visualizer类的实例vis,并创建窗口:

class MainWindow(QMainWindow):    def __init__(self,parent=None):        super(MainWindow, self).__init__(parent)        self.ui = Ui_display_test.Ui_MainWindow()        self.ui.setupUi(self)        self.vis = o3d.visualization.Visualizer()        self.vis.create_window()        

添加断点,或者使用vis.run()使窗口保持显示,在Visual Studio安装目录的Community\Common7\Tools找到并打开Spy++,按Ctrl+F,将“查找程序工具”拖动到打开的open3d窗口上,如图:

得到窗体类名为GLFW30。

通过Pywin32和PyQt5.QtGui 找到这个类对应的窗口,并获得对应WinId:

        self.winid = win32gui.FindWindow('GLFW30',None)        self.sub_window = QWindow.fromWinId(self.winid)

创建WindowContainer,将窗口放入其中,在将WindowContainer添加到Qt布局中:

        self.displayer = QWidget.createWindowContainer(self.sub_window)        self.ui.grid_display.addWidget(self.displayer)

此时open3d窗口已经嵌入Qt窗口中。

4.加载点云,测试效果:

根据open3d文档,o3d.visualization.draw_geometries([pcd])方法可以用以下代码替代实现:

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()

因此,添加函数:

    def draw_test(self):        pcd = o3d.io.read_point_cloud(r'../material/bun000.pcd')    #点云路径        self.vis.add_geometry(pcd)        self.vis.run()

并在析构函数添加

self.vis.destroy_window()

5.修改为非阻塞显示方式:

上面的代码虽然能正常显示点云,但是由于vis.run()是阻塞方式运行的,所以在窗口关闭时destroy_window()并不能被执行,此时会导致GLFW一直报错,程序无法停止运行。

在open3d文档中,有:

代码的下一部分是本教程的核心。update_geometry通知vis相关的几何图形已经更新。最后,可视化器通过调用poll_eventsupdate_renderer渲染一个新帧。在任何for循环迭代之后,destroy_window将关闭窗口。

 将vis.run()替换为:

while True:        self.vis.poll_events()        self.vis.update_renderer()

实现的效果与vis.run()相同。

添加一个定时器,设置定时器为20毫秒,将这两行代码写到定时器信号对应的槽函数中:

    def __init__:        …………        self.clock = QTimer(self)        self.clock.timeout.connect(self.draw_update)        self.clock.start(20)        …………    def draw_update(self):        self.vis.poll_events()        self.vis.update_renderer()      

就实现了每20ms刷新一次显示,同时不阻塞程序运行。

完整代码:

display_test.ui:

 MainWindow          0    0    828    608          MainWindow                                              QLayout::SetDefaultConstraint                                                 0     0     828     26              

Ui_display_test.py,由display_test.ui编译生成:

# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'd:\personal programs\gradesign\CSDN文章用\display_test.ui'## Created by: PyQt5 UI code generator 5.15.4## WARNING: Any manual changes made to this file will be lost when pyuic5 is# run again.  Do not edit this file unless you know what you are doing.from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_MainWindow(object):    def setupUi(self, MainWindow):        MainWindow.setObjectName("MainWindow")        MainWindow.resize(828, 608)        self.centralwidget = QtWidgets.QWidget(MainWindow)        self.centralwidget.setObjectName("centralwidget")        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)        self.gridLayout.setObjectName("gridLayout")        self.horizontalLayout = QtWidgets.QHBoxLayout()        self.horizontalLayout.setObjectName("horizontalLayout")        self.grid_display = QtWidgets.QGridLayout()        self.grid_display.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)        self.grid_display.setObjectName("grid_display")        self.horizontalLayout.addLayout(self.grid_display)        self.horizontalLayout.setStretch(0, 3)        self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)        MainWindow.setCentralWidget(self.centralwidget)        self.menubar = QtWidgets.QMenuBar(MainWindow)        self.menubar.setGeometry(QtCore.QRect(0, 0, 828, 26))        self.menubar.setObjectName("menubar")        MainWindow.setMenuBar(self.menubar)        self.statusbar = QtWidgets.QStatusBar(MainWindow)        self.statusbar.setObjectName("statusbar")        MainWindow.setStatusBar(self.statusbar)        self.retranslateUi(MainWindow)        QtCore.QMetaObject.connectSlotsByName(MainWindow)    def retranslateUi(self, MainWindow):        _translate = QtCore.QCoreApplication.translate        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))

displaytest.py:

import sysimport open3d as o3dfrom PyQt5.QtWidgets import QApplication,QMainWindow,QWidgetfrom PyQt5.QtGui import QWindowfrom PyQt5.QtCore import QTimerimport win32guiimport Ui_display_testclass MainWindow(QMainWindow):    def __init__(self,parent=None):        super(MainWindow, self).__init__(parent)        self.ui = Ui_display_test.Ui_MainWindow()        self.ui.setupUi(self)        self.vis = o3d.visualization.Visualizer()        self.vis.create_window(visible=False)  #visible=False窗口不显示,避免启动时一闪而过        self.winid = win32gui.FindWindow('GLFW30',None)        self.sub_window = QWindow.fromWinId(self.winid)        self.displayer = QWidget.createWindowContainer(self.sub_window)        self.ui.grid_display.addWidget(self.displayer)        self.clock = QTimer(self)        self.clock.timeout.connect(self.draw_update)        self.clock.start(20)        self.draw_test()    def draw_test(self):        pcd = o3d.io.read_point_cloud(r'../material/bun000.pcd')    #点云路径        self.vis.add_geometry(pcd)        self.vis.update_geometry(pcd)            def draw_update(self):        self.vis.poll_events()        self.vis.update_renderer()          def __del__(self):        #self.clock.stop()      #这一行其实并不需要        self.vis.destroy_window()if __name__ == '__main__':    app = QApplication(sys.argv)    window = MainWindow()    window.show()    sys.exit(app.exec_())

来源地址:https://blog.csdn.net/baiice_lee/article/details/129967491

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

在PyQt5窗口中嵌入open3d窗口显示点云图形

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

怎么在PyQt5中设置窗口全屏显示

今天就跟大家聊聊有关怎么在PyQt5中设置窗口全屏显示,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。调用窗口的主程序如下起作用的是window.showFullScreen()这个方
2023-06-08

C#如何调用SDK采集图像并在Halcon窗口中显示

本篇内容主要讲解“C#如何调用SDK采集图像并在Halcon窗口中显示”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#如何调用SDK采集图像并在Halcon窗口中显示”吧!开发环境 VS
2023-07-05

C#调用海康工业相机SDK采集图像并在Halcon窗口中显示方式

这篇文章主要介绍了C#调用海康工业相机SDK采集图像并在Halcon窗口中显示方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-02-26

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录