三维重建VTK体绘制,Ray Casting和最大密度投影

体绘制

体绘制算法实现要比面绘制算法更加复杂。体绘制算法实现了对重建模型细节特征的实现,相比于面绘制的实现,它更能够保证医学影像信息的完整性。体绘制实现中要考虑到三维体数据中灰度和梯度等特性问题,也要考虑到光线对模型绘制的影像,因此在体绘制中设置一个光学模型。现在一般有以下三种模型。
(1)光线吸收模型
现阶段,针对集中实现的光学模型而言,光线吸收模型是其中实现较为简单的一种模型。在一个三维空间中,其中的体素粒子能够对射入的光线进行完全吸收,即不反射。如公式表示。
在这里插入图片描述
式中:参数S为光线的投射方向的长度,表示距离为S处光线强度,表初始光强。
(2)光线发射模型
光线发射模型则与光线吸收模型形成反差,在该三维空间内,将体素粒子当作透明处理,不具备光线吸收,被认为能够发射光线。如公式表示。 在这里插入图片描述
式中:表初始光强,S表沿着光线射入方向长度。
(3)光线吸收和发射复合模型
在光线吸收模型和光线发射模型的基础上,又设计实现了一种复合的光学模型,该模型集成了光线吸收和光线反射。相比于上面两种操作单一的光线处理模型,这种复合的模型能够更为全面和客观的还原三维空间中的光学特征,即可以吸收也可以反射。所以这种复合光学模型更加复合大众需求,也就更为流行和被广泛应用。如公式表示。
在这里插入图片描述
式中:表光强,表透明度,表颜色值,表不透明度。

Ray Casting(光线投射算法)

光线投射法是体绘制的方法之一,也是现阶段较为流行的一种,基于图像空间,结合体数据的颜色、灰度不透明度和梯度不透明度合成图像。通过在颜色传输函数、灰度不透明度传输函数和梯度不透明度传输函数设置当前图像渲染效果最佳的参数来实现对重建三维模型颜色值和不透明度的渲染,利用光线吸收模型对通过颜色传输函数获取的颜色进行累加,直到光线穿过体数据,针对三维重建模型的平面像素的渲染效果,进而生成展示图像。Ray Casting算法的优点在于相比面绘制中的MC表面重建,它能够更加精确地模拟原始体数据,但同时能够明显看出来计算量相比于面绘制中的MC表面算法要大很多,如果想要实现实时渲染,那么对计算机图像处理的硬件要求是比较高。

基于VTK的Ray Casting实现

在进行Ray Casting算法的具体实现前要特别注意一点,算法是基于VTK类库实现,在VTK7.0版本之前算法的实现主要基于vtkVolumeRayCastMapper类和vtkVolumeRayCastCompositeFunction类,在VTK7.0之后类库删除了这两个类,为此我们使用vtkFixedPointVolumeRayCastMapper类来替代实现。
体绘制的实现不同于面绘制,体绘制注重于细节特征的绘制实现,所以在体绘制算法实现过程中要对体属性进行设置,主要从颜色、灰度不透明度和梯度不透明度三方面进行设置。

  • (1)灰度不透明度设置
    基于VTK类库中vtkPiecewiseFunction类实现三维模型重建过程的灰度不透明度设置,在算法实现中该函数采用了分段式线性标量映射函数。通过在光线投射中将采样点灰度值映射为不透明度来决定颜色最终值。
    基于vtkPiecewiseFunction类实现不透明度设置一般有设置一个断点或两个断点两种方式。借助该类中静态函数Addpoint()实现将灰度值映射为不透明度。在一个断点的设置中,有两个参数分为自变量和映射值,来代表灰度值和不透明度。在两个断点的实现中,是设置两个断点用作一条线段的两个断点,在进行相关映射实现。本文对比实现了这两种方式,第一种方式中设置参数分别为(100,0.00)、(140,0.40)和(180,0.60);第二种方式中设置参数 (-3024, 0, 0.5, 0.0)、(-16, 0, 0.49, .61)、(641, 0.72,0.5, 0.0)和(3071, 0.71, 0.5, 0.0)。
  • (2)梯度不透明度设置
    梯度不透明度的设置同样是基于VTK类库中vtkPiecewiseFunction类实现,不同的是梯度不透明度的绑定是通过类中的静态函数SetGradientOpacity()实现。该函数的实现有助加强过渡区域的渲染,CT等放射性检测设备获取的医学影像在该区域的梯度值变化是剧烈的,不同组织结构临界区域梯度值可能差别很大。
    基于vtkPiecewiseFunction类实现不透明度设置,借助该类中静态函数Addpoint()实现将梯度值映射为不透明度。在设置中,有两个参数分为自变量和映射值,来代表梯度值和不透明度。本文对比实现了这两种方式,第一种方式中设置参数分别为(10,0.00)、(90,0.50)和(100,1.00)。
  • (3)颜色设置
    颜色传输函数是基于VTK类库中vtkColorTransferFunction类实现,基本实现和不透明函数实现方式相同。不过对于参数的设置会存在差别。通过类中静态函数AddRGBPoint()设置基于RGB值设定的颜色参数,本系统开发中参数实现为(0.000, 0.00, 0.00, 0.00)、(64.00, 1.00, 0.52, 0.30)、(190.0, 1.00, 1.00, 1.00)和(220.0, 1.00, 1.00, 1.00)。
    在这里插入图片描述
    首先,基于vtkFixedPointVolumeRayCastMapper类创建智能指针,通过类中的静态函数SetInputConnection()和SetBlendModeToComposite(),获取经过平滑处理体数据并进行光线处理。基于vtkVolumeProperty类创建智能指针,定义体属性数据对象,通过类中静态函数ShadeOn()打开光照/阴影测试,通过静态函数SetScalarOpacity()、SetGradientOpacity()和SetColor()来依次添加灰度不透明度、梯度不透明度和颜色;基于vtkPiecewiseFunction类创建两个不同智能指针,用来设置灰度不透明度和梯度不透明度,通过多参数测试选取可视化效果最佳的参数实现对三维模型的渲染;基于vtkColorTransferFunction类设置颜色函数同样,通过多参数测试选取可视化效果最佳的参数实现对三维模型的渲染。最后使用vtkVolume类完成数据渲染。

代码实现

//体绘制

#include<vtkRenderWindowInteractor.h>
#include<vtkDICOMImageReader.h>
#include<vtkCamera.h>
#include<vtkActor.h>
#include<vtkRenderer.h>
#include<vtkVolumeProperty.h>
#include<vtkProperty.h>
#include<vtkPolyDataNormals.h>
#include<vtkImageShiftScale.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#include<vtkPiecewiseFunction.h>
#include<vtkColorTransferFunction.h>
#include<vtkRenderWindow.h>
#include<vtkImageCast.h>
#include<vtkOBJExporter.h>
#include<vtkOutlineFilter.h>
#include<vtkPolyDataMapper.h>
#include <vtkFixedPointVolumeRayCastMIPHelper.h>
#include<vtkInteractorStyleTrackballCamera.h>
#include<vtkImageGaussianSmooth.h>
#include<vtkMetaImageReader.h>
#include<vtkLODProp3D.h>
#include<vtkLoopSubdivisionFilter.h>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL);//基于vtk-7.0,所以是OpenGL,若基于VTK-8.0则是OpenGL2
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL);
//体绘制加速

//Gpu光照映射
#include<vtkGPUVolumeRayCastMapper.h>

#include<iostream>

int main()
{

	//定义绘制器;
	vtkRenderer* aRenderer = vtkRenderer::New();//指向指针;
	vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
	renWin->AddRenderer(aRenderer);

	vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New();
	iren->SetRenderWindow(renWin);

	vtkSmartPointer<vtkDICOMImageReader> reader = vtkSmartPointer<vtkDICOMImageReader>::New();
	reader->SetDirectoryName("D:\\Bishe\\Projects\\DICOM\\dicom\\lung");
	reader->SetDataByteOrderToLittleEndian();

	//高斯平滑
	vtkSmartPointer<vtkImageGaussianSmooth> gaussianSmoothFilter =
		vtkSmartPointer<vtkImageGaussianSmooth>::New();
	gaussianSmoothFilter->SetInputConnection(reader->GetOutputPort());
	gaussianSmoothFilter->SetDimensionality(3);
	gaussianSmoothFilter->SetRadiusFactor(5);
	gaussianSmoothFilter->SetStandardDeviation(1);
	gaussianSmoothFilter->Update();

	vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> volumeMapper =
		vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
	volumeMapper->SetInputConnection(gaussianSmoothFilter->GetOutputPort());

	vtkSmartPointer<vtkVolumeProperty> volumeProperty =
		vtkSmartPointer<vtkVolumeProperty>::New();
	volumeProperty->SetInterpolationTypeToLinear();
	volumeProperty->ShadeOn();
	volumeProperty->SetAmbient(0.4);
	volumeProperty->SetDiffuse(0.6);
	volumeProperty->SetSpecular(0.2);

	vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity =
		vtkSmartPointer<vtkPiecewiseFunction>::New();
	compositeOpacity->AddPoint(70, 0.00);
	compositeOpacity->AddPoint(90, 0.40);
	compositeOpacity->AddPoint(180, 0.60);
	volumeProperty->SetScalarOpacity(compositeOpacity);

	//设置梯度不透明属性
	vtkSmartPointer<vtkPiecewiseFunction> volumeGradientOpacity =
		vtkSmartPointer<vtkPiecewiseFunction>::New();
	volumeGradientOpacity->AddPoint(10, 0.0);
	volumeGradientOpacity->AddPoint(90, 0.5);
	volumeGradientOpacity->AddPoint(100, 1.0);
	volumeProperty->SetGradientOpacity(volumeGradientOpacity);//设置梯度不透明度效果对比

	vtkSmartPointer<vtkColorTransferFunction> color =
		vtkSmartPointer<vtkColorTransferFunction>::New();
	color->AddRGBPoint(0.000, 0.00, 0.00, 0.00);
	color->AddRGBPoint(64.00, 1.00, 0.52, 0.30);
	color->AddRGBPoint(190.0, 1.00, 1.00, 1.00);
	color->AddRGBPoint(220.0, 1.00, 1.00, 1.00);
	volumeProperty->SetColor(color);

	vtkSmartPointer<vtkVolume> volume =
		vtkSmartPointer<vtkVolume>::New();
	volume->SetMapper(volumeMapper);
	volume->SetProperty(volumeProperty);

	vtkOutlineFilter* outlineData = vtkOutlineFilter::New();//线框;
	vtkPolyDataMapper* mapOutline = vtkPolyDataMapper::New();
	mapOutline->SetInputConnection(outlineData->GetOutputPort());
	vtkActor* outline = vtkActor::New();
	outline->SetMapper(mapOutline);
	outline->GetProperty()->SetColor(0, 0, 0);//背景纯黑色;

	aRenderer->AddVolume(volume);
	aRenderer->AddActor(outline);
	aRenderer->SetBackground(1, 1, 1);
	aRenderer->ResetCamera();

	//重设相机的剪切范围;
	aRenderer->ResetCameraClippingRange();
	renWin->SetSize(800, 800);
	renWin->SetWindowName("测试");

	vtkRenderWindowInteractor* iren2 = vtkRenderWindowInteractor::New();
	iren2->SetRenderWindow(renWin);

	//设置相机跟踪模式
	vtkInteractorStyleTrackballCamera* style = vtkInteractorStyleTrackballCamera::New();
	iren2->SetInteractorStyle(style);

	renWin->Render();
	iren2->Initialize();
	iren2->Start();

	return EXIT_SUCCESS;

}

实现效果

在这里插入图片描述

最大密度投影

体绘制最大密度投影算法,一般通过30张左右切片来形成三维模型中的信息,并在平面中进行投影。针对读取DICOM序列图像获得的三维体数据中的高灰度值机构进行可视化处理。
最大密度投影体绘制算法同样是基于vtkFixedPointVolumeRayCastMapper类,不同与Ray Casting体绘制算法中通过vtkFixedPointVolumeRayCastMapper类中静态函数SetBlendModeToComposite()实现,最大密度投影算法通过vtkFixedPointVolumeRayCastMapper类中SetBlendModeToMaximumIntensity()函数实现。

代码实现

//体绘制

#include<vtkRenderWindowInteractor.h>
#include<vtkDICOMImageReader.h>
#include<vtkCamera.h>
#include<vtkActor.h>
#include<vtkRenderer.h>
#include<vtkVolumeProperty.h>
#include<vtkProperty.h>
#include<vtkPolyDataNormals.h>
#include<vtkImageShiftScale.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#include<vtkPiecewiseFunction.h>
#include<vtkColorTransferFunction.h>
#include<vtkRenderWindow.h>
#include<vtkImageCast.h>
#include<vtkOBJExporter.h>
#include<vtkOutlineFilter.h>
#include<vtkPolyDataMapper.h>
#include <vtkFixedPointVolumeRayCastMIPHelper.h>
#include<vtkInteractorStyleTrackballCamera.h>
#include<vtkRenderingVolumeOpenGL2ObjectFactory.h>
#include<vtkRenderingOpenGL2ObjectFactory.h>
#include<vtkMetaImageReader.h>
#include<vtkLODProp3D.h>


//体绘制加速

//Gpu光照映射
#include<vtkGPUVolumeRayCastMapper.h>

#include<iostream>

int main()
{

	vtkObjectFactory::RegisterFactory(vtkRenderingOpenGL2ObjectFactory::New());
	vtkObjectFactory::RegisterFactory(vtkRenderingVolumeOpenGL2ObjectFactory::New());

	//定义绘制器;
	vtkRenderer* aRenderer = vtkRenderer::New();//指向指针;
	vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
	renWin->AddRenderer(aRenderer);

	vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New();
	iren->SetRenderWindow(renWin);

	vtkSmartPointer<vtkDICOMImageReader> reader = vtkSmartPointer<vtkDICOMImageReader>::New();
	reader->SetDirectoryName("D:\\Bishe\\Projects\\DICOM\\dicom\\lung");
	reader->SetDataByteOrderToLittleEndian();


	//图像数据预处理,类型转换:通过 vtkimageCast 将不同类型数据集转化为 vtk 可以处理的数据集;
	vtkImageCast* cast_file = vtkImageCast::New();
	cast_file->SetInputConnection(reader->GetOutputPort());
	cast_file->SetOutputScalarTypeToUnsignedShort();
	cast_file->Update();


	vtkSmartPointer<vtkFixedPointVolumeRayCastMIPHelper> rayCastFun =
		vtkSmartPointer<vtkFixedPointVolumeRayCastMIPHelper>::New();

	vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> volumeMapper =
		vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
	volumeMapper->SetInputData(reader->GetOutput());
	//volumeMapper->Set
		//SetVolumeRayCastMapperFunction(rayCastFun);//必须设置,否则出错

	vtkSmartPointer<vtkVolumeProperty> volumeProperty =
		vtkSmartPointer<vtkVolumeProperty>::New();
	volumeProperty->SetInterpolationTypeToLinear();
	volumeProperty->ShadeOn();
	volumeProperty->SetAmbient(0.4);
	volumeProperty->SetDiffuse(0.6);
	volumeProperty->SetSpecular(0.2);

	vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity =
		vtkSmartPointer<vtkPiecewiseFunction>::New();
	compositeOpacity->AddPoint(70, 0.00);
	compositeOpacity->AddPoint(90, 0.40);
	compositeOpacity->AddPoint(180, 0.60);
	volumeProperty->SetScalarOpacity(compositeOpacity);

	vtkSmartPointer<vtkColorTransferFunction> color =
		vtkSmartPointer<vtkColorTransferFunction>::New();
	color->AddRGBPoint(0.000, 0.00, 0.00, 0.00);
	color->AddRGBPoint(64.00, 1.00, 0.52, 0.30);
	color->AddRGBPoint(190.0, 1.00, 1.00, 1.00);
	color->AddRGBPoint(220.0, 1.00, 1.00, 1.00);
	volumeProperty->SetColor(color);

	vtkSmartPointer<vtkVolume> volume =
		vtkSmartPointer<vtkVolume>::New();
	volume->SetMapper(volumeMapper);
	volume->SetProperty(volumeProperty);

	double volumeView[4] = { 0,0,0.5,1 };

	vtkOutlineFilter* outlineData = vtkOutlineFilter::New();//线框;
	outlineData->SetInputConnection(reader->GetOutputPort());
	vtkPolyDataMapper* mapOutline = vtkPolyDataMapper::New();
	mapOutline->SetInputConnection(outlineData->GetOutputPort());
	vtkActor* outline = vtkActor::New();
	outline->SetMapper(mapOutline);
	outline->GetProperty()->SetColor(0, 0, 0);//背景纯黑色;

	aRenderer->AddVolume(volume);
	aRenderer->AddActor(outline);
	aRenderer->SetBackground(1, 1, 1);
	aRenderer->ResetCamera();

	//重设相机的剪切范围;
	aRenderer->ResetCameraClippingRange();
	renWin->SetSize(800, 800);
	renWin->SetWindowName("测试");

	vtkRenderWindowInteractor* iren2 = vtkRenderWindowInteractor::New();
	iren2->SetRenderWindow(renWin);

	//设置相机跟踪模式
	vtkInteractorStyleTrackballCamera* style = vtkInteractorStyleTrackballCamera::New();
	iren2->SetInteractorStyle(style);

	renWin->Render();
	iren2->Initialize();

	iren2->Start();

	vtkOBJExporter* porter = vtkOBJExporter::New();
	porter->SetFilePrefix("D:\\Bishe\\Projects\\DICOM\\dicom");
	porter->SetInput(renWin);
	porter->Write();
	porter->Update();

	return EXIT_SUCCESS;

}

实现效果

在这里插入图片描述

  • 如有错误表述,欢迎指正,感谢!
  • 2
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: 这个三维扫描数据的vtk绘制程序设计.zip是一个基于VTK的程序设计,用于绘制三维扫描数据。该程序支持常见的数据格式,如DICOM、NRRD和MHA等,并可通过用户界面进行数据加载和显示。在程序中,可以对数据进行不同方向的切片、平移、缩放和旋转等操作,以显示不同视角下的图像。此外,该程序还提供了一个ROI(区域感兴趣)选择功能,可用于选择感兴趣区域,并在其中进行进一步的测量和分析。 该程序通过使用VTK的各种模块和可视化工具来实现,具有强大的绘图功能和灵活的用户交互性。在编写程序时,考虑了诸多因素,如稳定性、效率、易用性和可维护性等,以确保程序能够在不同的操作系统上稳定运行。 总之,这个三维扫描数据的vtk绘制程序设计.zip是一个功能丰富、易用性好、界面友好的程序,具有广泛的应用价值,可用于医学、工程和科研领域中的三维可视化操作。 ### 回答2: 三维扫描数据的vtk绘制程序设计.zip是一份使用VTK(Visualization Toolkit)库开发的程序设计文件,用于绘制三维扫描数据的模型。该程序设计文件包含了一个完整的VTK项目,其中包含了整个程序的源代码、库文件及可执行程序等。 该程序设计文件的主要功能是将三维扫描数据转换为三维模型,以直观地展示出扫描的内部结构和组成。该程序设计文件通过读取和处理数据文件中的数据信息,将其转换为各种绘制算法,并最终展示在屏幕上。该程序适用于医学、生物、机械等各个领域。 该程序设计文件具有以下优点: 1. 可以轻松处理各种类型的三维扫描数据,包括CT、MRI、PET等不同来源的数据。 2. 可以根据不同的数据特点进行灵活的绘制,支持不同的绘制算法,如蒙皮、立方、等值面等。 3. 程序的界面友好,可以根据用户需求进行自定义设置,并支持交互式绘制,增强用户验感。 总之,三维扫描数据的vtk绘制程序设计.zip提供了一种灵活、高效、直观的三维扫描数据处理方法,可适用于各种领域的应用需求。 ### 回答3: 这个文件夹中包含了一个使用VTK绘制三维扫描数据的程序。VTK是一种开源的图形处理库,它可以用来处理和显示三维数据。这个程序可以加载三维扫描数据文件,然后将数据转换为绘制,再使用VTK绘制结果显示出来。 这个程序的设计和实现涉及到了多个方面的知识和技术,比如数据结构、算法、计算机图形学等等。在程序中,数据结构用来存储和处理三维扫描数据,算法用来进行数据处理和绘制,计算机图形学知识则用于显示绘制结果。 用户可以使用这个程序来查看三维扫描数据的内部结构,从而更好地理解和诊断疾病。同时,用户也可以通过修改程序代码来实现自己的需求,比如改变绘制方式、加入交互功能等等。 总之,这个程序是一个非常有用的工具,可以帮助医生和研究人员更好地理解和分析三维扫描数据。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值