VTK最初是針對醫學領域的應用而設計的,所以對於醫學的可視化方面,如處理CT的掃描資料等,具有強大的功能。它將在可視化過程中經常遇到的細節屏蔽起來,並封裝了一些常用的可視化演算法,如將面繪製中常用的MC(Marching Cubes)演算法和體繪製中常用的光線投射(Ray-Casting)演算法封裝成類的形式提供給使用者。這樣在進行醫學體資料的可視化時就可以直接使用VTK中已提供的相關類。
VTK主要提供了三種體繪製技術,除了光線投射法外,還有二維紋理映射和基於VolumePro硬體輔助的體繪製。
光線投射法是一種基於映像空間掃描的,產生高品質映像的典型的體繪製演算法,基本思想是從映像平面的每個像素都沿著視線方向發出一條射線,此射線穿過體資料集,按一定步長進行採樣,由插入計算每個採樣點的顏色值和不透明度,然後由前向後或由後向前逐點計算累計的顏色值和不透明度值,直至光線完全被吸收或穿過物體。該方法能很好地反映物質邊界的變化,使用Phong模型,引入鏡面反射、漫反射和環境反射能得到很好的光照效果,在醫學上可將各組織器官的性質屬性、形狀特徵及相互之間的層次關係表現出來,從而豐富了映像的資訊。
二維紋理映射與光線投射法不同,它是基於物體空間掃描的,也就是對物體空間的資料點加以處理,計算每個資料點對螢幕像素的貢獻並加以合成,形成最終的映像。它的繪製速度比光線投射法快上5~10倍,但是成像品質遠不及採用三線性插值的光線投射法精確,當視角改變時還會產生偽跡。
基於VolumePro硬體輔助的體繪製方法,成像品質雖然不及光線投射法,但是要比二維紋理映射好。利用VolumePro硬體支援的體繪製速度是最快的,一般每秒至少20幀畫面,但目前只支援平行投影且價格昂貴。
每種技術各有其優點和缺點,開發人員應該根據實際需要進行選擇。就目前看來,VTK中的光線投射法是應用最多的。這是因為不僅它的成像品質是最好的,而且隨著電腦技術的發展和演算法的不斷改進,其繪製能力也在不斷提高。二維紋理映射受限於其成像品質和圖形硬體,VolumePro更是由於其價格原因使用較少。
VTK中的光線投射法
VTK為使用者提供了三種用於光線投射法的函數分別是:等值面繪製函數(vtkVolumeRayCastIsosurfaceFunction)、最大密度投影函數(vtkVolumeRayCast MIPFunction)和合成體繪製函數(vtkVolumeRayCastCompositeFunction)。在等值面繪製方法中,光線穿過資料場中待顯示的等值面,然後顏色和濃淡等參數被定義在VTK Volume的體屬性-vtkVolumeProperty中,通過設定等值面的值,可以重建出某一特定的組織,如皮膚、骨骼等,結果映像類似於表面顯示。最大密度投影方法(Maximum Intensity Projection,MIP)是通過計算光線穿過資料場時遇到的最大密度值進行繪製,它可以看作是最簡單的一種體繪製,不必明確地定義體資料和顏色值間的轉換關係,與最大密度相關的資料值投影在對應的螢幕上的每個像素中形成最終映像。由於MIP方法能提供較為直觀的映像,就像X光成像一樣,所以該方法常用於顯示血管的三維結構。但正如X光片一樣,MIP不能提供深度資訊,也無法描述重疊的結構。合成體繪製方法是最常用的一種光線投射方法,在VTK中通過傳遞函數將體資料值轉換成顏色、不透明度等光學屬性,最後將這些屬性合成到螢幕上的像素中形成三維映像。在VTK中,為了得到最好的繪製效果,要定義以下三個傳遞函數:
(1)不透明度傳遞函數。該函數確定各體素或單位長度值的不透明度;
(2)顏色傳遞函數。該函數確定體素的顏色值或者灰階值;
(3)梯度傳遞函數。該函數確定不同梯度值的不透明度,從而突出不同組織之間的結構和相互之間的層次關係。
在VTK中,使用vtkPiecewiseFunction類來實現傳遞函數的設計,使用該類中的AddPoint和AddSegment函數來實現數值點的添加。一個簡單的傳遞函數的設計如以下代碼所示:
vtkPiecewiseFunction*opacityTransferFunction=vtkPiecewise Function::New();
opacityTransferFunction->AddPoint(0, 0.0);
opacityTransferFunction->AddPoint(500, 0.0);
opacityTransferFunction->AddSegment (600, 0.73, 900, 0.9);
opacityTransferFunction->AddPoint(1300, 2.0);
通過利用直線進行曲線逼近來實現複雜的傳遞函數的設計。
VTK中,要將一套醫學體資料進行體繪製,要通過繪製類設定、繪製視窗設定、互動設定、資料讀取、傳遞函數設定、體屬性設定、繪製方法映射、各種屬性裝載、繪製九個步驟。下面是VTK中體繪製的C++代碼,對關鍵類和函數的作用進行了注釋。
vtkRenderer *aRender = vtkRenderer::New(); //設定繪製類
vtkRenderWindow*renWin=vtkRenderWindow::New();//設定繪製視窗
renWin->AddRenderer(aRender); //裝載繪製類
vtkRenderWindowInteractor*iRen=vtkRenderWindowInteractor::New();//設定繪製視窗的互動
iRen->SetRenderWindow(renWin); //裝載繪製視窗
vtkVolume16Reader*reader=vtkVolume 16Reader::New();//讀取DICOM資料
reader->SetDataDimensions (64,64);//設定映像像素值
reader->SetImageRange (1,93); //設定圖片數量
reader->SetDataByteOrderToLittleEndian();
reader->SetFilePrefix("X://data ");//設定資料路徑
reader->SetDataSpacing (1.0, 1.0, 0.48); //設定資料的間距
vtkPiecewiseFunction*opacityTransferFunction=vtkPiecewise Function::New();//設定不透明度傳遞函數
opacityTransferFunction->AddPoint(0, 0.0);
opacityTransferFunction->AddPoint(500, 0.0);
opacityTransferFunction->AddSegment (600, 0.73, 900, 0.9);
opacityTransferFunction->AddPoint(1300, 2.0);
vtkColorTransferFunction *colorTransferFunction = vtkColorTransferFunction::New();//設定顏色傳遞函數
colorTransferFunction->AddRGBPoint(0, 0, 0, 0);//此處顏色設定為灰階值
colorTransferFunction->AddRGBPoint(500, 0.1, 0.1, 0.1);
colorTransferFunction->AddRGBPoint(600, 0.7, 0.7, 0.7);
colorTransferFunction->AddRGBPoint(900, 0.85, 0.85, 0.85);
colorTransferFunction->AddRGBPoint(1300, 1.0, 1.0, 1.0);
vtkPiecewiseFunction *gradientTransferFunction = vtkPiecewiseFunction::New();//設定梯度傳遞函數
gradientTransferFunction->AddPoint(0, 2.0);
gradientTransferFunction->AddPoint(500, 2.0);
gradientTransferFunction-> AddSegment (600, 0.73, 900, 0.9);
gradientTransferFunction->AddPoint(1300, 0.1);
vtkVolumeProperty*volumeProperty=vtkVolumeProperty::New();//定義並設定相關體屬性
volumeProperty->SetColor(colorTransferFunction);
volumeProperty->SetScalarOpacity(opacityTransferFunction);
volumeProperty->SetGradientOpacity(gradientTransferFunction);
vtkVolumeRayCastCompositeFunction*compositeRaycastFunction = vtkVolumeRayCastCompositeFunction::New();//定義光線投射方法為合成體繪製方法
vtkVolumeRayCastMapper *volumeMapper = vtkVolumeRayCastMapper::New();
volumeMapper->SetVolumeRayCastFunction(compositeRaycastFunction);//載入體繪製方法
volumeMapper->SetInput(reader->GetOutput());
vtkVolume *volume = vtkVolume::New();//定義Volume
volume->SetMapper(volumeMapper); volume->SetProperty(volumeProperty);//設定體屬性
aRender->AddVolume(volume); //將Volume裝載到繪製類中
aRender->SetBackground(0, 0, 0);
renWin->SetSize(500, 500); //設定背景顏色和繪製視窗大小
renWin->Render(); //視窗進行繪製
iRen->Initialize();
iRen->Start(); //初始化並進行互動繪製
在上述代碼中,只需要對最大密度投影函數vtkVolumeRayCastMIPFunction和等值面繪製函數vtkVolumeRayCastIsosurfaceFunction分別初始化,在vtkVolumeRayCastMapper類中的SetVolumeRayCastFunction函數裡將體繪製的方法分別進行替換即可實現最大密度投射體繪製和等值面體繪製。