【VTK 学习笔记】体绘制

文章目录

    • 参考资料
    • 体绘制管线
    • 光线投射法
    • vtkPiecewiseFunction 分段线性函数
    • 颜色传输函数
    • 光照与阴影

参考资料

  • https://zhuanlan.zhihu.com/p/338223153
  • VTK图形图像开发进阶

体绘制管线

#!/usr/bin/env python

import vtk

def main():
    fileName = './MRHead.mha'
    
	#renWin 背景颜色
    colors = vtk.vtkNamedColors() 
    
    # 不透明传输函数,将灰度值映射成不透明度
    opacityTransferFunction = vtk.vtkPiecewiseFunction()
    opacityTransferFunction.AddPoint(70, 0.0)
    opacityTransferFunction.AddPoint(90, 0.4)
    opacityTransferFunction.AddPoint(180, 0.6)

    # 颜色传输函数,将灰度值映射成颜色值
    colorTransferFunction = vtk.vtkColorTransferFunction()
    colorTransferFunction.AddRGBPoint(0.0, 0.0, 0.0, 0.0)
    colorTransferFunction.AddRGBPoint(64.0, 1.0, 0.52, 0.3)
    colorTransferFunction.AddRGBPoint(190.0, 1.0, 1.0, 1.0)
    colorTransferFunction.AddRGBPoint(220.0, 0.2, 0.2, 0.2)

    # 设置体数据属性
    volumeProperty = vtk.vtkVolumeProperty()
 	volumeProperty.SetInterpolationTypeToLinear()   #线性插值
 	#volumeProperty.SetInterpolationTypeToNearest() 最近邻插值
    volumeProperty.SetColor(colorTransferFunction)  #颜色传输函数
    volumeProperty.SetScalarOpacity(opacityTransferFunction)   #不透明度传输函数
	volumeProperty.ShaderOn()   #阴影
	volumeProperty.SetAmbient(0.4)   #环境光系数
    volumeProperty.SetDiffuse(0.6)    #散射光系数
    volumeProperty.SetSpecular(0.2)    #反射光系数
    volumeProperty.SetSpecularPower(0.5) #高光强度
    
    # 可视化管线 :reader->filter->volumeMapper->volumeMapper->ren1->renWin->iren
    # vtkMetaImageReader 
    reader = vtk.vtkMetaImageReader()
    reader.SetFileName(fileName)
	
	# vtkImageCast
    cast = vtk.vtkImageCast()
    cast.SetInputConnection(reader.GetOutputPort())
    cast.SetOutputScalarTypeToUnsignedChar()
    
	# vtkFixedPointVolumeRayCastMapper()
    volumeMapper = vtk.vtkFixedPointVolumeRayCastMapper()
    #volumeMapper =vtk.vtkGPUVolumeRayCastMapper()
    volumeMapper.SetInputConnection(cast.GetOutputPort())
	
	# SetMapper SetProperty
    volume = vtk.vtkVolume()   #类似于几何渲染中的 vtkActor
    volume.SetMapper(volumeMapper)
    volume.SetProperty(volumeProperty)

	# vtkLight vtkCamera
	ren1 = vtk.vtkRenderer()
    ren1.AddVolume(volume)
    ren1.SetBackground(colors.GetColor3d('Wheat'))
    ren1.GetActiveCamera().Azimuth(45)
    ren1.GetActiveCamera().Elevation(30)
    ren1.ResetCameraClippingRange()
    ren1.ResetCamera()

	renWin = vtk.vtkRenderWindow()
    renWin.AddRenderer(ren1)
    renWin.SetSize(600, 600)
    renWin.SetPosition(500,500)
    renWin.SetWindowName('SimpleRayCast')
    renWin.Render()
	
	iren = vtk.vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)
    iren.Start()

if __name__ == '__main__':
    main()

【VTK 学习笔记】体绘制_第1张图片

光线投射法

光线投射法是最常用的体绘制方法。他是一种基于图像序列的直接体绘制方法,其基本原理是从投影图像平面的每个像素沿着视线方向发射一条穿过体数据的射线,然后在射线上按照一定的步长进行等距采样,对每个采样点采用插值技术来计算其体素值,根据颜色传输函数和不透明传输函数来获取相应的颜色值和不透明度,最后利用光线吸收模型将颜色值进行累加直至光线穿过体数据,即可得到当前平面像素的渲染颜色,生成最终的显示图像。光线投射法的优点是能够比较精确地模拟原始体数据,但计算量比较大,实时体绘制对计算机硬件地要求比较高。
【VTK 学习笔记】体绘制_第2张图片

  • vtkFixedPointVolumeRayCastMapper 能实现基于 Alpha合成地体绘制和最大密度投影体绘制方法。
  • vtkGPUVolumeRayCastMapper 实现了GPU加速地光线投射体绘制算法,GPU绘制如下
    【VTK 学习笔记】体绘制_第3张图片

vtkPiecewiseFunction 分段线性函数

AddPoint(...)   
 |      V.AddPoint(float, float) -> int
 |      C++: int AddPoint(double x, double y)
 |      V.AddPoint(float, float, float, float) -> int
 |      C++: int AddPoint(double x, double y, double midpoint,
 |          double sharpness)    
 |     	 
 |      Return the index of the point (0 based), or -1 on error.
 |  
 AddSegment(...)
 |      V.AddSegment(float, float, float, float)
 |      C++: void AddSegment(double x1, double y1, double x2, double y2)
 ClampingOn(...)
 |      V.ClampingOn()
 |      C++: virtual void ClampingOn()
 ClampingOff(...)
 |      V.Clampingff()
 |      C++: virtual void Clampingff()

Slicer软件中的分段线性函数
【VTK 学习笔记】体绘制_第4张图片
当前点 x 1 x_1 x1的M值(midpoint)的含义:
f ( x 1 + ( x 2 − x 1 ) M ) = 1 2 ( f ( x 1 + x 2 ) ) f(x_1+(x_2-x_1)M)=\dfrac{1}{2}(f(x_1+x_2)) f(x1+(x2x1)M)=21(f(x1+x2))
【VTK 学习笔记】体绘制_第5张图片
S在0到1之间曲线是曲线,在1的时候竖直
【VTK 学习笔记】体绘制_第6张图片
Clamping
【VTK 学习笔记】体绘制_第7张图片
不透明度传输函数和梯度不透明度函数都使用上面的分段线性函数作为参数

volumeProperty.SetScalarOpacity(opacityTransferFunction)
volumeProperty.SetGradientOpacity(volumeGradientOpacity)

梯度不透明函数能增强过渡区域的显示效果。例如在不同材料的临界区域,如空气到软组织或者软组织到骨头的临界区,梯度值会比较大,而材料内部梯度值则比较小。添加下列代码

volumeGradientOpacity = vtk.vtkPiecewiseFunction()
volumeGradientOpacity.AddPoint(10,0.0)
volumeGradientOpacity.AddPoint(90, 0.5)
volumeGradientOpacity.AddPoint(100, 1.0)
volumeProperty.SetGradientOpacity(volumeGradientOpacity)

【VTK 学习笔记】体绘制_第8张图片

颜色传输函数

颜色传输函数与不透明度传输函数的使用类似,二者的不同之处在于颜色传输函数是将一个标量值映射为一个颜色值。这个颜色值既可以是 RGB 值,也可以是 HSV 值。

class vtkColorTransferFunction
AddHSVPoint(...)
 |      V.AddHSVPoint(float, float, float, float) -> int
 |      C++: int AddHSVPoint(double x, double h, double s, double v) #x表示灰度值
 |      V.AddHSVPoint(float, float, float, float, float, float) -> int
 |      C++: int AddHSVPoint(double x, double h, double s, double v,
 |          double midpoint, double sharpness)
 |      
 |  
 |  AddHSVSegment(...)
 |      V.AddHSVSegment(float, float, float, float, float, float, float,
 |          float)
 |      C++: void AddHSVSegment(double x1, double h1, double s1,
 |          double v1, double x2, double h2, double s2, double v2)
 |      
 |      Add two points to the function and remove all the points between
 |      them
 |  
 |  AddRGBPoint(...)
 |      V.AddRGBPoint(float, float, float, float) -> int
 |      C++: int AddRGBPoint(double x, double r, double g, double b)
 |      V.AddRGBPoint(float, float, float, float, float, float) -> int
 |      C++: int AddRGBPoint(double x, double r, double g, double b,
 |          double midpoint, double sharpness)
 |  
 |  AddRGBSegment(...)
 |      V.AddRGBSegment(float, float, float, float, float, float, float,
 |          float)
 |      C++: void AddRGBSegment(double x1, double r1, double g1,
 |          double b1, double x2, double r2, double g2, double b2)
 |      
 |      Add two points to the function and remove all the points between
 |      them
 |  SetColor(...)
 |      V.SetColor(int, vtkPiecewiseFunction)
 |      C++: void SetColor(int index, vtkPiecewiseFunction *function)
 |      V.SetColor(vtkPiecewiseFunction)
 |      C++: void SetColor(vtkPiecewiseFunction *function)
 |      V.SetColor(int, vtkColorTransferFunction)
 |      C++: void SetColor(int index, vtkColorTransferFunction *function)
 |      V.SetColor(vtkColorTransferFunction)
 |      C++: void SetColor(vtkColorTransferFunction *function)
 |      
 |      Set the color of a volume to a gray level transfer function for
 |      the component indicated by index. This will set the color
 |      channels for this component to 1.

光照与阴影

阴影效果主要受环境光系数Ambient、散射光系数Diffuse、反射光系数Specular和高光系数SetSpecularPower四个参数影响(还与光源的数目、位置和颜色有关)。环境光系数、散射光系数、反射光系数一般情况下和为1,有时为了提高亮度,和会大于1.这三个系数中当环境光占主导时,阴影效果不明显;当散射光占主导时,显示效果比较粗糙;反射光占主导时,显示效果比较光滑。当阴影效果关闭时等于环境光系数为1.0,其他两个系数为0.高光系数控制体绘制的外观平滑程度。开启阴影效果对 vtkUnstructuredGrid 数据是无效的,另外对 vtkImageData 的最大密度投影也是无效的。

当多个segments 时可以用 index 索引

class vtkVolumeProperty
 |  SetShade(...)
 |      V.SetShade(int, int)
 |      C++: void SetShade(int index, int value)
 |      V.SetShade(int)
 |      C++: void SetShade(int value)
 |  ShadeOn(...)
 |      V.ShadeOn(int)
 |      C++: void ShadeOn(int index)
 |      V.ShadeOn()
 |      C++: void ShadeOn()
 |  ShadeOff(...)
 |      V.ShadeOff(int)
 |      C++: void ShadeOff(int index)
 |      V.ShadeOff()
 |      C++: void ShadeOff()
  |  SetAmbient(...)
 |      V.SetAmbient(int, float)
 |      C++: void SetAmbient(int index, double value)
 |      V.SetAmbient(float)
 |      C++: void SetAmbient(double value)
 |      Set/Get the ambient lighting coefficient.
 |  SetDiffuse(...)
 |      V.SetDiffuse(int, float)
 |      C++: void SetDiffuse(int index, double value)
 |      V.SetDiffuse(float)
 |      C++: void SetDiffuse(double value)
 |      
 |      Set/Get the diffuse lighting coefficient.
 |  SetSpecular(...)
 |      V.SetSpecular(int, float)
 |      C++: void SetSpecular(int index, double value)
 |      V.SetSpecular(float)
 |      C++: void SetSpecular(double value)
 |      
 |      Set/Get the specular lighting coefficient.
 |  SetSpecularPower(...)
 |      V.SetSpecularPower(int, float)
 |      C++: void SetSpecularPower(int index, double value)
 |      V.SetSpecularPower(float)
 |      C++: void SetSpecularPower(double value)

 |      Set/Get the specular power.

你可能感兴趣的:(【VTK学习笔记】)