PyQt5+VTK环境搭建

VTK 简介及安装

VTK 介绍

VTK(visualization toolkit)是一个开源的免费软件系统,主要用于三维计算机图形学、图像处理和可视化。Vtk 是在面向对象原理的基础上设计和实现的,它的内核是用 C++ 构建的,包含有大约 250,000 行代码,2000 多个类,还包含有几个转换界面,因此也可以自由的通过 Java,Tcl/Tk 和 Python 各种语言使用 VTK。

VTK 是一个开放源码、自由获取的软件系统,全世界的数以千计的研究人员和开发人员用它来进行 3D 计算机图形,图像处理,可视化。VTK 包含一个 c++类库,众多的翻译接口层,包括 Tcl/Tk,Java,Python。 Visualization Toolkit 是一个用于可视化应用程序构造与运行的支撑环境,它是在三维函数库 OpenGL 的基础上采用面向对象的设计方法发展起来的,它将我们在可视化开发过程中会经常遇到的细节屏蔽起来,并将一些常用的算法封装起来。比如 Visualization Toolkit 将我们在表面重建中比较常见的 MarchingCubes 算法封装起来,以类的形式给我们以支持,这样我们在对三维规则点阵数据进行表面重建时就不必再重复编写 MarchingCubes 算法的代码,而直接使用 Visualization Toolkit 中已经提供的 vtkMarchingCubes 类。Visualization Toolkit 是给从事可视化应用程序开发工作的研究人员提供直接的技术支持的一个强大的可视化开发工具。

VTK 在 Python 环境下安装

方法一 安装 anaconda,使用 conda install 安装:

注意不同版本的 Python 对应不同的命令。

适用于 python3

install -n envA -c menpo vtk=7 python=3

或者具体到某个版本:

conda install -n envB -c menpo vtk=7 python=3.5

适用于 python 2

conda install -n envC vtk python=2

适用于 3.6:

conda install -c clinicalgraphics vtk=7.1.0

以上的命令都可以不加版本号

方法二:镜像安装

由于国内的镜像里没有 vtk,所以直接用 conda 安装会非常慢,推荐下载 whl 文件后使用 pip 安装。

提供一个下载 VTK 的 whl 文件的网址:https://www.lfd.uci.edu/~gohlke/pythonlibs/#vtk

我是 win10 系统 64 位下,使用的 python3.7,下载的是:VTK‑8.1.2‑cp37‑cp37m‑win32.whl

然后进入下载目录,启动 cmd, window power shell 或者 git bash,输入命令: pip install VTK-7.1.1-cp36-cp36m-win_amd64.whl 完成安装。

安装完成后,在使用处导入vtk包即可。

检测安装成功

示例代码:

import vtk

cone_a = vtk.vtkConeSource()

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

coneActor = vtk.vtkActor()
coneActor.SetMapper(coneMapper)


ren1 = vtk.vtkRenderer()
ren1.AddActor(coneActor)
ren1.SetBackground(1.0, 1.0, 1.0)  
ren1.SetBackground2(0.1, 0.2, 0.4)
ren1.SetGradientBackground(1)

renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren1)
renWin.SetSize(300, 300)
renWin.Render()

iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)

iren.Initialize()
iren.Start()

运行结果如图所示:
VTK显示效果

VTK简单示例

绘制立方体

#!/usr/bin/env python

# This is (almost) a direct C++ to Python transliteration of
# <VTK-root>/Examples/DataManipulation/Cxx/Cube.cxx from the VTK
# source distribution, which "shows how to manually create vtkPolyData"
#
# A convenience function, mkVtkIdList(), has been added and one if/else
# so the example also works in version 6 or later.
#
# Lines like `obj->Delete()` have been transliterated as `del obj` to,
# preserve the resemblance to the original C++ example, although I
# doubt this achieves anything beyond what Python's garbage collection
# would do anyway.

import vtk

# Makes a vtkIdList from a Python iterable. I'm kinda surprised that
# this is necessary, since I assumed that this kind of thing would
# have been built into the wrapper and happen transparently, but it
# seems not.


def mkVtkIdList(it):
    vil = vtk.vtkIdList()
    for i in it:
        vil.InsertNextId(int(i))
    return vil

# 绘制通用方法
def myShow(cube):
    # Now we'll look at it.
    cubeMapper = vtk.vtkPolyDataMapper()
    if vtk.VTK_MAJOR_VERSION <= 5:
        cubeMapper.SetInput(cube)
    else:
        cubeMapper.SetInputData(cube)
    cubeMapper.SetScalarRange(0, 7)
    cubeActor = vtk.vtkActor()
    cubeActor.SetMapper(cubeMapper)

    # The usual rendering stuff.
    camera = vtk.vtkCamera()
    camera.SetPosition(1, 1, 1)
    camera.SetFocalPoint(0, 0, 0)

    renderer = vtk.vtkRenderer()
    renWin = vtk.vtkRenderWindow()
    renWin.AddRenderer(renderer)

    iren = vtk.vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)

    renderer.AddActor(cubeActor)
    renderer.SetActiveCamera(camera)
    renderer.ResetCamera()
    renderer.SetBackground(0, 0, 0)
    renderer.SetBackground(1.0, 1.0, 1.0)
    renderer.SetBackground2(0.1, 0.2, 0.4)
    renderer.SetGradientBackground(1)

    renWin.SetSize(300, 300)

    # interact with data
    renWin.Render()
    iren.Start()
    del cubeMapper
    del cubeActor
    del camera
    del renderer
    del renWin
    del iren


def main():
    # x = array of 8 3-tuples of float representing the vertices of a cube:
    # 8个三维值代表长方体的8个顶点
    x = [(0.0, 0.0, 0.0), (1.0, 0.0, 0.0), (1.0, 1.0, 0.0), (0.0, 1.0, 0.0),
         (0.0, 0.0, 1.0), (1.0, 0.0, 1.0), (1.0, 1.0, 1.0), (0.0, 1.0, 1.0)]

    # pts = array of 6 4-tuples of vtkIdType (int) representing the faces
    #     of the cube in terms of the above vertices
    # 点的编号0-7,每个面由4个点组成
    pts = [(0, 1, 2, 3), (4, 5, 6, 7), (0, 1, 5, 4),
           (1, 2, 6, 5), (2, 3, 7, 6), (3, 0, 4, 7)]

    # We'll create the building blocks of polydata including data attributes.
    cube = vtk.vtkPolyData()
    points = vtk.vtkPoints()
    polys = vtk.vtkCellArray()
    scalars = vtk.vtkFloatArray()

    # Load the point, cell, and data attributes.
    for i in range(8):
        points.InsertPoint(i, x[i])
    for i in range(6):
        polys.InsertNextCell(mkVtkIdList(pts[i]))
    for i in range(8):
        scalars.InsertTuple1(i, i)

    # We now assign the pieces to the vtkPolyData.
    cube.SetPoints(points)
    del points
    cube.SetPolys(polys)
    del polys
    cube.GetPointData().SetScalars(scalars)
    del scalars

    myShow(cube)
    # Clean up
    del cube


main()

运行结果如图所示:
在这里插入图片描述

PyQt5中引入VTK渲染窗口

from PyQt5.QtWidgets import QApplication, QMainWindow
import sys
import vtk
from PyQt5 import QtCore, QtGui, QtWidgets
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor


class myMainWindow(QtWidgets.QMainWindow):

    def __init__(self, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)

        self.frame = QtWidgets.QFrame()

        self.vl = QtWidgets.QVBoxLayout()
        self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
        self.vl.addWidget(self.vtkWidget)

        self.ren = vtk.vtkRenderer()
        self.vtkWidget.GetRenderWindow().AddRenderer(self.ren)
        self.iren = self.vtkWidget.GetRenderWindow().GetInteractor()

        # Create source
        source = vtk.vtkConeSource()
        source.SetCenter(0, 0, 0)
        source.SetRadius(0.1)

        source1 = vtk.vtkSphereSource()
        source1.SetCenter(0, 0, 0)
        source1.SetRadius(0.3)

        # Create a mapper
        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(source.GetOutputPort())

        mapper1 = vtk.vtkPolyDataMapper()
        mapper1.SetInputConnection(source1.GetOutputPort())

        # Create an actor
        actor = vtk.vtkActor()
        actor.SetMapper(mapper)

        actor1 = vtk.vtkActor()
        actor1.SetMapper(mapper1)

        self.ren.AddActor(actor)
        self.ren.AddActor(actor1)

        self.ren.ResetCamera()

        self.frame.setLayout(self.vl)
        self.setCentralWidget(self.frame)

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


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

运行结果:
在这里插入图片描述

PyQt5中使用VTK读取STL文件

# 部分代码,在PyQt主程序中以addWidget形式嵌入到主窗口中

    # 添加VTK显示窗读取STL文件===============================================
    self.vtkWidget = QVTKRenderWindowInteractor(self.centralwidget) # 提供平台独立的响应鼠标、键盘和时钟事件的交互机制
    self.verticalLayout_3.addWidget(self.vtkWidget)

    self.ren = vtk.vtkRenderer() # 负责管理场景的渲染过程
    self.ren.SetBackground(1.0, 1.0, 1.0) # 设置页面底部颜色值
    self.ren.SetBackground2(0.1, 0.2, 0.4) # 设置页面顶部颜色值
    self.ren.SetGradientBackground(1) # 开启渐变色背景设置

    self.vtkWidget.GetRenderWindow().AddRenderer(self.ren)
    self.iren = self.vtkWidget.GetRenderWindow().GetInteractor()
    # 交互器样式的一种,该样式下,用户是通过控制相机对物体作旋转、放大、缩小等操作
    style = vtk.vtkInteractorStyleTrackballCamera()
    self.iren.SetInteractorStyle(style)

    # Read from STL file
    stlreader = vtk.vtkSTLReader()
    stlreader.SetFileName("test.stl")

    # Read from OBJ file
    # objReader = vtk.vtkOBJReader()
	# objReader.SetFileName("test.obj")

    # Create a mapper
    mapper = vtk.vtkPolyDataMapper() # 渲染多边形几何数据
    mapper.SetInputConnection(stlreader.GetOutputPort()) 
    # VTK可视化管线的输入数据接口 ,对应的可视化管线输出数据的接口为GetOutputPort();
    # mapper.SetInputConnection(objReader.GetOutputPort())

    # Create an actor
    actor = vtk.vtkActor()
    actor.SetMapper(mapper)
    # 设置生成几何图元的Mapper。即连接一个Actor到可视化管线的末端(可视化管线的末端就是Mapper)。

    self.ren.AddActor(actor)
    self.ren.ResetCamera()

    self.centralwidget.setLayout(self.verticalLayout_3)
    self.setCentralWidget(self.centralwidget)

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

运行结果:
读取stl文件
读取obj文件

VTK支持的3D文件格式

VTK中可以导入/导出或读/写多种三维格式的文件,可以参考What 3D file formats can VTK import and export? The following table identifies the file formats that VTK can read and write. Importer and Exporter classes move full scene information into or out of VTK. Reader and Writer classes move just geometry.

File Format Read Write
3D Studio vtk3DSImporter
AVS “UCD” format vtkAVSucdReader
Movie BYU vtkBYUReader vtkBYUWriter
Renderman vtkRIBExporter
Open Inventor 2.0 vtkIVExporter/vtkIVWriter
CAD STL vtkSTLReader vtkSTLWriter
Fluent GAMBIT ASCII vtkGAMBITReader
Unigraphics Facet Files vtkUGFacetReader
Marching Cubes vtkMCubesReader vtkMCubesWriter
Wavefront OBJ vtkOBJExporter
VRML 2.0 vtkVRMLExporter
VTK Structured Grid † vtkStructuredGridReader vtkStructuredWriter
VTK Poly Data † vtkPolyDataReader vtkPolyDataWriter
PLOT3D vtkPLOT3DReader
CGM vtkCGMWriter
OBJ vtkOBJReader
Particle vtkParticleReader
PDB vtkPDBReader
PLY vtkPLYReader vtkPLYWriter
Gaussian vtkGaussianCubeReader
Facet vtkFacetReader vtkFacetWriter
XYZ vtkXYZMolReader
Ensight ‡ vtkGenericEnSightReader

本文作者: 旌旗
原文链接: https://seekzzh.site/pyqt5-vtk/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章