今天我们来介绍一下MedBeyond程序中,VR图像是怎么显示的,VR是Volume Renderring的缩写,相对于2D图像,体绘制能提供器官的立体信息。
体绘制技术有很多种,例如光线追踪Ray tracing、光线投射Ray Casting,这里不做过多介绍,重点讲解VTK中如何实现VR图像。
通过上图可知,体绘制的输出结果是一张二维图像,只不过相对于普通的二维图像而言,它附加的信息更多一些,例如深度信息、颜色等;有输出就必须有输入,舞台提供了,就必须有演员,VTK中与体绘制相关的是vtkVolume类,其继承体系如下:
演员虽然有了,但此时数据还是最原始的CT值,就是一连串代表灰度的数字,也就是说,此时的演员还是素颜的,那它是如何变成带有色彩的图像的?它还需要一个化妆师,在VTK中vtkVolumeProperty、vtkColorTransferFunction、vtkPiecewiseFunction类就扮演者装扮vtkVolume的任务:
this->m_property->SetColor(this->m_colorFun);
this->m_property->SetScalarOpacity(this->m_opacityFun);
this->m_volume->SetProperty(this->m_property);
通过名字可见,它们只是vtkVolume的属性,并不是真正将灰度值映射成彩色图片的,真正执行映射任务的是Mapper,Mapper根据属性执行映射,在VTK中有多种与体绘制相关的Mapper:
vtkFixedPointVolumeRayCastMapper
vtkGPUVolumeRayCastMapper
vtkSmartVolumeMapper
vtkFixedPointVolumeRayCastMapper是用纯软件方式实现体绘制,也就是利用CPU进行绘制,与之相对应的是vtkGPUVolumeRayCastMapper,根据名字可知是利用GPU进行绘制,其速度要比CPU更快,如果程序的环境是不固定的,可能有GPU,也可能没有GPU,可以使用vtkSmartVolumeMapper,他会根据环境自动选择是使用CPU还是GPU。
this->m_volume->SetMapper(this->m_CurMapper->GetMapper());
现在让我们再回到演员的属性上,Mapper在绘制时,会根据属性去将灰度映射成彩色,那就会有个颜色映射表,此外,还有透明度映射表,不同的表就代表不同的绘制模式。
colorfun->AddRGBPoint(-3024, 0, 0, 0, 0.5, 0.0);
colorfun->AddRGBPoint(-155, .55, .25, .15, 0.5, .92);
colorfun->AddRGBPoint(217, .88, .60, .29, 0.33, 0.45);
colorfun->AddRGBPoint(420, 1, .94, .95, 0.5, 0.0);
colorfun->AddRGBPoint(3071, .83, .66, 1, 0.5, 0.0);
opacity->RemoveAllPoints();
opacity->AddPoint(-3024, 0, 0.5, 0.0);
opacity->AddPoint(-155, 0, 0.5, 0.92);
opacity->AddPoint(217, .68, 0.33, 0.45);
opacity->AddPoint(420, .83, 0.5, 0.0);
opacity->AddPoint(3071, .80, 0.5, 0.0);
mapper->SetBlendModeToComposite();
property->ShadeOn();
property->SetAmbient(0.1);
property->SetDiffuse(0.9);
property->SetSpecular(0.2);
property->SetSpecularPower(10.0);
property->SetScalarOpacityUnitDistance(0.8919);
MIP绘制模式:
MIP绘制模式对应的映射表:
colorfun->AddRGBSegment(0.0, 1.0, 1.0, 1.0, 255.0, 1.0, 1.0, 1.0);
opacity->AddSegment(config->m_opacityLevel - 0.5config->m_opacityWindow, 0.0,
config->m_opacityLevel + 0.5config->m_opacityWindow, 1.0);
mapper->SetBlendModeToMaximumIntensity();