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的添加将不再赘述,请认真阅读调试程序的过程。