此代码来源于《三维图像编程实验》周振环 郑小中 赵明著 ,第三章,三正交面。但是源码没有显示冠状面,失状面,横断面,随怀疑出错,修改后如下,貌似正确。
#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingContextOpenGL2)
VTK_MODULE_INIT(vtkRenderingFreeType)
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkVolume16Reader.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkOutlineFilter.h"
#include "vtkCamera.h"
#include "vtkStripper.h"
#include "vtkLookupTable.h"
#include "vtkImageDataGeometryFilter.h"
#include "vtkProperty.h"
#include "vtkPolyDataNormals.h"
#include "vtkContourFilter.h"
#include "vtkImageData.h"
#include "vtkImageMapToColors.h"
#include "vtkImageActor.h"
int main()
{
vtkRenderer* aRenderer = vtkRenderer::New();
vtkRenderWindow *renWin = vtkRenderWindow::New();
renWin->AddRenderer(aRenderer);
vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renWin);
//读取图像
vtkVolume16Reader *v16 = vtkVolume16Reader::New();
v16->SetDataDimensions(64, 64);
v16->SetDataByteOrderToLittleEndian();
v16->SetFilePrefix("E:/vtk/VTKData/Data/headsq/quarter");
v16->SetImageRange(1, 93);
v16->SetDataSpacing(3.2, 3.2, 1.5);
v16->Update();
//抽取皮肤
vtkContourFilter *skinExtractor = vtkContourFilter::New();
skinExtractor->SetInputConnection(v16->GetOutputPort());
skinExtractor->SetValue(0, 500);
vtkPolyDataNormals *skinNormals = vtkPolyDataNormals::New();
skinNormals->SetInputConnection(skinExtractor->GetOutputPort());
skinNormals->SetFeatureAngle(60.0);
vtkStripper* skinStripper = vtkStripper::New();
skinStripper->SetInputConnection(skinNormals->GetOutputPort());
vtkPolyDataMapper* skinMapper = vtkPolyDataMapper::New();
skinMapper->SetInputConnection(skinStripper->GetOutputPort());
skinMapper->ScalarVisibilityOff();
vtkActor* skin = vtkActor::New();
skin->SetMapper(skinMapper);
skin->GetProperty()->SetDiffuseColor(1, .49, .25);
skin->GetProperty()->SetSpecular(.3);
skin->GetProperty()->SetSpecularPower(20);
//抽取骨头
vtkContourFilter* boneExtractor = vtkContourFilter::New();
boneExtractor->SetInputConnection(v16->GetOutputPort());
boneExtractor->SetValue(0, 1150);
vtkPolyDataNormals* boneNormals = vtkPolyDataNormals::New();
boneNormals->SetInputConnection(boneExtractor->GetOutputPort());
boneNormals->SetFeatureAngle(60.0);
vtkStripper *boneStripper = vtkStripper::New();
boneStripper->SetInputConnection(boneNormals->GetOutputPort());
vtkPolyDataMapper* boneMapper = vtkPolyDataMapper::New();
boneMapper->SetInputConnection(boneStripper->GetOutputPort());
boneMapper->ScalarVisibilityOff();
vtkActor* bone = vtkActor::New();
bone->SetMapper(boneMapper);
bone->GetProperty()->SetDiffuseColor(1, 1, .9412);
//产生一个外围边框
vtkOutlineFilter* outlineData = vtkOutlineFilter::New();
outlineData->SetInputConnection(v16->GetOutputPort());
vtkPolyDataMapper* mapOutline = vtkPolyDataMapper::New();
mapOutline->SetInputConnection(outlineData->GetOutputPort());
vtkActor* outline = vtkActor::New();
outline->SetMapper(mapOutline);
outline->GetProperty()->SetColor(0, 0, 0);
//下面创建三个穿过之前读取的立体的正交面,每个面使用的纹理贴图不同,因而着色不同
//首先创建一个灰度查询表
vtkLookupTable * bwLut = vtkLookupTable::New();
bwLut->SetTableRange(0, 2000);
bwLut->SetSaturationRange(0, 0);
bwLut->SetHueRange(0, 0);
bwLut->SetValueRange(0, 1);
bwLut->Build();
//接着创建一个包含所有色调的查询表
vtkLookupTable* hueLut = vtkLookupTable::New();
hueLut->SetTableRange(0, 2000);
hueLut->SetHueRange(0, 1);
hueLut->SetSaturationRange(1, 1);
hueLut->SetValueRange(1, 1);
hueLut->Build();
//最后创建一个具有点一色调,但饱和度不同的查询表
vtkLookupTable *satLut = vtkLookupTable::New();
satLut->SetTableRange(0, 2000);
satLut->SetHueRange(.6, .6);
satLut->SetSaturationRange(0, 1);
satLut->SetValueRange(1, 1);
satLut->Build();
//创建第一个平面。过滤器vtkImageMapToColors通过上面创建的查询表对数据进行映射
//vtkImageActor是vtkProp类型,它使用纹理映射显示图像,结果很快
//(注意:输入数据的值类型必须是unsigned char,这正好是vtkImageMapToColors产生的值的类型)
//同时注意置顶显示范围,流水线会请求范围内的数据
//并且vtkImageMapToColors只处理一个数据切片
vtkImageMapToColors* saggitalColors = vtkImageMapToColors::New();
saggitalColors->SetInputConnection(v16->GetOutputPort());
saggitalColors->SetLookupTable(bwLut);
vtkImageActor* saggital = vtkImageActor::New();
saggital->SetInputData(v16->GetOutput());//原书此处代码为saggitalColors->GetOutput(),但没有显示三个切面,遂改为如此,以下两个切面于此相同
//设置显示的冠状画面
saggital->SetDisplayExtent(32, 32, 0, 63, 0, 92);
//创建第二个平面,与之前的操作一样,除了显示范围不同外
vtkImageMapToColors* axialColors = vtkImageMapToColors::New();
axialColors->SetInputConnection(v16->GetOutputPort());
axialColors->SetLookupTable(hueLut);
vtkImageActor* axial = vtkImageActor::New();
axial->SetInputData(v16->GetOutput());//原书此处代码为axialColors->GetOutput(),但没有显示三个切面,遂改为如此,以下两个切面于此相同
//设置显示的横断面
axial->SetDisplayExtent(0, 63, 0, 63, 46, 46);
//创建第三个平面,与之前的操作一样,除了显示范围不同外
vtkImageMapToColors* coronalColors = vtkImageMapToColors::New();
coronalColors->SetInputConnection(v16->GetOutputPort());
coronalColors->SetLookupTable(satLut);
vtkImageActor* coronal = vtkImageActor::New();
coronal->SetInputData(v16->GetOutput());//原书此处代码为coronalColors->GetOutput(),但没有显示三个切面,遂改为如此,以下两个切面于此相同
//设置显示的失状面
coronal->SetDisplayExtent(0, 63, 32, 32, 0, 92);
vtkCamera *aCamera = vtkCamera::New();
aCamera->SetViewUp(0, 0, -1);
aCamera->SetPosition(0, 1, 0);
aCamera->SetFocalPoint(0, 0, 0);
aCamera->ComputeViewPlaneNormal();
aRenderer->AddActor(outline);
aRenderer->AddActor(saggital);
aRenderer->AddActor(axial);
aRenderer->AddActor(coronal);
aRenderer->AddActor(axial);
aRenderer->AddActor(coronal);
aRenderer->AddActor(skin);
aRenderer->AddActor(bone);
//关闭骨头的演示
bone->VisibilityOff();
//皮肤设为半透明状态,以便观察三界面效果图
skin->GetProperty()->SetOpacity(0.5);
aRenderer->SetActiveCamera(aCamera);
//aRenderer->Render();
aRenderer->ResetCamera();
aCamera->Dolly(1.5);
aRenderer->SetBackground(1, 1, 1);
renWin->SetSize(640, 480);
aRenderer->ResetCameraClippingRange();
iren->Initialize();
iren->Start();
return 0;
}