VTK 渲染在 PyQt 中没有按预期工作

VTK rendering not working as expected inside PyQt

我需要在 PyQt 应用程序中集成 VTK 可视化。但是,当我将模型放入 QVTKRenderWindowInteractor 时,显示会显示出一些不需要的透明效果(见下图)。无论我尝试加载什么,表面或点云都会发生这种情况。

有什么方法可以在 QVTKRenderWindowInteractor 中实现正确的表示吗?

第一张图片是 vtk.vtkConeSource() 的圆锥体。

第二张图片是 cturtle.pcd 来自 PCL 测试的点云。

左:没有QVTKRenderWindowInteractor。 右:与QVTKRenderWindowInteractor

我附上问题的示例代码以供重现。 这是没有Qt的代码:

#!/usr/bin/env python

import vtk
from vtk.util.colors import tomato

"""This simple example shows how to do basic rendering and pipeline creation."""

cone = vtk.vtkConeSource()
cone.SetResolution(8)

coneMapper = vtk.vtkPolyDataMapper()
coneMapper.SetInputConnection(cone.GetOutputPort())

coneActor = vtk.vtkActor()
coneActor.SetMapper(coneMapper)
coneActor.GetProperty().SetColor(tomato)
coneActor.RotateX(30.0)
coneActor.RotateY(-45.0)

ren = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)


ren.AddActor(coneActor)
ren.SetBackground(0.1, 0.2, 0.4)

iren.Initialize()

ren.ResetCamera()
ren.GetActiveCamera().Zoom(1.5)
renWin.Render()

iren.Start()

这是 QVTKRenderWindowInteractor 中的等效显示:

#!/usr/bin/env python

import vtk
from PyQt5.QtWidgets import QApplication
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
from vtk.util.colors import tomato

"""A simple example that uses the QVTKRenderWindowInteractor class."""


app = QApplication(['QVTKRenderWindowInteractor'])

cone = vtk.vtkConeSource()
cone.SetResolution(8)

coneMapper = vtk.vtkPolyDataMapper()
coneMapper.SetInputConnection(cone.GetOutputPort())

coneActor = vtk.vtkActor()
coneActor.SetMapper(coneMapper)
coneActor.GetProperty().SetColor(tomato)
coneActor.RotateX(30.0)
coneActor.RotateY(-45.0)

ren = vtk.vtkRenderer()
widget = QVTKRenderWindowInteractor()
widget.GetRenderWindow().AddRenderer(ren)

ren.AddActor(coneActor)
ren.SetBackground(0.1,0.2,0.4)

widget.Initialize()

ren.ResetCamera()
ren.GetActiveCamera().Zoom(1.5)
widget.GetRenderWindow().Render()

widget.Start()

widget.show()
app.exec_()

正如我在评论中所写,我无法在 MacOS 10.11.6 上重现 VTK 8.1 的问题。如果您 运行 是旧版本,请考虑升级。

下面是 QVTKRenderWindowInteractor 小部件嵌入 QMainWindow 的另一个示例。问题是否仍然存在?

如果是,请比较我在下面附加的 print(self.ren) 的输出。我会在 vtk issue tracker.

上报告此事
#!/usr/bin/env python
import sys
import vtk
from PyQt5 import QtWidgets
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
from vtk.util.colors import tomato

class MainWindow(QtWidgets.QMainWindow):

    def __init__(self, parent = None):
        super(MainWindow, self,).__init__(parent)

        self.frame = QtWidgets.QFrame()
        self.vl = QtWidgets.QVBoxLayout()
        self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
        self.vl.addWidget(self.vtkWidget)
        self.ren = vtk.vtkRenderer()
        self.ren.SetBackground(0.5,0.5,0.5)
        self.vtkWidget.GetRenderWindow().AddRenderer(self.ren)
        self.iren = self.vtkWidget.GetRenderWindow().GetInteractor()

        source = vtk.vtkConeSource()
        source.SetResolution(8)
        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(source.GetOutputPort())
        actor = vtk.vtkActor()
        actor.SetMapper(mapper)
        actor.GetProperty().SetColor(tomato)
        actor.RotateX(30.0)
        actor.RotateY(-45.0)

        self.ren.AddActor(actor)
        self.ren.SetBackground(0.1, 0.2, 0.4)
        self.ren.ResetCamera()
        self.ren.GetActiveCamera().Zoom(1.5)
        self.frame.setLayout(self.vl)
        self.setCentralWidget(self.frame)

        # Print the renderer.
        print(self.ren)

        self.show()
        self.iren.Initialize()


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())

控制台输出:

vtkOpenGLRenderer (0x7ff4c3d8a5f0)
  Debug: Off
  Modified Time: 1159
  Reference Count: 2
  Registered Events: (none)
  Aspect: (1, 1)
  PixelAspect: (1, 1)
  Background: (0.1, 0.2, 0.4)
  Background2: (0.2, 0.2, 0.2)
  BackgroundAlpha: 0
  GradientBackground: Off
  Viewport: (0, 0, 1, 1)
  Displaypoint: (0, 0, 0)
  Viewpoint: (0, 0, 0)
  Worldpoint: (0, 0, 0, 0)
  Pick Position X1 Y1: -1 -1
  Pick Position X2 Y2: -1 -1
  IsPicking boolean: 0
  Props:
    Debug: Off
    Modified Time: 923
    Reference Count: 1
    Registered Events: (none)
    Number Of Items: 1
  PickResultProps:
  nullptr
  Near Clipping Plane Tolerance: 0.001
  ClippingRangeExpansion: 0.5
  Ambient: (1, 1, 1)
  Backing Store: Off
  Display Point: (0, 0, 0)
  Lights:
    Debug: Off
    Modified Time: 806
    Reference Count: 1
    Registered Events: (none)
    Number Of Items: 0
  Light Follow Camera: On
  View Point: (0, 0, 0)
  Two Sided Lighting: On
  Automatic Light Creation: On
  Layer = 0
  PreserveDepthBuffer: Off
  PreserveColorBuffer: Off
  Interactive = On
  Allocated Render Time: 10000
  Last Time To Render (Seconds): -1
  TimeFactor: 1
  Erase: On
  Draw: On
  UseDepthPeeling: Off
  OcclusionRation: 0
  MaximumNumberOfPeels: 4
  LastRenderingUsedDepthPeeling: Off
  Delegate:null
  Selector: 0x0
  TexturedBackground: Off
  BackgroundTexture:null
  Pass:null
  PickedId0
  NumPicked0
  PickedZ 0

尝试了几种方法后,我得到了以下解决方案 Merge Request

我使用 QGLWidget 作为 QVTKRenderWindowInteractor 的基础 class,而不是 QWidget。此更改是因为据报道有时 QWidget 会导致渲染问题。

为此,我在导入 QVTKRenderWindowInteractor 之前添加了以下代码:

import vtk.qt
vtk.qt.QVTKRWIBase = "QGLWidget"

from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor

为了使用 QGLWidget,我必须安装以下包:

sudo apt-get install python3-pyqt5.qtopengl

新版vtk解决方案:

# this should be done before importing vtk
import vtkmodules.qt
vtkmodules.qt.QVTKRWIBase = 'QGLWidget'

import vtk