-
-
Save notaTeapot/5feea53dccc921ea6af88a4d222e1e2b to your computer and use it in GitHub Desktop.
# Partially Working Error on Exit | |
from PySide2 import QtWidgets, QtGui,QtCore | |
import open3d as o3d | |
import win32gui | |
import sys | |
import threading | |
import time | |
class Worker(QtCore.QObject): | |
def run(self,vis): | |
vis.run() | |
class MainWindow(QtWidgets.QMainWindow): | |
def __init__(self): | |
super(MainWindow, self).__init__() | |
widget = QtWidgets.QWidget() | |
layout = QtWidgets.QGridLayout(widget) | |
self.setCentralWidget(widget) | |
file_path = "C:\\test\test.pcd" | |
self.pcd = o3d.io.read_point_cloud(file_path) | |
self.vis = o3d.visualization.VisualizerWithEditing() | |
self.vis.create_window() | |
self.vis.add_geometry(self.pcd) | |
hwnd = win32gui.FindWindowEx(0, 0, None, "Open3D - free view") | |
self.window = QtGui.QWindow.fromWinId(hwnd) | |
self.windowcontainer = self.createWindowContainer(self.window, widget) | |
layout.addWidget(self.windowcontainer, 0, 0) | |
self.thread = QtCore.QThread() | |
self.worker = Worker() | |
self.thread.started.connect(lambda: self.worker.run(self.vis)) | |
self.thread.start() | |
timer = QtCore.QTimer(self) | |
timer.timeout.connect(self.blub) | |
timer.start(100) | |
#print("starting vis") | |
btn = QtWidgets.QPushButton(text="test") | |
btn.clicked.connect(lambda: print("Button pressed!")) | |
layout.addWidget(btn) | |
def blub(self): | |
#Function to keep PySide eventloop running | |
pass | |
def start_vis(self): | |
print("thread start") | |
self.vis.run() | |
print("thread end") | |
def update_vis(self): | |
#self.vis.update_geometry() | |
self.vis.poll_events() | |
self.vis.update_renderer() | |
if __name__ == '__main__': | |
app = QtWidgets.QApplication(sys.argv) | |
form = MainWindow() | |
form.setWindowTitle('o3d Embed') | |
form.setGeometry(100, 100, 600, 500) | |
form.show() | |
sys.exit(app.exec_()) |
No problem, the blub function is just a placeholder to keep the eventloop running, it should work now.
not working on mac or linux, if use hwnd = widget.winId() working partially
I want to press btn to add another geometry, but run() will block the current thread. So I didn't succeed, Do you know how to solve it, thank you very much!
Overriding the closeEvent
of your MainWindow
could fix your Error on Exit
def closeEvent(self, event):
self.vis.destroy_window()
self.thread.quit()
event.accept()
Overriding the
closeEvent
of yourMainWindow
could fix your Error on Exitdef closeEvent(self, event): self.vis.destroy_window() self.thread.quit() event.accept()
yes, this works 👍
And you can add visible=False
as parameter to self.vis.create_window(visible=False)
to get rid of the open3D window flash on startup.
I want to press btn to add another geometry, but run() will block the current thread. So I didn't succeed, Do you know how to solve it, thank you very much!
I have the same problem, did you find the solution yet?
Thanks for your help.
Could anyone hint me on how this code could be changed to visualize a .OBJ or .PLY file with texture? (still using VisualizerWithEditing() within a Qt widget)
Here is what I have been able to achieve (and not):
-
using o3d.io.read_triangle_mesh() on a .PLY file instead of o3d.io.read_point_cloud() for a .PCD brings the object with texture in the visualizer, but then clicking does not do anything.
-
using o3d.io.read_triangle_mesh() on a .OBJ brings the object but does not load the texture, and again clicking does not do anything.
-
using o3d.io.read_triangle_model() yields an error as self.vis.add_geometry() does not support "triangle_model" object type. self.vis Class only has add_geometry(), and does not support add_model() as some other open3d classes have.
I am thinking about finding a way to convert the OBJ or PLY object to a point-cloud (with texture) in open3d and then loading it into the visualizer as a workaround if no other way exists (and need to figure out how to perform that conversion).
[Edit] I converted a textured mesh (.PLY) to point-count simply with the following:
filepath1 = 'my_filepath_to_my_ply_file'
obj1 = o3d.io.read_triangle_mesh(filepath1)
pcd = o3d.geometry.PointCloud()
pcd.points = obj1.vertices
pcd.colors = obj1.vertex_colors
pcd.normals = obj1.vertex_normals
It is not ideal as clicking between points results in "no click", or may hit a point located on a face behind the intended face.
It also seems that VisualizerWithEditing() ignores further add_geometry() calls, so it is not possible to have more than one object in the visualizer.
I am thinking it may then be best to use the standard open3d visualizer and use ray_casting to identify the location where the user clicked.
https://www.open3d.org/docs/release/tutorial/geometry/ray_casting.html#Creating-a-virtual-point-cloud
Anyone tried doing that?
I want to press btn to add another geometry, but run() will block the current thread. So I didn't succeed, Do you know how to solve it, thank you very much!
I solved it by using open3d.visualization.Visualizer() instead of self.vis = o3d.visualization.VisualizerWithEditing()
VisualizerWithEditing() can only render one geometry at a time even though you succeeded in adding it whereas Visualizer can only render more than one geometry.
Thanks again for your help, but I'll be prompted that attribute 'blub' is not define when I run the program. Do you know how to solve it?