VTK修炼之道67:体绘制讨论_不透明度传输函数

来源:互联网 发布:安卓软件效果器 编辑:程序博客网 时间:2024/06/11 17:51

1.vtkVolume

vtkVolume类似于几何渲染中的vtkActor,用于表示渲染场景中的对象。除了存储基本变换信息(平移、旋转、缩放等),其内部还存储了两个重要对象。这两个对象分别是vtkAbstractVolumeMapper对象和vtkVolumeProperty对象。

1.1 void SetMapper(vtkAbstractVolumeMapper* mapper);

该函数用于连接vtkAbstractVolumeMapper对象,并根据不同的体绘制算法获取其内部生成的图元数据。具体的体绘制Mapper如下所示:


1.2 void SetProperty(vtkVolumeProperty* property)

该函数用于设置VTKVolumeProperty对象。其中vtkVolumeProperty用来设置体绘制的颜色、不透明度函数、阴影等信息。在体绘制中,颜色和不透明度设置至关重要,决定了最终的显示结果。

2.VTKVolumeProperty——不透明度传输函数

不透明度传输函数是一个分段线性标量映射函数,利用该函数可将光线投影过程中的采样点灰度值映射为不同的不透明度值,已决定最终颜色值。一个标准的不透明度设置代码如下:

//添加灰度不透明度属性vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity =vtkSmartPointer<vtkPiecewiseFunction>::New();compositeOpacity->AddPoint(70, 0.0);compositeOpacity->AddPoint(90, 0.4);compositeOpacity->AddPoint(180, 0.6);volumeProperty->SetScalarOpacity(compositeOpacity);
VTKVolumeProperty类中通过如下函数设置和获取不透明度函数:

void SetScalarOpacity(vtkPiecewiseFuntion* function);vtkPiecewiseFunction*  GetScalarOpacity(int Index);
vtkPiecewiseFunction类定义标量线性分段函数,其支持两种设置方式,第一种方式是直接添加断点;第二种是直接添加一条线段,即添加两个断点。

2.1 直接添加断点

该函数驱动如下:

int AddPoint(double x,double y);
第一个参数x为自变量,这里是指灰度值;y则是映射值,这里指不同明度。执行成功后,返回当前添加的断点的index索引值(从0开始),否则返回-1.

2.2 直接添加一条线段

其核心就是添加两个断点。其函数设置如下:

void AddSegment(double x1,double y1,double x2, double y2);
添加两个断点(x1,y1)/(x2,y2),组成一条线段。注意添加一条线段时,如果改线段内已经存在断点,则该断点会被清除。如果采用这种方式设置不透明度传输函数,则上面代码要重写为:

compositeOpacity->AddSegment(70, 0, 90, 0.4);compositeOpacity->AddSegment(90, 0.4, 180, 0.6);compositeOpacity->AddSegment(180, 0.6, 255, 1.0);volumeProperty->SetScalarOpacity(compositeOpacity)

2.3 删除断点操作

vtkPiecewiseFunction类中也包括了删除断点函数。具体如下:

int RemovePoint(double x); //将自变量值为x的断点删除;

void RemoveAllPoints(); //删除所有断点;

2.4 实际意义

上面代码中设置了三个不透明度断点(70,0.00)、(90,0.40)、(180,0.60)。其意义是,当灰度值小于70时,不透明导读应设置为0;当灰度值介于70~90时,通过线性映射到0.0~0.40之间;当灰度值介于90~180时,现行映射至0.40~0.60;当灰度值大于180度时,不透明度映射到0.60~1.00的一个值。如果图像的灰度范围为0~255,那么上述代码利用三个断点将整个灰度范围分为四段处理。

2.5 Clamping标志

vtkPiecewiseFunction中有个Clamping标志,当Clamping标志为真时,对于小于所有断点最小灰度值的灰度值,其映射为最小灰度值断点对应的映射值;对于大于所有断点最大灰度值的灰度值,其映射值为最大灰度值断点对应的映射值。如下图所示:


当Clamping标志为假时,所有位于断点灰度值范围之外的灰度对应映射值都为零。如下图所示:


3.不同不透明度传输函数对应的体绘制实验

代码如下:

#include <vtkAutoInit.h>VTK_MODULE_INIT(vtkRenderingOpenGL);VTK_MODULE_INIT(vtkRenderingVolumeOpenGL);VTK_MODULE_INIT(vtkRenderingFreeType);VTK_MODULE_INIT(vtkInteractionStyle);#include <vtkSmartPointer.h>#include <vtkStructuredPointsReader.h>#include <vtkStructuredPoints.h>#include <vtkGPUVolumeRayCastMapper.h>#include <vtkVolumeProperty.h>#include <vtkPiecewiseFunction.h>#include <vtkColorTransferFunction.h>#include <vtkVolume.h>#include <vtkRenderer.h>#include <vtkRenderWindow.h>#include <vtkRenderWindowInteractor.h>#include <vtkCamera.h>int main(){vtkSmartPointer<vtkStructuredPointsReader> reader =vtkSmartPointer<vtkStructuredPointsReader>::New();reader->SetFileName("mummy.128.vtk");reader->Update();vtkSmartPointer<vtkGPUVolumeRayCastMapper> volumeMapper1 =vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();volumeMapper1->SetInputData(reader->GetOutput());vtkSmartPointer<vtkGPUVolumeRayCastMapper> volumeMapper2 =vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();volumeMapper2->SetInputData(reader->GetOutput());/****************************************************************/vtkSmartPointer<vtkVolumeProperty> volumeProperty1 =vtkSmartPointer<vtkVolumeProperty>::New();volumeProperty1->SetInterpolationTypeToLinear(); //设置线性插值volumeProperty1->ShadeOn();//开启阴影功能 volumeProperty1->SetAmbient(0.4);//设置环境温度系数volumeProperty1->SetDiffuse(0.6);//设置漫反射系数volumeProperty1->SetSpecular(0.2);//设置镜面反射系数vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity1 =vtkSmartPointer<vtkPiecewiseFunction>::New();compositeOpacity1->AddPoint(70, 0.0);compositeOpacity1->AddPoint(90, 0.4);compositeOpacity1->AddPoint(180, 0.6);volumeProperty1->SetScalarOpacity(compositeOpacity1);////////////////////////vtkSmartPointer<vtkVolumeProperty> volumeProperty2 =vtkSmartPointer<vtkVolumeProperty>::New();volumeProperty2->SetInterpolationTypeToLinear(); //设置线性插值volumeProperty2->ShadeOn();//开启阴影功能 volumeProperty2->SetAmbient(0.4);//设置环境温度系数volumeProperty2->SetDiffuse(0.6);//设置漫反射系数volumeProperty2->SetSpecular(0.2);//设置镜面反射系数vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity2 =vtkSmartPointer<vtkPiecewiseFunction>::New();compositeOpacity2->AddPoint(100, 0.0);compositeOpacity2->AddPoint(140, 0.4);compositeOpacity2->AddPoint(180, 0.6);volumeProperty2->SetScalarOpacity(compositeOpacity2);/////////////////////////////vtkSmartPointer<vtkPiecewiseFunction> gradientOpacity =vtkSmartPointer<vtkPiecewiseFunction>::New();gradientOpacity->AddPoint(10, 0.0);gradientOpacity->AddPoint(90, 0.5);gradientOpacity->AddPoint(100, 1.0);volumeProperty1->SetGradientOpacity(gradientOpacity);volumeProperty2->SetGradientOpacity(gradientOpacity);vtkSmartPointer<vtkColorTransferFunction> color =vtkSmartPointer<vtkColorTransferFunction>::New();color->AddRGBPoint(0, 0, 0, 0);color->AddRGBPoint(64, 1.0, 0.52, 0.3);color->AddRGBPoint(190.0, 1.00, 1.00, 1.00);color->AddRGBPoint(220.0, 0.20, 0.20, 0.20);volumeProperty1->SetColor(color);volumeProperty2->SetColor(color);/****************************************************************/vtkSmartPointer<vtkVolume> volume1 =vtkSmartPointer<vtkVolume>::New();volume1->SetMapper(volumeMapper1);volume1->SetProperty(volumeProperty1);vtkSmartPointer<vtkVolume> volume2 =vtkSmartPointer<vtkVolume>::New();volume2->SetMapper(volumeMapper2);volume2->SetProperty(volumeProperty2);//////////////double View1[4] = { 0, 0, 0.5, 1 };double View2[4] = { 0.5, 0, 1, 1 };vtkSmartPointer<vtkRenderer> render1 =vtkSmartPointer<vtkRenderer>::New();render1->AddVolume(volume1);render1->SetViewport(View1);render1->SetBackground(1, 1, 0);vtkSmartPointer<vtkRenderer> render2 =vtkSmartPointer<vtkRenderer>::New();render2->AddVolume(volume2);render2->SetViewport(View2);render2->SetBackground(0, 1, 0);vtkSmartPointer<vtkRenderWindow> rw =vtkSmartPointer<vtkRenderWindow>::New();rw->AddRenderer(render1);rw->AddRenderer(render2);rw->SetSize(640, 320);rw->SetWindowName("Differ Gray Opacity Function");vtkSmartPointer<vtkRenderWindowInteractor> rwi =vtkSmartPointer<vtkRenderWindowInteractor>::New();rwi->SetRenderWindow(rw);render1->GetActiveCamera()->SetPosition(0, -1, 0);render1->GetActiveCamera()->SetFocalPoint(0, 0, 0);render1->GetActiveCamera()->SetViewUp(0, 0, 1);render1->GetActiveCamera()->Azimuth(30);render1->GetActiveCamera()->Elevation(30);render1->ResetCamera();render2->SetActiveCamera(render1->GetActiveCamera());rw->Render();rwi->Start();return 0;}

利用不透明度传输函数,可以有选择的对图像中的对象进行显示。对于不想看到的图像部分,只需将其对应的灰度范围的不透明度映射为0即可。下图即为该程序的输出成果:


左视图采用的不透明度设置参数如下:

vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity1 =vtkSmartPointer<vtkPiecewiseFunction>::New();compositeOpacity1->AddPoint(70, 0.0);compositeOpacity1->AddPoint(90, 0.4);compositeOpacity1->AddPoint(180, 0.6);volumeProperty1->SetScalarOpacity(compositeOpacity1);
右视图采用的不透明度设置参数如下:
vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity2 =vtkSmartPointer<vtkPiecewiseFunction>::New();compositeOpacity2->AddPoint(100, 0.0);compositeOpacity2->AddPoint(140, 0.4);compositeOpacity2->AddPoint(180, 0.6);volumeProperty2->SetScalarOpacity(compositeOpacity2);

4.参看资料

1.《C++ primer》
2.《The VTK User’s Guide – 11thEdition》
3.  张晓东, 罗火灵. VTK图形图像开发进阶[M]. 机械工业出版社, 2015.

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 吃了过期的东西怎么办 吃了过期的牛肉怎么办 生存战争肉腐烂了怎么办? 家里进了蝙蝠找不到了怎么办 方舟手游恐龙找不到了怎么办 这是我的战争怎么办 小孩吃坏东西呕吐发烧怎么办 睿芽密码忘了怎么办 做绿豆糕太稀了怎么办 自热火锅吃完后怎么办 自煮火锅吃完了怎么办 自热火锅没熟怎么办 厕所被米饭堵了怎么办 减完肥肉特别松怎么办 新开的熟食店没人光顾怎么办 吃剩的软炸里脊怎么办 小火锅加热时胀盒该怎么办 天丝面料容易皱怎么办 快递员拒不送件怎么办 鞋店里面买到假鞋子了怎么办 孕吐伤了胃疼怎么办 孕期吐的胃疼怎么办 买的巧克力化了怎么办 跑步后脸上出盐怎么办 头发被剪的很短怎么办 孩子做事情拖拉不专注怎么办 新热水壶有味道怎么办 新买电热壶有味怎么办 两个月狗耳朵臭怎么办 狗狗牙齿变黄怎么办 人用了狗沐浴露怎么办 狗狗吞食牙膏吐怎么办? 狗狗吞食了牙膏怎么办 大猪拉稀不吃食怎么办 猪不发烧不吃食怎么办 天天吃自热米饭怎么办 喝了加热包水怎么办啊 蛋挞没有盒子装怎么办 塑料饭盒盖子被吸住了怎么办 火腿淹的有臭味怎么办 微波炉热饭盖子打不开怎么办