三维图像编程实验
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.3 测试安装结果

1.3.1 VTK安装测试用例

#include"vtkConeSource.h"
#include"vtkPolyDataMapper.h"
#include"vtkRenderWindow.h"
#include"vtkActor.h"
#include"vtkRenderer.h"
intmain()
{
  //创建一个圆锥,并设置其参数:高度、底面半径和分辨率。
  vtkConeSource*cone=vtkConeSource::New();
  cone->SetHeight(3.0);
  cone->SetRadius(1.0);
  cone->SetResolution(10);   //决定圆锥棱角的多少
  //创建一个多边形映射器,用于把多边形数据映射为可被计算机渲染的图元。
  vtkPolyDataMapper*coneMapper=vtkPolyDataMapper::New();
  coneMapper->SetInputConnection(cone->GetOutputPort());
  //创建一个演员,并关联一个映射器,从而确定了演员的形状。
  vtkActor*coneActor=vtkActor::New();
  coneActor->SetMapper(coneMapper);
  
  //创建一个渲染器,添加要被渲染的演员,设置背景颜色。
  vtkRenderer*ren1=vtkRenderer::New();
  ren1->AddActor(coneActor);
  ren1->SetBackground(0.1,0.2,0.4);
  //创建渲染窗口,供渲染器渲染用。
  vtkRenderWindow*renWin=vtkRenderWindow::New();
  renWin->AddRenderer(ren1);
  renWin->SetSize(300,300);
  //渲染360次,这里主要是为了延时。
  inti;
  for(i=0;i<360;++i) renWin->Render();
  //清除对象。
  cone->Delete();
  coneMapper->Delete();
  coneActor->Delete();
  ren1->Delete();
  renWin->Delete();
  return0;
}

可以发现在生成解决方案时,并不像想象中那么顺利,有7个错误均说“无法解析的外部符号__declspec(dllimport)public:void__thiscallvtkRenderer::AddActor(classvtkProp*)”。像这样的问题后面会经常出现,原因就是编译器无法将VTK自带的.lib文件与VisualStudio2008上写的程序程序关联起来。

解决方法:打开“项目→属性→连接器→输入→附加依赖项”,在此输入vtkCommon.lib,vtkFilter-ing.lib,vtkGraphics.lib,vtkRendering.lib四个需要用到的库文件名,由系统根据设定的配置去查找,最后单击“重新生成解决方案”按钮并运行。运行结果如图1-11所示。

图1-11 VTK安装测试用例的运行结果

注:后面的实例中将会频频出现需要添加用到的.lib文件这个问题,为了避免累赘,在此提示具体操作方法,即根据错误提示在vtk帮助文档里面查找对象对应的类库,以后用的次数多了就不再需要查找了。添加时注意每个.lib文件之间要用空格隔开。

1.3.2 ITK安装测试用例

#include"itkImage.h"
#include<iostream>
intmain()
{
//定义一个图像类型
  typedefitk::Image<unsignedshort,3>ImageType;
  ImageType::Pointerimage=ImageType::New();
//输出:ITKHelloWorld!
  std::cout<<"ITKHelloWorld!"<<std::endl;
  return0;
}

可以发现与VTK用例类似的问题出现了。同样,将.lib文件按1.3.2节的方法添加进去即可。如果手头没有vtk或itk帮助文档,可以将所有的vtk或itk运行时可能需要的.lib文件一次性添加进去。对于ITK而言,该文件在E:\Program Files\ITK\lib\InsightToolkit中;对于VTK而言,该文件在E:\ProgramFiles\VTK2008\lib\vtk-5.6中。最后将.lib文件名复制到“项目→属性→连接器→输入→附加依赖项”中即可。运行结果如图1-12所示。

图1-12 ITK安装测试用例的运行结果

1.3.3 VTK与ITK混合编程测试用例

#include"itkImage.h"
#include"itkImageFileReader.h"
#include"itkImageToVTKImageFilter.h"
#include"vtkImageViewer.h"
#include"vtkRenderWindowInteractor.h"
#include"vtkImageActor.h"
#include"vtkRenderer.h"
#include"vtkRenderWindow.h"
#include<iostream>
usingnamespacestd;
intmain(intargc,char**argv){
typedefitk::Image<unsignedshort,2>ImageType;
typedefitk::ImageFileReader<ImageType>ReaderType;          //文件读取器
typedefitk::ImageToVTKImageFilter<ImageType>ConnectorType;   //VTK与ITK链接器
ReaderType::Pointerreader=ReaderType::New();
ConnectorType::Pointerconnector=ConnectorType::New();
reader->SetFileName("E:\\Program Files\\ITK\\InsightToolkit\\Wrapping\\WrapITK\\images\\
ThresholdSegmentationLevelSetWhiteMatterTest.png");
connector->SetInput(reader->GetOutput());
vtkImageActor*actor=vtkImageActor::New();
actor->SetInput(connector->GetOutput());
vtkRenderer* ren=vtkRenderer::New();
ren->AddActor(actor);
vtkRenderWindow*renWin=vtkRenderWindow::New();
renWin->AddRenderer(ren);
vtkImageViewer* viewer=vtkImageViewer::New();
//绘制窗口交互器
vtkRenderWindowInteractor* renderWindowInteractor=vtkRenderWindowInteractor::New();
viewer->SetInput(connector->GetOutput());
viewer->SetupInteractor(renderWindowInteractor);
viewer->SetColorWindow(255);
viewer->SetColorLevel(128);
viewer->Render();
renderWindowInteractor->Initialize();
renderWindowInteractor->Start();
return0;
}

该程序中需要载入路径参数,打开“项目→属性→配置属性→调试→命令参数”,在此添加“E:\ProgramFiles\VTK\vtkdata\Data\fullhead15.png”。如果需要添加多个参数,则要用空格将其隔开,并在附加依赖项中添加需要的.lib文件。再次运行,可以发现仍然有错误:“无法找到itkImageToVTKImageFilter.h文件”,这是因为ITK算法库类比较多,无法将所有的类路径一次性添加到包含文件中。可以在计算机中查找该头文件,发现其在E:\Pro-gramFiles\ITK\InsightToolkit\Wrapping\WrapITK\ExternalProjects\ItkVtkGlue\src中,为了在编译过程中使编译器能够查找到该头文件,可以将其同vtk、itk配置一样添加到“工具→选项→项目和解决方案→VC++目录”的包含文件中,如图1-13所示。再次运行,运行结果如图1-14所示。

图1-13 添加包含文件

图1-14 ITK、VTK混合编程测试用例的运行结果

注:上述出现的错误在后面会经常见到,因此应该注意其解决方法。

1.3.4 InsightApplication安装测试用例一

#include<iostream>
#include"itkMesh.h"
#include"itkLineCell.h"
#include"itkTriangleCell.h"
#include"vtkPolyDataReader.h"
#include"vtkPolyData.h"
#include"vtkPoints.h"
#include"vtkCellArray.h"
intmain(intargc,char* argv[])
{
  vtkPolyDataReader* reader=vtkPolyDataReader::New();
  reader->SetFileName("E:\ProgramFiles\VTK\vtkdata\Data\fran_cut.vtk");
  reader->Update();          //触发立即执行读取操作
  vtkPolyData* polyData=reader->GetOutput();
  constunsignedintPointDimension =3;
  constunsignedintMaxCellDimension=2;
  typedefitk::DefaultStaticMeshTraits<
                vtkFloatingPointType,
                PointDimension,
                MaxCellDimension,
                vtkFloatingPointType,
                vtkFloatingPointType>     MeshTraits;
  typedefitk::Mesh<
                vtkFloatingPointType,
                PointDimension,
      MeshTraits           >   MeshType;
MeshType::Pointer mesh=MeshType::New();
constunsignedintnumberOfPoints=polyData->GetNumberOfPoints();
vtkPoints* vtkpoints=polyData->GetPoints();
mesh->GetPoints()->Reserve(numberOfPoints);
for(unsignedintp=0;p<numberOfPoints;p++)
  {
  vtkFloatingPointType* apoint=vtkpoints->GetPoint(p);
  mesh->SetPoint(p,MeshType::PointType(apoint));
  }
vtkCellArray* triangleStrips=polyData->GetStrips();
vtkIdType * cellPoints;
vtkIdType   numberOfCellPoints;
unsignedintnumberOfTriangles=0;
triangleStrips->InitTraversal();
while(triangleStrips->GetNextCell(numberOfCellPoints,cellPoints))
  {
  numberOfTriangles+=numberOfCellPoints-2;
  }
vtkCellArray* polygons=polyData->GetPolys();
polygons->InitTraversal();
while(polygons->GetNextCell(numberOfCellPoints,cellPoints))
  {
  if(numberOfCellPoints==3)
    {
    numberOfTriangles++;
    }
  }
mesh->GetCells()->Reserve(numberOfTriangles);
typedefMeshType::CellType CellType;
typedefitk::TriangleCell<CellType>TriangleCellType;
intcellId=0;
triangleStrips->InitTraversal();
while(triangleStrips->GetNextCell(numberOfCellPoints,cellPoints))
  {
  unsignedintnumberOfTrianglesInStrip=numberOfCellPoints-2;
  unsignedlongpointIds[3];
  pointIds[0]=cellPoints[0];
  pointIds[1]=cellPoints[1];
  pointIds[2]=cellPoints[2];
  for(unsignedintt=0;t<numberOfTrianglesInStrip;t++)
    {
    MeshType::CellAutoPointerc;
    TriangleCellType* tcell=newTriangleCellType;
    tcell->SetPointIds(pointIds);
    c.TakeOwnership(tcell);
    mesh->SetCell(cellId,c);
    cellId++;
    pointIds[0]=pointIds[1];
    pointIds[1]=pointIds[2];
    pointIds[2]=cellPoints[t+3];
    }
  }
polygons->InitTraversal();
while(polygons->GetNextCell(numberOfCellPoints,cellPoints))
  {
  if(numberOfCellPoints!=3)     {
    continue;
    }
  MeshType::CellAutoPointerc;
  TriangleCellType* t=newTriangleCellType;
  t->SetPointIds((unsignedlong*)cellPoints);
  c.TakeOwnership(t);
  mesh->SetCell(cellId,c);
  cellId++;
  }
std::cout<<"Mesh "<<std::endl;
std::cout<<"NumberofPoints= "<<mesh->GetNumberOfPoints()<<std::endl;
std::cout<<"NumberofCells= "<<mesh->GetNumberOfCells()  <<std::endl;
getchar();
  reader->Delete();
  return0;
}

该范例是InsightApplication自带的用例,其主要功能是将一幅vtk的PolyData结构图转换为一个itk的Mesh(网格)结构,并统计最后该网格的单元数及点数。程序的运行结果如图1-15所示。

图1-15 InsightApplication安装测试用例一的运行结果

1.3.5 InsightApplication安装测试用例二

#include"itkCommand.h"
#include"itkImage.h"
#include"itkVTKImageExport.h"
#include"itkVTKImageImport.h"
#include"itkConfidenceConnectedImageFilter.h"
#include"itkCastImageFilter.h"
#include"itkRGBPixel.h"
#include"itkImageFileReader.h"
#include"itkImageFileWriter.h"
#include"vtkImageImport.h"
#include"vtkImageExport.h"
#include"vtkImageActor.h"
#include"vtkInteractorStyleImage.h"
#include"vtkRenderer.h"
#include"vtkRenderWindow.h"
#include"vtkRenderWindowInteractor.h"
#include"vtkActor.h"
#include"vtkPolyData.h"
#include"vtkPolyDataMapper.h"
#include"vtkContourFilter.h"
#include"vtkImageData.h"
#include"vtkDataSet.h"
#include"vtkProperty.h"
template<typenameITK_Exporter,typenameVTK_Importer>
voidConnectPipelines(ITK_Exporterexporter,VTK_Importer* importer)
{
  importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
  importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
  importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
  importer->SetSpacingCallback(exporter->GetSpacingCallback());
  importer->SetOriginCallback(exporter->GetOriginCallback());
  importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
  importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
  importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
  importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
  importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
  importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
  importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
template<typenameVTK_Exporter,typenameITK_Importer>
voidConnectPipelines(VTK_Exporter* exporter,ITK_Importerimporter)
{
  importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
  importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
  importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
  importer->SetSpacingCallback(exporter->GetSpacingCallback());
  importer->SetOriginCallback(exporter->GetOriginCallback());
  importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
  importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
  importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
  importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
  importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
  importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
  importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
intmain()
{
    typedefunsignedcharPixelType;
    constunsignedintDimension=2;
    typedefitk::Image<PixelType,Dimension>ImageType;
    typedefitk::ImageFileReader<ImageType>ReaderType;
ReaderType::Pointerreader=ReaderType::New();
reader->SetFileName("E:\ProgramFiles\VTK\vtkdata\Data\fullhead15.png");
reader->Update();
typedefitk::ConfidenceConnectedImageFilter<ImageType,ImageType>SegmentationFilterType;
SegmentationFilterType::Pointerfilter=SegmentationFilterType::New();
filter->SetInput(reader->GetOutput());
filter->SetNumberOfIterations(2);
filter->SetReplaceValue(255);
filter->SetMultiplier(2.5);
ImageType::IndexTypeindex;
index[0]=100;
index[1]=100;
filter->SetSeed(index);
typedefitk::VTKImageExport<ImageType>ExportFilterType;
ExportFilterType::PointeritkExporter1=ExportFilterType::New();
ExportFilterType::PointeritkExporter2=ExportFilterType::New();
itkExporter1->SetInput(reader->GetOutput());
itkExporter2->SetInput(filter->GetOutput());
vtkImageImport* vtkImporter1=vtkImageImport::New();
ConnectPipelines(itkExporter1,vtkImporter1);
vtkImageImport* vtkImporter2=vtkImageImport::New();
ConnectPipelines(itkExporter2,vtkImporter2);
vtkImageActor* actor=vtkImageActor::New();
actor->SetInput(vtkImporter1->GetOutput());
vtkInteractorStyleImage* interactorStyle=vtkInteractorStyleImage::New();
vtkRenderer* renderer=vtkRenderer::New();
vtkRenderWindow* renWin=vtkRenderWindow::New();
vtkRenderWindowInteractor* iren=vtkRenderWindowInteractor::New();
renWin->SetSize(500,500);
renWin->AddRenderer(renderer);
iren->SetRenderWindow(renWin);
    iren->SetInteractorStyle(interactorStyle);
    
    renderer->AddActor(actor);
    renderer->SetBackground(0.4392,0.5020,0.5647);
    
    vtkContourFilter* contour=vtkContourFilter::New();
    contour->SetInput(vtkImporter2->GetOutput());
    contour->SetValue(0,128);
    
    vtkPolyDataMapper* polyMapper=vtkPolyDataMapper::New();
    vtkActor       * polyActor=vtkActor::New();
    
    polyActor->SetMapper(polyMapper);
    polyMapper->SetInput(contour->GetOutput());
    polyMapper->ScalarVisibilityOff();
    
    vtkProperty* property=vtkProperty::New();
    property->SetRepresentationToSurface();
    property->SetAmbient(0.1);
    property->SetDiffuse(0.1);
    property->SetSpecular(0.5);
    property->SetColor(1.0,0.0,0.0);
    property->SetLineWidth(2.0);
    
    polyActor->SetProperty(property);
    renderer->AddActor(polyActor);
    renWin->Render();
    iren->Start();
    
    actor->Delete();
    interactorStyle->Delete();
    polyActor->Delete();
    vtkImporter1->Delete();
    vtkImporter2->Delete();
    contour->Delete();
    property->Delete();
    polyMapper->Delete();
    renWin->Delete();
    renderer->Delete();
    iren->Delete();
    
  return0;
}

该范例也是InsightApplication安装自带的一个用例,其主要功能是将ITK和VTK的数据流合并,即itkImageFileReader→itkVtkImageExport→vtkImageImport→vtkImageActor。这样通过ITK数据流的信息都可以由VTK数据流实现。该程序的优点是如果发现ITK的数据流过期, VTK数据流将重新执行。该程序与1.3.3节的程序类似,都实现了VTK与ITK的连接。该程序的运行结果如图1-16所示。

图1-16 InsightApplication安装测试用例二的运行结果

注:本书后续章节所有程序用例,如出现上述问题,均应按照上述解决方案逐步调试,程序用例中用到的ITK与VTK的.lib的添加将不再赘述,请认真阅读调试程序的过程。