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 許可協議。轉載請註明出處!

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