VTK可视化管线:
vtk渲染引擎实现图形图像的渲染,通过了很多步骤,在之前的程序中,我们使用了例如vtkCamera、vtkLight、vtkConeSource、vtkPropMapper等,都是与vtk渲染相关,vtk渲染引擎与vtk可视化管线是vtk中非常重要的两个模块。
vtk渲染管线实际上就是用于获取数据,处理数据,在将数据给vtk渲染引擎渲染,最终显示。在vtk中,有很多已有的数据源,例如vtkCylinderSource、vtkEarthSource等,可以直接生成数据,除此之外,还有很多的工具可以读取已知类型的数据,例如vtkSTLReader,vtkDICOMImageReader等。vtk可视化管线的三个基本要素就是:数据对象,数据处理对象,数据流方向。
下面是vtk体绘制的一个例子:
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)
#pragma comment(lib, "vtkalglib-8.1.lib")
#pragma comment(lib, "vtkChartsCore-8.1.lib")
#pragma comment(lib, "vtkCommonColor-8.1.lib")
#pragma comment(lib, "vtkCommonComputationalGeometry-8.1.lib")
#pragma comment(lib, "vtkCommonCore-8.1.lib")
#pragma comment(lib, "vtkCommonDataModel-8.1.lib")
#pragma comment(lib, "vtkCommonExecutionModel-8.1.lib")
#pragma comment(lib, "vtkCommonMath-8.1.lib")
#pragma comment(lib, "vtkCommonMisc-8.1.lib")
#pragma comment(lib, "vtkCommonSystem-8.1.lib")
#pragma comment(lib, "vtkCommonTransforms-8.1.lib")
#pragma comment(lib, "vtkDICOMParser-8.1.lib")
#pragma comment(lib, "vtkDomainsChemistry-8.1.lib")
#pragma comment(lib, "vtkDomainsChemistryOpenGL2-8.1.lib")
#pragma comment(lib, "vtkexoIIc-8.1.lib")
#pragma comment(lib, "vtkexpat-8.1.lib")
#pragma comment(lib, "vtkFiltersAMR-8.1.lib")
#pragma comment(lib, "vtkFiltersCore-8.1.lib")
#pragma comment(lib, "vtkFiltersExtraction-8.1.lib")
#pragma comment(lib, "vtkFiltersFlowPaths-8.1.lib")
#pragma comment(lib, "vtkFiltersGeneral-8.1.lib")
#pragma comment(lib, "vtkFiltersGeneric-8.1.lib")
#pragma comment(lib, "vtkFiltersGeometry-8.1.lib")
#pragma comment(lib, "vtkFiltersHybrid-8.1.lib")
#pragma comment(lib, "vtkFiltersHyperTree-8.1.lib")
#pragma comment(lib, "vtkFiltersImaging-8.1.lib")
#pragma comment(lib, "vtkFiltersModeling-8.1.lib")
#pragma comment(lib, "vtkFiltersParallel-8.1.lib")
#pragma comment(lib, "vtkFiltersParallelImaging-8.1.lib")
#pragma comment(lib, "vtkFiltersPoints-8.1.lib")
#pragma comment(lib, "vtkFiltersProgrammable-8.1.lib")
#pragma comment(lib, "vtkFiltersSelection-8.1.lib")
#pragma comment(lib, "vtkFiltersSMP-8.1.lib")
#pragma comment(lib, "vtkFiltersSources-8.1.lib")
#pragma comment(lib, "vtkFiltersStatistics-8.1.lib")
#pragma comment(lib, "vtkFiltersTexture-8.1.lib")
#pragma comment(lib, "vtkFiltersTopology-8.1.lib")
#pragma comment(lib, "vtkFiltersVerdict-8.1.lib")
#pragma comment(lib, "vtkfreetype-8.1.lib")
#pragma comment(lib, "vtkGeovisCore-8.1.lib")
#pragma comment(lib, "vtkgl2ps-8.1.lib")
#pragma comment(lib, "vtkglew-8.1.lib")
#pragma comment(lib, "vtkhdf5-8.1.lib")
#pragma comment(lib, "vtkhdf5_hl-8.1.lib")
#pragma comment(lib, "vtkImagingColor-8.1.lib")
#pragma comment(lib, "vtkImagingCore-8.1.lib")
#pragma comment(lib, "vtkImagingFourier-8.1.lib")
#pragma comment(lib, "vtkImagingGeneral-8.1.lib")
#pragma comment(lib, "vtkImagingHybrid-8.1.lib")
#pragma comment(lib, "vtkImagingMath-8.1.lib")
#pragma comment(lib, "vtkImagingMorphological-8.1.lib")
#pragma comment(lib, "vtkImagingSources-8.1.lib")
#pragma comment(lib, "vtkImagingStatistics-8.1.lib")
#pragma comment(lib, "vtkImagingStencil-8.1.lib")
#pragma comment(lib, "vtkInfovisCore-8.1.lib")
#pragma comment(lib, "vtkInfovisLayout-8.1.lib")
#pragma comment(lib, "vtkInteractionImage-8.1.lib")
#pragma comment(lib, "vtkInteractionStyle-8.1.lib")
#pragma comment(lib, "vtkInteractionWidgets-8.1.lib")
#pragma comment(lib, "vtkIOAMR-8.1.lib")
#pragma comment(lib, "vtkIOCore-8.1.lib")
#pragma comment(lib, "vtkIOEnSight-8.1.lib")
#pragma comment(lib, "vtkIOExodus-8.1.lib")
#pragma comment(lib, "vtkIOExport-8.1.lib")
#pragma comment(lib, "vtkIOExportOpenGL2-8.1.lib")
#pragma comment(lib, "vtkIOGeometry-8.1.lib")
#pragma comment(lib, "vtkIOImage-8.1.lib")
#pragma comment(lib, "vtkIOImport-8.1.lib")
#pragma comment(lib, "vtkIOInfovis-8.1.lib")
#pragma comment(lib, "vtkIOLegacy-8.1.lib")
#pragma comment(lib, "vtkIOLSDyna-8.1.lib")
#pragma comment(lib, "vtkIOMINC-8.1.lib")
#pragma comment(lib, "vtkIOMovie-8.1.lib")
#pragma comment(lib, "vtkIONetCDF-8.1.lib")
#pragma comment(lib, "vtkIOParallel-8.1.lib")
#pragma comment(lib, "vtkIOParallelXML-8.1.lib")
#pragma comment(lib, "vtkIOPLY-8.1.lib")
#pragma comment(lib, "vtkIOSQL-8.1.lib")
#pragma comment(lib, "vtkIOTecplotTable-8.1.lib")
#pragma comment(lib, "vtkIOVideo-8.1.lib")
#pragma comment(lib, "vtkIOXML-8.1.lib")
#pragma comment(lib, "vtkIOXMLParser-8.1.lib")
#pragma comment(lib, "vtkjpeg-8.1.lib")
#pragma comment(lib, "vtkjsoncpp-8.1.lib")
#pragma comment(lib, "vtklibharu-8.1.lib")
#pragma comment(lib, "vtklibxml2-8.1.lib")
#pragma comment(lib, "vtkLocalExample-8.1.lib")
#pragma comment(lib, "vtklz4-8.1.lib")
#pragma comment(lib, "vtkmetaio-8.1.lib")
#pragma comment(lib, "vtkNetCDF-8.1.lib")
#pragma comment(lib, "vtknetcdfcpp-8.1.lib")
#pragma comment(lib, "vtkoggtheora-8.1.lib")
#pragma comment(lib, "vtkParallelCore-8.1.lib")
#pragma comment(lib, "vtkpng-8.1.lib")
#pragma comment(lib, "vtkproj4-8.1.lib")
#pragma comment(lib, "vtkRenderingAnnotation-8.1.lib")
#pragma comment(lib, "vtkRenderingContext2D-8.1.lib")
#pragma comment(lib, "vtkRenderingContextOpenGL2-8.1.lib")
#pragma comment(lib, "vtkRenderingCore-8.1.lib")
#pragma comment(lib, "vtkRenderingFreeType-8.1.lib")
#pragma comment(lib, "vtkRenderingGL2PSOpenGL2-8.1.lib")
#pragma comment(lib, "vtkRenderingImage-8.1.lib")
#pragma comment(lib, "vtkRenderingLabel-8.1.lib")
#pragma comment(lib, "vtkRenderingLOD-8.1.lib")
#pragma comment(lib, "vtkRenderingOpenGL2-8.1.lib")
#pragma comment(lib, "vtkRenderingVolume-8.1.lib")
#pragma comment(lib, "vtkRenderingVolumeOpenGL2-8.1.lib")
#pragma comment(lib, "vtksqlite-8.1.lib")
#pragma comment(lib, "vtksys-8.1.lib")
#pragma comment(lib, "vtkTestingGenericBridge-8.1.lib")
#pragma comment(lib, "vtkTestingIOSQL-8.1.lib")
#pragma comment(lib, "vtkTestingRendering-8.1.lib")
#pragma comment(lib, "vtktiff-8.1.lib")
#pragma comment(lib, "vtkverdict-8.1.lib")
#pragma comment(lib, "vtkViewsContext2D-8.1.lib")
#pragma comment(lib, "vtkViewsCore-8.1.lib")
#pragma comment(lib, "vtkViewsInfovis-8.1.lib")
#pragma comment(lib, "vtkzlib-8.1.lib")
#include <iostream>
#include <windows.h>
#include <vtkSmartPointer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkActor.h>
#include <vtkProperty.h>
#include <vtkRenderer.h>
#include <vtkMetaImageReader.h>
#include <vtkDICOMImageReader.h>
#include <vtkMarchingCubes.h>
#include <vtkGeometryFilter.h>
#include <vtkPolyDataMapper.h>
int main(int argc, char* argv[])
{
vtkSmartPointer<vtkRenderer> CTRenderer = vtkSmartPointer<vtkRenderer>::New();
// vtkSmartPointer<vtkDICOMImageReader> pSrcImage = vtkDICOMImageReader::New();
// pSrcImage->SetDirectoryName("F:\\Data\\36040001");
// pSrcImage->SetDataScalarTypeToUnsignedChar();
// pSrcImage->SetDataByteOrderToLittleEndian();
// pSrcImage->Update();
vtkSmartPointer<vtkMetaImageReader> pSrcImage = vtkMetaImageReader::New(); // 上下两种选一个,读取的文件不同
pSrcImage->SetFileName(".\\FullHead.vtk");
pSrcImage->SetDataScalarTypeToUnsignedChar();
pSrcImage->Update();
//------skin
vtkSmartPointer<vtkActor> skinActor = vtkActor::New();
vtkSmartPointer<vtkMarchingCubes> skinImage = vtkMarchingCubes::New();
skinImage->SetInputConnection(pSrcImage->GetOutputPort());
skinImage->ComputeNormalsOn();
skinImage->SetValue(0, 500); // 皮肤的值
vtkSmartPointer<vtkPolyDataMapper> skinMapper = vtkPolyDataMapper::New();
skinMapper->SetInputConnection(skinImage->GetOutputPort());
skinMapper->ScalarVisibilityOff();
skinActor->SetMapper(skinMapper);
skinActor->GetProperty()->SetColor(0.725, 0.478, 0.341);
skinActor->GetProperty()->SetOpacity(0.8); // 皮肤不透明度0.8
//------bone
vtkSmartPointer<vtkActor> boneActor = vtkActor::New();
vtkSmartPointer<vtkMarchingCubes> boneImage = vtkMarchingCubes::New();
boneImage->SetInputConnection(pSrcImage->GetOutputPort());
boneImage->ComputeNormalsOn();
boneImage->SetValue(0, 1150); // 骨骼的值
vtkSmartPointer<vtkPolyDataMapper> boneMapper = vtkPolyDataMapper::New();
boneMapper->SetInputConnection(boneImage->GetOutputPort());
boneMapper->ScalarVisibilityOff();
boneActor->SetMapper(boneMapper);
boneActor->GetProperty()->SetColor(0.9, 0.9, 0.9);
//------
CTRenderer->AddActor(skinActor);
CTRenderer->AddActor(boneActor);
CTRenderer->SetBackground(0.7, 0.9, 0.9);
CTRenderer->SetGradientBackground(true);
CTRenderer->SetViewport(0.0, 0.0, 1.0, 1.0);
// mainWindow
vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
renWin->AddRenderer(CTRenderer);
renWin->SetSize(640, 480);
renWin->Render();
renWin->SetWindowName("ViewPort");
vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkSmartPointer<vtkInteractorStyleTrackballCamera> interatorStyle = vtkInteractorStyleTrackballCamera::New();
interactor->SetInteractorStyle(interatorStyle);
interactor->SetRenderWindow(renWin);
renWin->Render();
interactor->Initialize();
interactor->Start();
return 0;
}
下面是体绘制的效果图:
如需下载模型文件:
头部:下载地址
脊椎骨架:下载地址
编译好的VTK:下载地址
在上面的例子中,使用了很多vtk的类,vtkProp,vtkRender,vtkRenderWindow等,这些类都是与vtk渲染相关的,这就是vtk渲染引擎的组成部分,而用于获取数据,处理数据,以及把数据传递给渲染引擎进行显示,这样的结构或者相关的类,就是vtk可视化管线。
以之前的HelloWorld程序为例:vtkCyLinderSource和vtkPolyDataMapper就是可视化管线部分,vtkActor,vtkRender,vtkRenderWindow就是渲染引擎部分。
可视化管线的执行:
通常,vtk管线并不是只有一层,管线的连接可以有很多层,甚至特定情况下是树状结构,在获取源数据之后,可能需要对数据做不同的处理已查看不同的效果,如果管线流程较多,而在比较靠前的位置发生了改变,则后面依赖的部分都需要做改变,因此,有时候数据更改量非常大。因此,应该尽量将不会改变的管线流程放在前面,以提高效率。在每一个管线后面显示的调用Update,可以更新。
VTK采用一种叫做“惰性赋值”(LazyEvaluation)的方案来控制管线的执行,惰性赋值是指根据每个对象的内部修改时间来决定什么时候执行管线,只有当你或者程序发出“请求数据”时,管线才会被执行(前面提到vtkObject里有一个重要的成员变量MTime,管线里的每个从vtkObject派生的类的对象都会跟踪自己的内部修改时间,当遇到“请求数据”时,该对象会比较这个修改时间,如果发现修改时间发生了改变,对象就会执行。)。换言之,VTK是采用命令驱动(Demand Driven)的方法来控制管线的执行,这种方法的好处是,当对数据对象作了更改时,不必立即作计算,只有当发出请求时才开始处理,这样能最小化计算所需的时间,以便更流畅地与数据进行交互。
vtkObject和vtkObjectBase:
vtkObjectBase和vtkObject是VTK里两个重要的父类,vtkObjectBase采用引用计数和智能指针的技术来管理VTK对象的内存分配与回收,但智能指针的不当使用会影响引用计数。
vtkObjectBase定义了运行时类型识别及状态信息输出的相关接口,有助于调试VTK应用程序。VTK框架里,大多数的类都是从vtkObject派生,vtkObject实现了观察者/命令(Observer/Command)设计模式,内部维护一个修改时间,用于控制可视化管线的执行。可视化管线是VTK里的重要概念,管线的连接应该使用SetInputConnection()/GetOutputPort()接口进行连接。
VTK采用“惰性赋值”(Lazy Evaluation)的方案来控制管线的执行,只有当发出“请求数据”时,管线才会被执行。好处是,当对数据对象作了更改时,不必立即作计算,只有当发出请求时才开始处理,这样能最小化计算所需的时间,以便更流畅地进行交互。
来源:CSDN
作者:蒲公英24
链接:https://blog.csdn.net/qq_31622605/article/details/81086106