VTK教程5--------体绘制

将第三讲的工程备份一份,后续的教程都会基于该教程讲解。由于篇幅问题,我不会贴上所有的代码,但是会给出pipeline流程图和关键代码,如果你对前面的教程掌握较好,那么通过pipeline流程图自己也能实现体绘制。
一般来说,体绘制的数据来源于扫描仪器的产生,比如MRI,CT,超声等等,但是各种仪器,或者说同类仪器由不同厂家生产,其扫描得到的原始数据有或多或少的差别,所以定义了一些标准格式,比如dicom。有人觉得拿到dicom格式的图像就万事大吉,体绘制就会极其顺利。其实不是的,本人在初次通过vtk进行体绘制的时候,死活读取不到数据,国内外的网站搜寻了一大堆,各种在论坛和前辈请教。甚至把数据传给别人依旧不能重建出来,其中的一种情况就是你拿到的数据已经经过了处理,比如压缩。
那么,对于不同格式的数据,我们有没有一个统一的办法解决问题呢?答案是肯定的,在vtk中有一个功能强大的类叫作vtkImageData,其实你通过vtk提供的各种reader去读取三维切片序列,或者直接读取一个三维图像,最终也要转换为vtkImageData格式。所以,当vtk中没有提供直接读取的reader,或者说直接读取的reader读取不到图像,我们依旧可以通过填写vtkImageData中的数据来实现体绘制。好了,扯得有点多了,直接上pipeline流程图:
VTK教程5--------体绘制_第1张图片
先总体讲一下,本质上还是和cone例子中的流程一直,该有的data,mapper,actor(这里是vtkVolum),renderer都有,将他们串联起来就实现了体绘制。在途中的vtkxxxReader代表的是vtk中原生自带的所有reader,比如读取dicom、bmp、jpg这些格式的reader,如果你的图像格式可以通过原生reader读取到,那么调用GetOutputData也就能够得到vtkImagedata。如果你拿到的格式没有原生reader,那么你可以通过C++的fstream来读取,只需要把vtkImagedata填好就可以了。另外,说一下vtkVolumeProperty类,顾名思义是控制体绘制的参数的,比如光照,颜色等等。另外两个类vtkColorTransferFunction和vtkPiecewiseFunction分别控制体绘制的颜色和透明度,设置好后再传给vtkVolumeProperty。例如可以通过vtkColorTransferFunction可以改变骨骼的颜色,通过vtkPiecewiseFunction来讲人体的其他组织设置成透明,那么最后就只剩下骨骼。下面贴出填写vtkImagedata的代码:

	this->pvtkImageData = vtkImageData::New();
	this->pvtkImageData->SetDimensions(x, y, z); // 设置渲染数据的长宽高,俗称三维
	this->pvtkImageData->SetSpacing(dx, dy, dz); // 设置三维的间隔,也就是两个像素点之间的间隔
	this->pvtkImageData->SetOrigin(0.0, 0.0, 0.0); // 设置原点
	this->pvtkImageData->AllocateScalars(VTK_UNSIGNED_SHORT, 1); // 该函数分配内存,具体的分配大小由两个函数参数共同决定
	                                                             // 在这里代表的意思是,分配了x * y * z * sizeof(unsigned short * 1)这么大的内存
	unsigned short *ptr = (unsigned short *)this->pvtkImageData->GetScalarPointer(); // 获取存储data数据的地址
	memcpy(ptr, targetdata, x * y * z * sizeof(unsigned short * 1); // 将目标数据拷贝到vtkImageData中

接下里给出一些颜色和透明度的参考值,透明度映射:

	this->popacityTransferFunction = vtkPiecewiseFunction::New();
	this->popacityTransferFunction->AddPoint(1000, 0.0);
	this->popacityTransferFunction->AddPoint(4000, 0.68);
	this->popacityTransferFunction->AddPoint(7000, 0.83);

颜色映射:

	this->pvtkColorTransferFunction = vtkColorTransferFunction::New();
	this->pvtkColorTransferFunction->AddHSVPoint(1000, 0.042, 0.73, 0.55);
	this->pvtkColorTransferFunction->AddHSVPoint(2500, 0.042, 0.73, 0.55, 0.5, 0.92);
	this->pvtkColorTransferFunction->AddHSVPoint(4000, 0.088, 0.67, 0.88);
	this->pvtkColorTransferFunction->AddHSVPoint(5500, 0.088, 0.67, 0.88, 0.33, 0.45);
	this->pvtkColorTransferFunction->AddHSVPoint(7000, 0.95, 0.063, 1.0);

vtkVolumeProperty的设置:

	this->pvtkVolumeProperty->SetColor(pvtkColorTransferFunction);
	this->pvtkVolumeProperty->SetScalarOpacity(popacityTransferFunction);
	this->pvtkVolumeProperty->SetInterpolationTypeToLinear();
	this->pvtkVolumeProperty->ShadeOn();
	this->pvtkVolumeProperty->SetShade(0, 1);
	this->pvtkVolumeProperty->SetDiffuse(0.9);
	this->pvtkVolumeProperty->SetAmbient(0.1);
	this->pvtkVolumeProperty->SetSpecular(0.2);
	this->pvtkVolumeProperty->SetSpecularPower(10.0);
	this->pvtkVolumeProperty->SetComponentWeight(0, 1);
	this->pvtkVolumeProperty->SetDisableGradientOpacity(1);
	this->pvtkVolumeProperty->DisableGradientOpacityOn();
	this->pvtkVolumeProperty->SetScalarOpacityUnitDistance(0.891927);

最终,渲染本文末尾共享的数据,可以得到如下效果:
VTK教程5--------体绘制_第2张图片
图中渲染的是一个头部MRI图像。
如果对颜色按照如下代码进行修改:

	this->popacityTransferFunction->AddPoint(1000, 0.0);
	this->popacityTransferFunction->AddPoint(1150, 0.68);
	this->popacityTransferFunction->AddPoint(1300, 0.83);
	this->popacityTransferFunction->AddPoint(1301, 0);

将得到这样一幅图VTK教程5--------体绘制_第3张图片
大部分人体组织都看不见了,只剩下一个轮廓。

大脑图像下载

更多VTK教程,请VX搜索CodeKit。

你可能感兴趣的:(VTK教程,体绘制,vtk,图像格式,vtkImagedata,三维重建)