VTK中的体绘制方法

来源:互联网 发布:公司网络信息保密协议 编辑:程序博客网 时间:2024/05/21 09:27

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函数里将体绘制的方法分别进行替换即可实现最大密度投射体绘制和等值面体绘制。

原创粉丝点击