1. 程式人生 > >【轉】vtk入門

【轉】vtk入門



【轉】vtk入門

VTK 程式設計簡介
黃為鵬
0 如何利用文件
VTK 是由 Will Schroeder 等創立的 Kitware Inc. 的開放原始碼產品。Kitware 提供關於VTK 的技術支援和各種服務產品,包括教科書和使用者指南:The Visualization Toolkit An Object-Oriented Approach To 3D Graphics, 3rd edition 和 The Visualization Toolkit User's Guide 。兩本書的內容各有側重,教科書主要介紹視覺化的各種演算法以及 VTK 中的資料結構,而使用者指南強調軟體的使用方法。可以根據使用過程中遇到的不同問題參考兩本書中的相應章節。程式設計中對具體的類、函式等的使用可以參考電子版的手冊。程式設計中遇到的問題,可以在 VTK 的 maillist 上提出,一般都會有解答。
1 編譯 VTK 庫
1.1 準備原始碼

http://www.vtk.org/ 下載原始碼。原始碼按成熟度依次分為官方發行版、每日打包版和 CVS 開發版,其中官方發行版最穩定,CVS 開發版最新。一般應用使用官方發行版即可。
1.2 用 CMake 產生具體平臺下的工程檔案
VTK 是用 C++ 語言開發的平臺無關的圖形庫。為了使相互關聯的 VTK 庫程式碼能在不同平臺(如 Windows 和 Unix)和不同編譯器(如 Visual Studio 6.0 和 Borland)下方便使用,Kitware 開發了 CMake 這一轉換工具。比如使用 CMake,可以為 Windows 平臺下的 Visual Studio 6.0 產生相應的工程檔案(.dsp 或 .dsw 檔案),此後就可以在 Visual Studio的整合開發環境(IDE)下進行編譯連線了。
CMake 提供一個使用者介面,使用者可以定製某些變數,其中比較重要的是 BUILD_SHARED_LIBS,根據它的選擇可以生成 VTK 的靜態庫或者動態連結庫。如果編譯成靜態庫,那麼在開發應用程式時要將相應庫程式碼加入可執行程式;如果是動態庫,則可執行程式與動態連結庫是分離的。用動態庫的好處是可以減小主程式的體積,缺點是可執行程式不能獨立執行。不過在有些情況下,因為某些專利演算法在商業用途裡只能授權使用,所以 VTK 提供的部分程式碼只能以動態連結庫的方式使用,所以應該熟悉編譯動態連結庫的方法。其他較常見的重要變數有 VTK_USE_PATENTED 、VTK_USE_HYBRID 等,編譯時使它們開啟開關,就可以編譯出相應的庫以便日後使用了。

圖 1
1.3 編譯庫
以下以 Windows 平臺下的 Visual Studio 6.0 編譯環境為例來說明使用方法,不再宣告。
開啟用 CMake 產生的 .dsw 檔案,選擇工程型別進行編譯。工程型別主要分兩類:Release 和 Debug ,開發過程中一般用 Debug ,到發行時再用 Release ,所以在此用Debug即可。編譯整個工程產生全部庫,這個過程所需時間很長。編譯完成後,會在 CMake 裡面指定的目標目錄內(如 vtkbin )產生編譯出的庫檔案(預設在 vtkbin/bin/Debug 目錄內)。
2 在 Visual Studio 6.0開發環境下使用 VTK 庫
VTK 庫編譯好了以後,就可以在 Visual Studio 開發環境下使用 VTK 庫了。使用 VTK庫首先要設定標頭檔案和庫檔案的路徑,以便使用 VTK 庫的程式在編譯和連結的時候可以搜尋到。標頭檔案的位置即原始碼的各個子目錄,裡面包含了大量的 .h 檔案。將其路徑加入到 Visual Studio 6.0 的 Tools -> Options -> Directories 內,如圖 2。注意除了原始碼的各個子目錄外,還要加上一個 vtkConfigure.h 檔案的路徑,它在 CMake 產生的目標目錄內。庫檔案的設定與此類似,也在 Directories 頁面進行,其路徑是前述編譯產生庫檔案的目錄(如 vtkbin/bin/Debug )。這樣設定好路徑以後,使用 VTK 庫的程式就可以正確地編譯和連結了。對於使用動態連結庫的程式來說,此時還不能執行編譯出來的可執行程式( .exe),還需要一步,即把 VTK 的動態連結庫檔案所在路徑加入作業系統的環境變數 PATH ,或直接將這些庫檔案拷貝到系統目錄。

圖 2
3 VTK 庫程式設計特點
VTK 庫是用面向物件的 C++ 語言寫成的,由於主要開發者有著十數年涉及視覺化系統的經驗,所以 VTK 擁有非常合理的模型和結構。
VTK 的程式設計風格在教科書的附錄 A,包括命名規範、術語定義、各類物件的用途說明等。值得注意的,比如它的物件工廠(Object Factory)概念。在 VTK 裡,是用<class>::New() 的方式來初始化物件的,而不是用 C++ 中的 new 來新建物件,物件工廠不僅可以做到程式碼與裝置無關,而且通過引用計數(reference counting),可以使程式清晰簡明,不容易發生記憶體洩漏或崩潰的問題。
VTK 中實現了數百個類及其方法,它們之間簡化的繼承和關聯關係可以從教科書附錄 A.3 的圖中看到。熟悉不同的類的用途和它們之間的關係,對程式設計十分有利。
對開發者來說,如何擴充這個類庫是重要的,教科書的附錄 A.4 介紹了這個問題,而使用者指南的開發者指南部分有一章來講具體的做法。
4通過例子學習 VTK 概念及程式設計
要用 VTK 庫進行視覺化程式設計首先要對視覺化要有一定的概念和基礎。除了普通的視覺化教科書以外,VTK 提供的教科書本身就非常好。VTK 源程式包的 Example 目錄包括了一系列例子,它們都有詳盡的註釋。一步步學習這些例子,可以很容易理解 VTK 涉及的視覺化概念和 VTK 程式設計的一般特點。
學習這些例子首先要成功編譯執行它們。這個步驟跟編譯庫類似,也需要先用 CMake 工具生成 Visual Studio 的工程檔案,然後編譯;而要保證程式能正確執行,還得保證 VTK 庫檔案在環境變數的 PATH 內。
初學者應該從 Tutorial 目錄內的 Step x 例子入手,它們從最簡單的 VTK 程式開始,一步步地增加概念,演示了各種視覺化概念。注意例子裡的註釋,以第一個程式(Step1 的 Cone 程式)為例,看一下源程式:

源程式:Example/Tutorial/Step1/Cxx/Cone.cxx
//
// This example creates a polygonal model of a cone, and then renders it to
// the screen. It will rotate the cone 360 degrees and then exit. The basic
// setup of source -> mapper -> actor -> renderer -> renderwindow is
// typical of most VTK programs.
//

// First include the required header files for the VTK classes we are using.
#i nclude "vtkConeSource.h"
#i nclude "vtkPolyDataMapper.h"
#i nclude "vtkRenderWindow.h"
#i nclude "vtkCamera.h"
#i nclude "vtkActor.h"
int main( int argc, char *argv[] )
{
//
// Next we create an instance of vtkConeSource and set some of its
// properties. The instance of vtkConeSource "cone" is part of a
// visualization pipeline (it is a source process object); it produces data
// (output type is vtkPolyData) which other filters may process.
//
vtkConeSource *cone =
cone->SetHeight( 3.0 );
cone->SetRadius( 1.0 );
cone->SetResolution( 10 );
//
// In this example we terminate the pipeline with a mapper process object.
// (Intermediate filters such as vtkShrinkPolyData could be inserted in
// between the source and the mapper.) We create an instance of
// vtkPolyDataMapper to map the polygonal data into graphics primitives. We
// connect the output of the cone souece to the input of this mapper.
//
vtkPolyDataMapper *coneMapper =
coneMapper->SetInput( cone->GetOutput() );

程式段 1
這個簡單的例子是一個控制檯下的程式,建立一個稜錐,在螢幕上繪製,旋轉360度後退出。程式雖簡單,但已經包括了資料來源、對映器、演員、繪製器、繪製視窗等概念,這些概念在 VTK 程式設計中幾乎都是必然涉及的。通過這個例子,就可以對教科書裡講到的各種視覺化概念(如相機、演員),程式設計模型(如管道)等有直觀的瞭解了。
這裡僅舉這個最簡單的例子,事實上,VTK 自帶的例子循序漸進,從簡單的概念,到各種複雜的概念、演算法和資料結構、GUI 程式設計、直到具體的應用等,都做了很好的例證。結合教科書和例子,可以較快地理解 VTK 的各個方面。
比如說,如果要用 VTK 在 Win32 環境下程式設計,應該學習 Example/GUI/Win32 下的例程,如果要用 MFC 框架,那麼可以參考其中的 vtkMFC 例程。體會 VTK 庫和 Win32 的關係、和 MFC 框架的關係,以便在這些平臺上開發自己的程式。這需要對 VTK和作業系統、程式設計環境本身有比較深入的瞭解,而這種瞭解對自行開發程式是十分必要的。
5 用 VTK 進行 CT 片三維重構
VTK 作為一種通用的視覺化類庫,在科學和工程界有著廣泛的應用。其中一種重要而常見的應用就是在醫學領域,比如著名的“視覺化人”專案,就有 VTK 的應用。實際上,VTK 在醫學方面的應用是是 VTK 比較強調的,在它提供的例程應用中,就有專門的醫學目錄。學習它們,並應用於我們的專案中,是一條合適的途徑。
比如,如果要做一個 3D 的醫學影像系統,其中重要的一個環節就是三維重構,這也是在全膝置換手術中需要的。所以,用 VTK 進行 CT 片的三維重構,就是一個合適的應用的例子。
利用 VTK 做 CT 片的三維重構,從演算法和資料結構來看,就是一個讀取資料問題和一個圖形顯示問題。
對於我們手裡的 CT 片,因為它們符合 DICOM 3.0 標準,所以對它們的讀取還是相對容易的。VTK 已經實現了這類資料的讀取,vtkImageSource類的很多子類都可以完成這種工作,如vtkImageReader 類或者 vtkVolumeReader 等。這樣我們程式設計的時候只要指定必須的引數,就可以實現對單張 CT 片乃至 CT 片序列的讀取了。根據 VTK 的資料管道,原始資料讀取入了以後,就可以使用各種各種過濾器進行資料轉換,在這個例子裡,即進行表面抽取、影射,然後就可以繪製了。因為是三維重建,所以還應該加入互動器,以便可以在繪製窗口裡進行互動。
關於重建演算法,對於 CT 片這種三維規則資料場,可以採取成熟、基本的演算法來進行三維重建,比如 MarchingCubes 演算法。
我們使用 Visual Studio 6.0 開發平臺來完成上述的工作,使對 CT 片的讀取、重建及顯示、互動等功能融合到 MFC 的框架中,以便提供一個方便的使用者介面。具體的程式另件給出,各部分的功能可以參考註釋。

[參考文獻]
1.The Visualization Toolkit An Object-Oriented Approach To 3D Graphics, 3rd edition
2.The Visualization Toolkit User's Guide
3.VTK 原始碼:http://www.vtk.org/get-software.php
4.VTK 電子文件:http://www.vtk.org/get-software.php
5.VTK 郵件列表:http://public.kitware.com/mailman/listinfo/vtkusers
6.http://digitalne.nju.edu.cn/new/course/vtk/index.htm

一些三維方面的開原始碼

1 microterra
      http://microterra.sourceforge.net/index.html

2 Demeter Terrain Engine
   http://www.terrainengine.com/
     

3 http://dmoz.org/Computers/Software/Graphics/3D/Terrain/

4 blue marblevierer an OSG example

   http://www.andesengineering.com/BlueMarbleViewer

#vtk影象重構