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

这篇具有很好参考价值的文章主要介绍了在PyQt5窗口中嵌入open3d窗口显示点云图形。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

运行结果如下图所示:

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

 

实现过程:

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

import sys
import open3d as o3d
from PyQt5.QtWidgets import QApplication,QMainWindow,QWidget
from PyQt5.QtGui import QWindow
from PyQt5.QtCore import QTimer
import win32gui

其中win32gui为Pywin32库。

2.设计界面:

用Qt Designer绘制界面,如图:

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

 保存并编译.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窗口上,如图:在PyQt5窗口中嵌入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:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>828</width>
    <height>608</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="0">
     <layout class="QHBoxLayout" name="horizontalLayout" stretch="3">
      <item>
       <layout class="QGridLayout" name="grid_display">
        <property name="sizeConstraint">
         <enum>QLayout::SetDefaultConstraint</enum>
        </property>
       </layout>
      </item>
     </layout>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>828</width>
     <height>26</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

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, QtWidgets


class 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:文章来源地址https://www.toymoban.com/news/detail-461173.html

import sys
import open3d as o3d
from PyQt5.QtWidgets import QApplication,QMainWindow,QWidget
from PyQt5.QtGui import QWindow
from PyQt5.QtCore import QTimer
import win32gui
import Ui_display_test

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

到了这里,关于在PyQt5窗口中嵌入open3d窗口显示点云图形的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python: 用open3D库,连续多帧显示点云(查看localization pose的好坏)

    连续多帧显示点云,需要 点云文件 和 定位信息(IMU惯导信息),我这里是从bag包里面自己解析出来的定位信息,因为是自己写的节点,所以直接从代码里面跑出来的,不是ros官方定义的,所以没有用官方给出的方法 总体思路: 将每一帧点云和旋转矩阵进行 时间对齐 -----

    2023年04月11日
    浏览(46)
  • 第二章 python-pcl、open3d读取、显示pcd、bin等格式点云数据

    点云数据实际上就是许多组点的集合,每个点由{x,y,z}组成。当然理论上的只包含有3D坐标。 实际激光雷达获取的点云数据还会包含强度、反射率等等。但我们一般只用提取{x,y,z}来处理即可。 点云数据相比于其他传感器数据的核心优势就是在于 精准的深度信息。可惜获取具体

    2024年01月16日
    浏览(61)
  • 基于Open3D的点云处理17-Open3d的C++版本

    http://www.open3d.org/docs/latest/cpp_api.html http://www.open3d.org/docs/latest/getting_started.html#c http://www.open3d.org/docs/release/cpp_project.html#cplusplus-example-project https://github.com/isl-org/open3d-cmake-find-package https://github.com/isl-org/open3d-cmake-external-project https://github.com/isl-org/Open3D/releases Note: -DBUILD_SHARED_LIBS

    2024年02月09日
    浏览(62)
  • open3d点云平移

    功能简介 open3d中点云的平移函数为:pcd.translate((tx, ty, tz), relative=True)。当relative为True时,(tx, ty, tz)表示点云平移的相对尺度,也就是平移了多少距离。当relative为False时,(tx, ty, tz)表示点云中心(质心)平移到的指定位置。质心可以坐标可以通过pcd.get_center()得到。 代码

    2024年01月22日
    浏览(80)
  • Open3D点云处理

    Open3D is an open-source library that supports rapid development of software that deals with 3D data. The Open3D frontend exposes a set of carefully selected data structures and algorithms in both C++ and Python. The backend is highly optimized and is set up for parallelization. Open3D是一个支持3D数据处理软件快速开发的开源库,在前端提供

    2023年04月17日
    浏览(57)
  • Open3d点云对象详解

    PointCloud 是open3d中用于点云处理的类,封装了包括几何变换、数据滤波、聚类分割等一系列实用算法。如无特别说明,本例中所有例程均基于斯坦福兔子的点云模型,下载地址:斯坦福标准模型 读取和清除点云 一般点云数据的读取方法属于 open3d.io 的内容,但点云类也提供了

    2023年04月19日
    浏览(87)
  • Open3D点云数据处理(一):VSCode配置python,并安装open3d教程

    专栏地址:https://blog.csdn.net/weixin_46098577/category_11392993.html 在很久很久以前,我写过这么一篇博客,讲的是open3d点云处理的基本方法。👇 当时是 PyCharm + Anaconda + python3.8 + open3d 0.13 已经是2023年了,现在有了全新版本。目前python由当年的3.8更新到了3.11版本,open3d也从0.13来到了

    2024年02月07日
    浏览(64)
  • open3d操作.ply文件(点云)

    读取.ply文件

    2024年02月14日
    浏览(33)
  • 点云可视化 open3D

    禁止转载 Python点云数据处理(六)Open3d补充:点云基本处理 - 知乎 https://zhuanlan.zhihu.com/p/353971365?utm_id=0 open3d绘制点云1–单帧点云 - 知乎 https://zhuanlan.zhihu.com/p/591249741 (168条消息) open3D 的使用,pcd可视化,3D bbox可视化,web_visualizer使用等。_CV矿工的博客-CSDN博客 https://blog.csdn.ne

    2024年02月09日
    浏览(45)
  • Open3D 详解:点云裁剪实战

    Open3D 详解:点云裁剪实战 在进行点云处理时,经常需要对点云进行裁剪操作,以去除无用的噪点或仅保留感兴趣区域内的点云。Open3D 是一个广泛应用于三维数据处理的开源库,提供了简单易用的点云裁剪方法。 以下是一个基于 Open3D 的点云裁剪实战例程。首先,我们导入需

    2024年02月06日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包