光線投射法是最常用的體繪制方法。它是一種基於圖像序列的直接體繪制方法。
光線投影法的基本原理是從投影圖像平面(通常為平面)的每個像素沿着視線方向發射一條穿過體數據的射線,然后在射線上按照一定的步長進行等距采樣,對每個采樣點采用插值技術來計算其體素值,根據顏色傳輸函數和不透明度傳輸函數來獲取相應的顏色值和不透明度,最后利用光線吸收模型將顏色值進行累加直至管線穿過體數據。這樣,就可以得到當前平面像素的渲染顏色,最終生成顯示圖像。
光線投影法的優點是能夠比較精確地模擬原始體數據,但計算量較大,實時體繪制對計算機硬件的要求比較高。
在VTK中,VTKVolumeRayCastMapper類可用於實現光線投影體算法,並生成渲染圖元數據傳遞給vtkVolume對象進行渲染。
vtkVolumeRayCastMapper采用軟件方法來實現光線投影算法,精度高但是計算量比較大,因此渲染速度相對比較慢。
該類內部實現了兩個非常重要的函數:
- vtkVolumeRayCastMapper::SetInput(vtkImageData*):該函數用於設置輸入圖像數據;
- vtkVolumeRayCastMapper::SetVolumeRayCastFunction(vtkVolumeRayCastFunction*):該類用於設置光線投射函數。
vtkVolumeRayCastMapper中計算每條光線在通過體數據后的顏色是通過定義的vtkVolumeRayCastFunction對象來實現的。因此,必須為vtkVolumeRayCastMapper指定一個vtkVolumeRayCastFunction象, vtkVolumeRayCastFunction是一個虛基類,他包含三個子類。
2.1 vtkVolumeRauCastCompositeFunction
該方式 通過Alpha合成技術 生成每個像素的顏色值。對於每條光線在穿過體數據時,先根據設置的采樣步長進行采樣,通過插值技術來計算每個采樣點的像素值;然后根據vtkVolumeProperty中設置顏色傳輸函數和不透明度傳輸函數來計算采樣點的顏色和不透明度。最后,對所有采樣點采用Alpha合成方法計算最終的顏色。
另外,該方式還可以設置插值優先還是分類優先。 插值優先是指對投射光線進行采樣,計算采樣點的顏色值時,先通過插值方式計算該采樣點的標量值(灰度值),然后再根據顏色傳輸函數和不透明度傳輸函數計算該點的顏色值和不透明度 。 分類優先是指在計算采樣點時,先根據顏色傳輸函數和不透明度傳輸函數計算包含該采樣點的立方體的8個頂點顏色值和不透明度,然后通過插值方法獲取當前采樣點的顏色值與不透明度 。選擇插值優先還是分類優先要通過一下兩個函數:
- SetCompositeMethodToInterpolateFirst()
- SetCompositeMethodToClassifyFirst()
從顯示效果上來說,插值優先具有較好的顯示效果,但在一些情況下也會存在問題。 例如,CT圖像中,低於20的值屬於空氣,20~80的部分是軟組織,大於80部分是骨骼。如果先進行插值,那么空氣與谷歌之間永遠不會相鄰,因為他們之間一定存在軟組織。但是,我們的牙齒是和空氣直接接觸的,當使用插值優先策略並使用比較高的采樣率進行體繪制時,渲染結果會使牙齒看起來像是覆蓋了一層皮膚。
2.2 vtkVolumeRayCastMIPFunction
最大密度投影函數主要用於對體數據中高灰度值得結構進行可視化。當光線穿過體數據時,在光線上進行等距采樣。取采樣點中屬性最大值為該條光線的輸出。光線對應的屏幕像素顏色值就可以通過該值進行顏色映射獲得。默認情況下,這個屬性是指體數據的像素值或者體數據的不透明度,其設置函數為:
- SetMaximizeMethodToScalarValue()
- SetMaximizedMethodToOpacity()
當采用標量(灰度)屬性時,先經過體數據的光線進行等距離采樣,然后通過插值計算每個采樣點的標量值,最后取標量值為最大的采樣點對應的顏色和不透明度作為輸出;當采樣不透明度作為輸出時,投射光線上每次采樣都要計算一次不透明度,最后取不透明度最大值的采樣點的顏色和不透明度作為輸出。
通常,最大強度投影算法不計算明暗信息和深度信息,成像類似於X光,該方法常用於顯示血管的三維結構。該類的使用方法也是非常簡單的,和vtkVolumeRayCastCompositeFunction一致:
1 vtkSmartPoint<vtkVolumeRayCastMIPFunction> rayCastFun =
2 vtkSmartPointer<vtkVolumeRayCastMIPFunction>::New();
2.3 vtkVolumeRayCastIsosurfaceFunction
對等值面繪制函數能夠渲染體數據中特定等值面,其中,SetIsoValue(double)函數用於設置等值面的值。在進行體繪制,所有小於該值的像素不透明度都設置為0.通過設定等值面的值,可以重建出某一特定的組織,如皮膚、骨骼等,渲染結果類似與面繪制。同樣地,使用該函數進行體繪制時,代碼如下:
1 vtkSmartPointer<vtkVolumeRayCastIsosurfaceFunction> rayCastFun =
2 vtkSmartPointer<vtkVolumeRayCastIsosurfaceFunction>::New(); 3 rayCastFun->SetIsoValue(100);
三種體繪制輸出結果如下:
2.最大密度投影法輸出圖像:缺乏深度信息(更像X光輸出);
3.等值面法體繪制輸出結果:與面繪制結果類似。
3.1 討論一:投影光線上的采樣點的步長
光線投影體繪制中,投影光線上的采樣點的步長是一個重要參數,決定了體繪制的精度和速度。步長越小,采樣點就越多,但是體繪制效果提高的同時計算量也會增加。vtkVolumeRayCastMapper中設置步長的函數為:
Void SetSampleDistance(float);
這里需要注意的是,等值面繪制函數不需要進行采樣,而其他另個繪制函數都需要進行采樣。在實際應用中,調整采樣步長主要考慮的因素有樣本間距、標量數據以及標量數據映射的顏色和不同明度變化率。
vtkVolumeRayCastMapper中默認的采樣步長為1;單位為世界坐標系。下面顯示了步長為1和步長為4的兩種情況對比:
左側為步長等於1的情況;非常精細。
右側為步長等於4的卿狂,比較粗糙。
實際應用過程中,如果體數據變化比較劇烈,應該適當減小采樣步長以獲得比較精細的渲染結果,代價就是速度的降低。
3.2 討論二:圖像采樣間距(投影光線間隔)
默認情況下,圖像采樣間距為1,即每個像素對應一條投影光線;如果設為0.5,那么每個像素對應4條投射光線;如果設置為2,則每四個像素對應一條投影光線。設置圖像采樣距離的函數:
void SetImageSampleDistance(float);
需要格外注意的是,當使用這個函數的時候,必須先關閉自動調節采樣距離功能,代碼如下:
SetAutoAdjustSampleDistance(0); //關閉自動調整采樣
默認的情況下,該函數的功能是開啟的,以保證在圖像旋轉等交互時,能夠自動調整采樣距離保證實時性。如果關閉此功能,在旋轉圖像等交互過程中,體繪制渲染過程會變得很慢。
當然,即使我們采用自動調整圖像采樣距離,也可以設定它的范圍,控制函數為:
1 void SetMaximunImageSampleDistance(float); 2 void SetMinimumImageSampleDistance(float);
下圖顯示的是不同圖像采樣距離的渲染結果:
左圖的圖像采樣距離為1;右圖的圖像采樣間距為4.同樣,步長越小,渲染越精細,渲染時間越長。