在VTK中,
vtkVolumeRayCastMapper类(在VTK8.x.x已被移除)可用于实现光线投射体数据算法,并生成渲染图元数据传递给vtkVolume对象进行渲染。vtkVolumeRayCastMapper类采用软件方法来实现光线投射算法,精度高但是计算量比较大。其内部两个最重要的函数:
SetVolumeRayCastMapper::SetInput(vtkImageData*) //该函数用于设置输入图像数据。
SetVolumeRayCastMapper::SetVolumeRay(vtkVolumeRayCastFunction*) //该函数用于设置光线投射函数。
vtkVolumeRayCastMapper中计算每条光线在通过体数据后的颜色是通过定义的vtkVolumeRayCastFunction对象实现的。vtkVolumeRayCastFunction是一个虚基类,它有三个子类。
1、vtkVolumeRayCastCompositeFunction该方式通过Alpha合成技术生成每个像素的颜色值。
2、vtkVolumeRayCastMIPFunction最大密度投影函数主要用于对体数据中高灰度值的结构进行可视化。
3、vtkVolumeRayCastIsosurfaceFunction等值面绘制函数能够渲染体数据中特定的等值面。
替代者:
vtkFixedPointVolumeRayCastMapper是一个较好的vtkVolumeRayCastMapper的替代者。该类能够实现基于Alpha合成的体绘制和最大密度投影体绘制方法,能够支持任意类型的一元或独立多元数据。vtkFixedPointVolumeRayCastMapper的使用方法的使用方法与vtkVolumeRayCastMapper基本相同,如支持设置投射光线采样步长、设置图像采样距离、设置自动调节图像采样距离等。
二者的区别:
vtkFixedPointVolumeRayCastFMapper只支持基于Alpha合成的体绘制方法和最大密度体绘制方法,可以通过基类vtkVolumeMapper的接口函数来设置。
void SetBlendModeToComposite();
void SetBlendModeToMaximumIntensity();
void SetBlendModeToMinimumIntensity();
void SetBlendModeToAddictive();
List item
对于Alpha合成体绘制方法,vtkFixedPointVolumeRayCastFMapper类仅支持先插值在分类操作;
vtkFixedPointVolumeRayCastFMapper类支持更多种数据类型。
我们利用vtkFixedPointVolumeRayCastMapper类来显示基于Alpha合成的体绘制方法和最大密度体绘制方法的效果。
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkStructuredPoints.h>
#include <vtkStructuredPointsReader.h>
#include <vtkColorTransferFunction.h>
#include <vtkPiecewiseFunction.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkVolumeProperty.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
int main(int argc, char *argv[])
{
vtkNew<vtkStructuredPointsReader> reader;
reader->SetFileName("E:\\TestData\\mummy.128.vtk");
reader->Update();
vtkNew<vtkFixedPointVolumeRayCastMapper> volumeMapper0;
volumeMapper0->SetInputData(reader->GetOutput());
volumeMapper0->SetBlendModeToComposite();
vtkNew<vtkFixedPointVolumeRayCastMapper> volumeMapper1;
volumeMapper1->SetInputData(reader->GetOutput());
volumeMapper1->SetBlendModeToMaximumIntensity();
vtkNew<vtkVolumeProperty> volumeProperty;
volumeProperty->SetInterpolationTypeToLinear();
volumeProperty->SetAmbient(0.4);
volumeProperty->SetDiffuse(0.6);
volumeProperty->SetSpecular(0.2);
vtkNew<vtkPiecewiseFunction> compositeOpacity;
compositeOpacity->AddPoint(70, 0.00);
compositeOpacity->AddPoint(90, 0.40);
compositeOpacity->AddPoint(180, 0.60);
volumeProperty->SetScalarOpacity(compositeOpacity); //设置不透明度传输函数
vtkNew<vtkPiecewiseFunction> volumeGradientOpacity;
volumeGradientOpacity->AddPoint(10, 0.0);
volumeGradientOpacity->AddPoint(90, 0.5);
volumeGradientOpacity->AddPoint(100, 1.0);
//volumeProperty->SetGradientOpacity(volumeGradientOpacity);//设置梯度不透明度效果对比
vtkNew<vtkColorTransferFunction> color;
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, 0.20, 0.20, 0.20);
volumeProperty->SetColor(color);
vtkNew<vtkVolume> volume0;
volume0->SetMapper(volumeMapper0);
volume0->SetProperty(volumeProperty);
vtkNew<vtkVolume> volume1;
volume1->SetMapper(volumeMapper1);
volume1->SetProperty(volumeProperty);
double leftViewport[4] = { 0.0, 0.0, 0.5, 1.0 };
double rightViewport[4] = { 0.5, 0.0, 1.0, 1.0 };
vtkNew<vtkRenderer> renderer0;
renderer0->SetBackground(1.0, 1.0, 1.0);
renderer0->SetViewport(leftViewport);
renderer0->AddVolume(volume0);
vtkNew<vtkRenderer> renderer1;
renderer1->SetBackground(1.0, 1.0, 1.0);
renderer1->SetViewport(rightViewport);
renderer1->AddVolume(volume1);
vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(renderer0);
renWin->AddRenderer(renderer1);
renWin->SetSize(640, 480);
renWin->SetWindowName("VolumeMapper");
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
renWin->Render();
iren->Start();
return EXIT_SUCCESS;
}
效果图:
这个下面是最大密度投影法的结果:
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkStructuredPoints.h>
#include <vtkStructuredPointsReader.h>
//#include <vtkVolumeRayCastMIPFunction.h>
//#include <vtkVolumeRayCastMapper.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#include <vtkColorTransferFunction.h>
#include <vtkPiecewiseFunction.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkVolumeProperty.h>
#include <vtkAxesActor.h>
#include <vtkImageShiftScale.h>
#include <vtkImageCast.h>
int main(int argc, char *argv[]) {
vtkSmartPointer<vtkStructuredPointsReader> reader =
vtkSmartPointer<vtkStructuredPointsReader>::New();
reader->SetFileName("../data/ironProt.vtk");//mummy.128.vtk
reader->Update();
vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> volumeMapper =
vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
volumeMapper->SetInputData(reader->GetOutput());
volumeMapper->SetBlendModeToMaximumIntensity();
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, 0.20, 0.20, 0.20);
volumeProperty->SetColor(color);
vtkSmartPointer<vtkVolume> volume =
vtkSmartPointer<vtkVolume>::New();
volume->SetMapper(volumeMapper);
volume->SetProperty(volumeProperty);
vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New();
ren->SetBackground(1.0, 1.0, 1.0);
ren->AddVolume(volume);
vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
renWin->AddRenderer(ren);
renWin->SetSize(640, 480);
renWin->Render();
renWin->SetWindowName("VolRenderingApp");
vtkSmartPointer<vtkRenderWindowInteractor> iren =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
iren->SetRenderWindow(renWin);
ren->ResetCamera();
renWin->Render();
iren->Start();
return EXIT_SUCCESS;
}
效果如下:
如果是DICOM影像则替换一下即可
std::string str = "/media/xuli/TOSHIBA EXT/CTP-data/CTP-data-dicom/同层";
vtkSmartPointer<vtkDICOMImageReader> reader = vtkSmartPointer<vtkDICOMImageReader>::New();
reader->SetDirectoryName(str.c_str());
reader->Update();