python+VTK環境搭建:安裝及用PyQt5建立一個包含三維模型的互動視窗
一、VTK簡介及安裝
1.1 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 是給從事視覺化應用程式開發工作的研究人員提供直接的技術支援的一個強大的視覺化開發工具。
1.2 VTK在Python環境下安裝
方法一(未親手實踐)、安裝anaconda,使用conda install安裝:
注意不同版本的Python對應不同的命令。
1)適用於python3(3.6以下)
install -n envA -c menpo vtk=7 python=3
or if you want to be more specific:
conda install -n envB -c menpo vtk=7 python=3.5
2)適用於python 2 (不過最近好多庫都宣告不支援python2了)
conda install -n envC vtk python=2
適用於3.6:
conda install -c clinicalgraphics vtk=7.1.0
以上的命令都可以不加版本號
方法二(已經實踐):由於國內的映象裡沒有vtk,所以直接用conda安裝會非常慢,推薦下載whl檔案後使用pip 安裝。
我是win7系統64位下,使用的python3.5,下載的是:
VTK 7.1.1 cp35 cp35m win_amd64.whl
然後進入下載目錄,啟動cmd或者window power shell,輸入命令: pip install VTK-7.1.1-cp36-cp36m-win_amd64.whl完成安裝。
安裝完成後,檢測是否安裝成功,在spyder裡輸入
import vtk
這裡提供一個檢測的小程式碼:
1. import vtk
2.
3. cone_a=vtk.vtkConeSource()
4.
5. coneMapper = vtk.vtkPolyDataMapper()
6. coneMapper.SetInputConnection(cone_a.GetOutputPort())
7.
8. coneActor = vtk.vtkActor()
9. coneActor.SetMapper(coneMapper)
10.
11.
12. ren1= vtk.vtkRenderer()
13. ren1.AddActor( coneActor )
14. ren1.SetBackground( 0.1, 0.2, 0.4 )
15.
16. renWin = vtk.vtkRenderWindow()
17. renWin.AddRenderer( ren1 )
18. renWin.SetSize( 300, 300 )
19. renWin.Render()
20.
21. iren=vtk.vtkRenderWindowInteractor()
22. iren.SetRenderWindow(renWin)
23.
24. iren.Initialize()
25. iren.Start()
執行結果如下圖:
二、建立包含三維模型視窗的對話方塊
- 2.1 建立一個對話方塊
參考我的另外一篇部落格,利用PyQt5建立一個對話方塊。
- 2.2 對話方塊中加入渲染視窗及三維模型
當上述對話方塊搭建好以後,可以輸入下面的測試程式碼進行實驗,會得到一個包含渲染視窗的對話方塊如下,並且可以用滑鼠對三維模型進行簡單的操作:
PyQt4版本使用以下程式碼:
#!/usr/bin/env python
import sys
import vtk
from vtk.qt4.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
from PyQt4 import Qt
from PyQt4 import QtGui, QtCore
class test(Qt.QMainWindow):
"""Test class"""
def __init__(self, parent=None):
Qt.QMainWindow.__init__(self, parent)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
self.setWindowTitle(self.tr("PyQt4 VTK test"))
self.workspace = Qt.QWorkspace()
self.setCentralWidget(self.workspace)
self.frame = QtGui.QFrame(self.workspace)
self.hbox = QtGui.QHBoxLayout()
# create the widget
self.widget = QVTKRenderWindowInteractor(self.frame)
self.widget.Initialize()
self.widget.Start()
# if you dont want the 'q' key to exit comment this.
self.widget.AddObserver("ExitEvent", lambda o, e, a=app: a.quit())
self.cone = vtk.vtkConeSource()
self.cone.SetResolution(8)
self.coneMapper = vtk.vtkPolyDataMapper()
self.coneMapper.SetInput(self.cone.GetOutput())
self.coneActor = vtk.vtkActor()
self.ren.AddActor(self.coneActor)
self.renWin=self.widget.GetRenderWindow()
self.renWin.AddRenderer(self.ren)
self.hbox.addWidget(self.widget)
self.frame.setLayout(self.hbox)
self.workspace.addWindow(self.frame)
if __name__ == "__main__":
app = Qt.QApplication(sys.argv)
mainwindow = test()
mainwindow.show()
sys.exit(app.exec_())
若是PyQt5版本則使用以下程式碼(已經經過驗證):
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.5)
# 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()
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
if __name__ == "__main__":
app = QApplication(sys.argv)
window = myMainWindow()
sys.exit(app.exec_())