#vtk
Вопрос:
Мне нужно отрисовывать три окна vtk одновременно, и общее время составляет 0,11 с. Я хочу ускорить этот процесс.
Я хочу отобразить три окна с помощью многопоточности.
Мой код таков:
from PyQt5.QtWidgets import *
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
import sys, vtk
from vtk.util.numpy_support import numpy_to_vtk
import numpy as np
import time
import _thread, threading
def numpyToVTK(data, multi_component=False, type='float'):
'''
multi_components: 比如rgb就是多component的,有3个通道,而gray图只有一个通道
type:数据类型,比如mask转为vtkImageData的时候,就可以用char类型,默认是float
'''
if type == 'float':
data_type = vtk.VTK_FLOAT
elif type == 'char':
data_type = vtk.VTK_UNSIGNED_CHAR
else:
raise RuntimeError('unknown type')
if multi_component == False:
if len(data.shape) == 2:
data = data[:, :, np.newaxis]
flat_data_array = data.transpose(2,1,0).flatten()
vtk_data = numpy_to_vtk(num_array=flat_data_array, deep=True, array_type=data_type)
shape = data.shape
else:
assert len(data.shape) == 3, 'only test for 2D RGB'
flat_data_array = data.transpose(1, 0, 2)
flat_data_array = np.reshape(flat_data_array, newshape=[-1, data.shape[2]])
vtk_data = numpy_to_vtk(num_array=flat_data_array, deep=True, array_type=data_type)
shape = [data.shape[0], data.shape[1], 1]
img = vtk.vtkImageData()
img.GetPointData().SetScalars(vtk_data)
img.SetDimensions(shape[0], shape[1], shape[2])
return img
class VTKWidget(QVTKRenderWindowInteractor):
def __init__(self, setWindowLevel, render):
super().__init__()
self.lastPoint = None
self.press = False
self.setWindowLevel = setWindowLevel
self.render = render
img = np.zeros(shape=[256, 256])
for i in range(256):
for j in range(256):
img[i, j] = i j
imgActor = vtk.vtkImageSlice()
imgMapper = vtk.vtkImageSliceMapper()
self.windowLevel = vtk.vtkImageMapToWindowLevelColors()
self.windowLevel.SetInputData(numpyToVTK(img))
imgMapper.SetInputConnection(self.windowLevel.GetOutputPort())
imgActor.SetMapper(imgMapper)
render = vtk.vtkRenderer()
render.AddActor(imgActor)
self.GetRenderWindow().AddRenderer(render)
interactor = self.GetRenderWindow().GetInteractor()
interactor.RemoveAllObservers()
self.GetRenderWindow().Render()
def mouseMoveEvent(self, ev):
super().mouseMoveEvent(ev)
pos = [ev.pos().x(), ev.pos().y()]
if self.press:
if self.lastPoint is not None:
dx = pos[0] - self.lastPoint[0]
dy = pos[1] - self.lastPoint[1]
window = self.windowLevel.GetWindow()
level = self.windowLevel.GetLevel()
self.setWindowLevel(window dx, level dy)
self.render()
self.lastPoint = pos
def updateWindowLevel(self, window, level):
self.windowLevel.SetLevel(level)
self.windowLevel.SetWindow(window)
def Render(self):
self.GetRenderWindow().Render()
def mousePressEvent(self, ev):
super().mousePressEvent(ev)
self.press = True
def mouseReleaseEvent(self, ev):
super().mouseReleaseEvent(ev)
self.press = False
self.lastPoint = None
def closeEvent(self, evt):
self.Finalize()
super().closeEvent()
class RenderThread(threading.Thread):
def __init__(self, func):
super().__init__()
self.func = func
def run(self) -> None:
self.func()
class Window(QFrame):
def __init__(self):
super().__init__()
layout = QHBoxLayout()
self.setLayout(layout)
self.vtkWidget1 = VTKWidget(setWindowLevel=self.setWindowLevel, render=self.render)
self.vtkWidget2 = VTKWidget(setWindowLevel=self.setWindowLevel, render=self.render)
self.vtkWidget3 = VTKWidget(setWindowLevel=self.setWindowLevel, render=self.render)
layout.addWidget(self.vtkWidget1)
layout.addWidget(self.vtkWidget2)
layout.addWidget(self.vtkWidget3)
def setWindowLevel(self, window, level):
self.vtkWidget1.updateWindowLevel(window=window, level=level)
self.vtkWidget2.updateWindowLevel(window=window, level=level)
self.vtkWidget3.updateWindowLevel(window=window, level=level)
def render(self):
start = time.time()
# --------------------------------------------------------------------------------------
# original data
self.vtkWidget1.Render()
self.vtkWidget2.Render()
self.vtkWidget3.Render()
# --------------------------------------------------------------------------------------
## thread method 1
# _thread.start_new_thread(self.vtkWidget1.Render, ())
# _thread.start_new_thread(self.vtkWidget2.Render, ())
# _thread.start_new_thread(self.vtkWidget3.Render, ())
# --------------------------------------------------------------------------------------
## thread method 2
# thread1 = RenderThread(func=self.vtkWidget1.Render)
# thread2 = RenderThread(func=self.vtkWidget2.Render)
# thread3 = RenderThread(func=self.vtkWidget3.Render)
#
# thread1.start()
# thread2.start()
# thread3.start()
# thread1.join()
# thread2.join()
# thread3.join()
end = time.time()
print('render time: ', end-start)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = Window()
win.show()
app.exec_()
Среда моего компьютера-это:
win 10
python 3.7
vtk 8.1.2
CPU: i7-9700K 3.60GHz
На моем компьютере отрисовка трех окон заняла около 0,12 секунды:
self.vtkWidget1.Render()
self.vtkWidget2.Render()
self.vtkWidget3.Render()
Но, если я хочу использовать многопоточность:
_thread.start_new_thread(self.vtkWidget1.Render, ())
_thread.start_new_thread(self.vtkWidget2.Render, ())
_thread.start_new_thread(self.vtkWidget3.Render, ())
Или:
thread1 = RenderThread(func=self.vtkWidget1.Render)
thread2 = RenderThread(func=self.vtkWidget2.Render)
thread3 = RenderThread(func=self.vtkWidget3.Render)
thread1.start()
thread2.start()
thread3.start()
thread1.join()
thread2.join()
thread3.join()
Приложение работает неправильно.
Мне нужна помощь для:
- как использовать многопоточность для
Render()
. - как ускорить
Render()
Любое предложение приветствуется~~~