Визуализация массивного облака точек в tkinter
Передо мной стоит задача визуализировать массивное облако точек используя tkinter. Облако точек хранится в las файле. в самом большом файле находится 40 000 000 точек.
Я пробовал несколько библиотек, которые могут это сделать и вот что про них скажу: matplotlib, panda3d, vispy - их можно встроить в tkinter, но даже миллион точек отображается с трудом. Также приходится самостоятельно парсить данные из файлов.
Open3d прекрасно справляется с задачей визуализации, но я не нашёл способ встроить окно в tkinter.
Также у меня получилось вывести .ply файл используя pyopengltk в приведенным ниже коде, но тут возникает проблема с конвертацией .las в .ply
from pyopengltk import OpenGLFrame
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
import open3d as o3d
import numpy as np
class PCFrame(OpenGLFrame):
def initgl(self):
pcd = o3d.io.read_point_cloud('example.ply')
#o3d.visualization.draw_geometries([pcd])
points = np.asarray(pcd.points, dtype=np.float32)
mn = np.min(points)
mx = np.max(points)
points = 2 * (points - mn) / (mx - mn) - 1
self.size = points.dtype.itemsize
self.length = len(points)
colors = np.asarray(pcd.colors, dtype=np.float32)
# vertexBuffer
self.vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
glBufferData(GL_ARRAY_BUFFER, points, GL_STATIC_DRAW)
# colorBuffer
self.cba = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.cba)
glBufferData(GL_ARRAY_BUFFER, colors, GL_STATIC_DRAW)
glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_COLOR_ARRAY)
glClearColor(255, 255, 255, 1.0)
def redraw(self):
glRotate(1, 3, 1, 1)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
glVertexPointer(3, GL_FLOAT, 3*4, None)
glBindBuffer(GL_ARRAY_BUFFER, self.cba)
glColorPointer(3, GL_FLOAT, 3*4, None)
glDrawArrays(GL_POINTS, 0, self.length)
def main():
root = Tk()
root.geometry('500x500')
pcf = PCFrame(root)
pcf.pack(fill=BOTH, expand=True)
pcf.animate = 10
def zoom(event):
scale = 1.0
if event.num == 5 or event.delta == -120:
scale /= 1.2
elif event.num == 4 or event.delta == 120:
scale *= 1.2
glScale(scale, scale, scale)
root.bind('<Button-5>', zoom)
root.bind('<Button-4>', zoom)
return root.mainloop()
if __name__=="__main__":
main()```