首页 > 其他分享 >VTK 体绘制之vtkVolume

VTK 体绘制之vtkVolume

时间:2023-06-25 13:22:40浏览次数:32  
标签:1.0 函数 color 梯度 VTK 透明度 vtkVolume 绘制 vtkNew

基本概念
  vtkVolume类似于几何渲染中的vtkActor,用于表示渲染场景中的对象。除了存储基本的变换信息(平移、旋转、放缩等),其内部还存储了两个重要对象。这两个对象分别是vtkAbstactVolumeMapper对象和    vtkVolumeProperty对象。相应的函数如下。
1)void SetMapper(vtkAbstractVolumeMapper* mapper)。该函数用于连接vtkAbstractMapper对象,并根据不同的体绘制算法获取其内部生产的图元数据。
2)void SetProperty(vtkVolumeProperty* property)。该函数用于设置vtkVolumeProperty对象。其中vtkVolumeProperty用来设置体绘制的颜色和不透明函数以及阴影等信息。

在体绘制中,颜色以及不透明度的设置至关重要,决定了最终的显示效果。这里简单介绍在vtkVolumeProperty中设置不透明度以及阴影。

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

1 //添加灰度不透明度属性
2 vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
3 compositeOpacity->AddPoint(70, 0.0);
4 compositeOpacity->AddPoint(90, 0.4);
5 compositeOpacity->AddPoint(180, 0.6);
6 volumeProperty->SetScalarOpacity(compositeOpacity);

  上面代码中设置了三个不透明度断点(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,那么上述代码利用三个断点将整个灰度范围分为四段处理。vtkVolumeProperty类中通过如下函数设置和获取不透明度函数:

1 void SetScalarOpacity(vtkPiecewiseFuntion* function);
2 vtkPiecewiseFunction*  GetScalarOpacity(int Index)

梯度不透明度函数
  梯度不透明度函数是将梯度模值映射为一个不透明度乘子,从而增强过渡区域的显示效果。该函数也是使用vtkPiecewiseFunction类。例如,在不同材料的临界区域,如空气到软组织,或者软组织到骨头的临界区,梯度值会比较大,而材料的内部梯度值则会相对比较小。一个标准的梯度不透明度函数代码如下:

1 vtkSmartPointer<vtkPiecewiseFunction> gradientOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
2 gradientOpacity->AddPoint(10, 0.0);
3 gradientOpacity->AddPoint(90, 0.5);
4 gradientOpacity->AddPoint(100, 1.0);

  上述代码中将梯度小于10的点的不透明度乘子设为0,即完全透明。当梯度大小为10时,不透明度为0;梯度大小为90时,不透明度乘子为0.5;梯度大小在10~90时,不透明度乘子通过线性映射至0~0.5之间的数值;同理,当梯度大小在90~100之间时,不透明度乘子通过线性映射至0.5~1.0之间;梯度值大于100时,其不透明度乘子为1.0。vtkVolumeProperty中通过如下函数设置和获取梯度不透明度函数:

void SetGradientOpacity(vtkPiecewiseFunction* function);
vtkPiecewiseFunction* GetGradientOpacity();

颜色传输函数
  颜色传输函数与不透明度传输函数的使用类似,二者的不同之处在于颜色传输函数是将一个标量值映射为颜色值。这个颜色值可以是RGB值,也可以是HSV值。VTK中颜色传输函数采用vtkColorTransferFunction类实现。一个标准的颜色传输函数代码如下:

1 vtkSmartPointer<vtkColorTransferFunction> color = vtkSmartPointer<vtkColorTransferFunction>::New();
2 color->AddRGBPoint(0, 0, 0, 0);
3 color->AddRGBPoint(64, 1.0, 0.52, 0.3);
4 color->AddRGBPoint(190.0, 1.00, 1.00, 1.00);
5 color->AddRGBPoint(220.0, 0.20, 0.20, 0.20);

        由于vtkVolumeProperty接受两种形式的颜色传输函数(灰度或者RGB),一次在获取相应的颜色传输函数时,需要首先判断VTKVolumeProperty已经设置的颜色传输类型,其函数为:

1 int GetColorChannels();
2 如果返回为1,则说明设置的是灰度传输函数;
3 如果返回为3,则说明设置的是彩色RGB传输函数。

  根据不同的类型既可通过如下函数获取有效的传输函数:

1 VTKColorTransferFunction* GetRGBTransferFunction();
2 vtkPiecewiseFunction* GetGrayTransferFunction();

光照与阴影
  通过VTKVolumeProperty可以设置体绘制阴影效果(Shading)。阴影效果主要受环境光系数、散射光系数、反射光系数和高光强度四个参数影响。使用vtkVolumeProperty::SetAmbient()设置环境光系数;使用vtkVolumeProperty::SetDiffuse()设置散射光系数;使用vtkVolumeProperty::SetSpecular()设置反射光系数。一般情况下,三个系数的和应该为1。但是有时候,在体绘制过程中为了提高亮度,三值之和会大于1。另外,还有一个参数是高光强度(Specular Power),用于控制体绘制的外观平滑程度。可用于VTKVolumeProperty::SetSpecularPower()设置该参数。vtkVolumeProperty中默认是是关闭阴影效果的,因此需要显式调用ShadeOn()函数来打开阴影效果。一个标准的光照与阴影设置代码如下。

1 volumeProperty->ShadeOn();
2 volumeProperty->SetAmbient(0.4);
3 volumeProperty->SetDiffuse(0.6);
4 volumeProperty->SetSpecular(0.2);

示例演示

        我们对比加与不加梯度不透明度函数两种情况。代码如下。

 1 /**********************************************************************
 2 
 3 Copyright (c) Mr.Bin. All rights reserved.
 4 For more information visit: http://blog.csdn.net/webzhuce
 5 
 6 **********************************************************************/
 7 #include <vtkSmartPointer.h>
 8 #include <vtkImageData.h>
 9 #include <vtkStructuredPoints.h>
10 #include <vtkStructuredPointsReader.h>
11 #include <vtkColorTransferFunction.h>
12 #include <vtkPiecewiseFunction.h>
13 #include <vtkRenderer.h>
14 #include <vtkRenderWindow.h>
15 #include <vtkRenderWindowInteractor.h>
16 #include <vtkVolumeProperty.h>
17 #include <vtkFixedPointVolumeRayCastMapper.h>
18 
19 int main(int argc, char *argv[])
20 {
21     vtkNew<vtkStructuredPointsReader> reader;
22     reader->SetFileName("E:\\TestData\\mummy.128.vtk");
23     reader->Update();
24     vtkNew<vtkFixedPointVolumeRayCastMapper> volumeMapper0;
25     volumeMapper0->SetInputData(reader->GetOutput());
26     volumeMapper0->SetBlendModeToComposite();
27 
28     vtkNew<vtkFixedPointVolumeRayCastMapper> volumeMapper1;
29     volumeMapper1->SetInputData(reader->GetOutput());
30     volumeMapper1->SetBlendModeToComposite();
31 
32     vtkNew<vtkVolumeProperty> volumeProperty0;
33     volumeProperty0->SetInterpolationTypeToLinear();
34     volumeProperty0->SetAmbient(0.4);
35     volumeProperty0->SetDiffuse(0.6);
36     volumeProperty0->SetSpecular(0.2);
37 
38     vtkNew<vtkVolumeProperty> volumeProperty1;
39     volumeProperty1->SetInterpolationTypeToLinear();
40     volumeProperty1->SetAmbient(0.4);
41     volumeProperty1->SetDiffuse(0.6);
42     volumeProperty1->SetSpecular(0.2);
43 
44     vtkNew<vtkPiecewiseFunction> compositeOpacity;
45     compositeOpacity->AddPoint(70,   0.00);
46     compositeOpacity->AddPoint(90,   0.40);
47     compositeOpacity->AddPoint(180,  0.60);
48     volumeProperty0->SetScalarOpacity(compositeOpacity); //设置不透明度传输函数
49     volumeProperty1->SetScalarOpacity(compositeOpacity); //设置不透明度传输函数
50 
51     vtkNew<vtkPiecewiseFunction> volumeGradientOpacity;
52     volumeGradientOpacity->AddPoint(10,  0.0);
53     volumeGradientOpacity->AddPoint(90,  0.5);
54     volumeGradientOpacity->AddPoint(100, 1.0);
55     //volumeProperty0->SetGradientOpacity(volumeGradientOpacity);//设置梯度不透明度效果对比
56     volumeProperty1->SetGradientOpacity(volumeGradientOpacity);//设置梯度不透明度效果对比
57 
58     vtkNew<vtkColorTransferFunction> color;
59     color->AddRGBPoint(0.000,  0.00, 0.00, 0.00);
60     color->AddRGBPoint(64.00,  1.00, 0.52, 0.30);
61     color->AddRGBPoint(190.0,  1.00, 1.00, 1.00);
62     color->AddRGBPoint(220.0,  0.20, 0.20, 0.20);
63     volumeProperty0->SetColor(color);
64     volumeProperty1->SetColor(color);
65 
66     vtkNew<vtkVolume> volume0;
67     volume0->SetMapper(volumeMapper0);
68     volume0->SetProperty(volumeProperty0);
69 
70     vtkNew<vtkVolume> volume1;
71     volume1->SetMapper(volumeMapper1);
72     volume1->SetProperty(volumeProperty1);
73 
74     double leftViewport[4] = { 0.0, 0.0, 0.5, 1.0 };
75     double rightViewport[4] = { 0.5, 0.0, 1.0, 1.0 };
76     vtkNew<vtkRenderer> renderer0;
77     renderer0->SetBackground(1.0, 1.0, 1.0);
78     renderer0->SetViewport(leftViewport);
79     renderer0->AddVolume(volume0);
80 
81     vtkNew<vtkRenderer> renderer1;
82     renderer1->SetBackground(1.0, 1.0, 1.0);
83     renderer1->SetViewport(rightViewport);
84     renderer1->AddVolume(volume1);
85 
86     vtkNew<vtkRenderWindow> renWin;
87     renWin->AddRenderer(renderer0);
88     renWin->AddRenderer(renderer1);
89     renWin->SetSize(640, 480);
90     renWin->SetWindowName("VolumeMapper");
91 
92     vtkNew<vtkRenderWindowInteractor> iren;
93     iren->SetRenderWindow(renWin);
94     renWin->Render();
95     iren->Start();
96 
97     return EXIT_SUCCESS;
98 }

运行结果

 

标签:1.0,函数,color,梯度,VTK,透明度,vtkVolume,绘制,vtkNew
From: https://www.cnblogs.com/ybqjymy/p/17502694.html

相关文章

  • Golang 图片上绘制文字
    之前介绍过使用FreeType-go来绘制字现在相关的包被做了整合,主要是整合到了github.com/golang/freetype和golang.org/x/image/font这里了,所以就有了这篇博客。 例子代码在:https://github.com/golang/freetype/blob/master/example/freetype/main.go packagemainimport(......
  • wxpython使用matplotlib.pyplot绘制GUI嵌入式统计图
    在使用wxpython编写GUI时,如果需要在GUI上显示统计图,这里就可以用到matplotlib.pyplot;一、首先就是导入matplotlib.pyplot模块frommatplotlib.backends.backend_wxaggimportFigureCanvasWxAggasFigureCanvasimportmatplotlib.pyplotasplt然后就需要一个容器,可以理......
  • Flutter 绘制探索 | 操作坐标系范围
    前言在视频【Flutter绘制指南|第二集·坐标系】中,实现了画板区域内的单位坐标系。今天来拓展一下,让坐标系支持变换,比如坐标系的平移和缩放,从而让坐标系的功能更加完备。本文要实现的效果如下,可以通过下方的七个按钮操作坐标系的范围,这样可以查看在当前定义域内的函数曲线,也......
  • 百度地图 鼠标绘制库 bmap-draw 避坑
    1.距离测量工具无法修改单位为米根据官方文档:距离测量类unit string 测量所用单位制,默认为千米'kilometers',另外可接受米'metric'无法对其进行修改this.distance=newDistanceMeasure(scene,{unit:"metric",isSeries,//不连续测量...m......
  • Flutter 绘制探索 | 扇形区域与点击校验
    作者:张风捷特烈0.前言今天来探索一个问题,如何绘制一块扇形区域路径,并且校验触点是否落在扇形区域之中。这个问题对于绘制饼图及处理手势事件校验非常重要。1.扇形区域的定义首先来明确一下扇形区域的表示,如下图所示,一个扇形区域通过五个属性进行描述:属性名类型作用centerO......
  • 【Python】在同一图形中更加优雅地绘制多个子图
    1.引言数据可视化非常重要,有一句俗语叫做一图顶千言,我相信好多小伙伴应该都听说过这句话;即使是有人第一次听到,我想应该也会觉得赞成,这足以说明数据可视化的重要性。我们在前一篇博客中,介绍了如何利用subplot来在一张子图里绘制多个子图,最近我又发现了一种更加优雅地实现,迫不及待地......
  • Unity绘制参考网格
    1.仿制Maya参考网格 usingUnityEngine;publicclassReferenceGridRenderer:MonoBehaviour{//[SerializeField]Colorcolor=newColor(1,1,1,0.5f);[SerializeField][Range(1,1000)]floatrange=20;[SerializeField][Range(0.1f,100)]floatin......
  • [数据分析与可视化] Python绘制数据地图3-GeoPandas使用要点
    本文主要介绍GeoPandas的使用要点。GeoPandas是一个Python开源项目,旨在提供丰富而简单的地理空间数据处理接口。GeoPandas扩展了Pandas的数据类型,并使用matplotlib进行绘图。GeoPandas官方仓库地址为:GeoPandas。GeoPandas的官方文档地址为:GeoPandas-doc。本文主要参考GeoPandasEx......
  • 软件测试|教你用matplotlib绘制热力图
    前言热力图,是一种通过对色块着色来显示数据的统计图表。绘图时,需指定颜色映射的规则。例如,较大的值由较深的颜色表示,较小的值由较浅的颜色表示;较大的值由偏暖的颜色表示,较小的值由较冷的颜色表示,等等。当然,只要我们提供数据,Python就能够绘制出热力图。下面我们就来介绍一下如何......
  • 用JavaScript绘制树状图(具有分支合并功能)的一种方法(其一)
    需求分析在很多模拟经营游戏中,科技树是一项重要的内容,其为玩家提供了各项技术与其前后置科技间的拓扑关系。这些科技树在表现形式上和普通树状图很相似,但由于其频繁的分支合并,为科技树的绘制带来困难。因此,我们需要一种简单的方法来绘制科技树。比如,当用户输入:<!--为了降低用户......