0
点赞
收藏
分享

微信扫一扫

vtk 常用绘制方法 vtkMarchingCubes 面绘制


VTK 深用绘制

vtkMarchingCubes

vtkRecursiveDividingCubes

ContourFilter提取等值面

vtkSmartPointer< vtkMarchingCubes > boneExtractor =
vtkSmartPointer< vtkMarchingCubes >::New();
boneExtractor->SetInputConnection(reader->GetOutputPort());
boneExtractor->SetValue(0, 400); //设置提取的等值信息
boneExtractor->Update();


//利用ContourFilter提取等值面
/*vtkSmartPointer< vtkContourFilter > boneExtractor =
vtkSmartPointer< vtkContourFilter >::New();
boneExtractor->SetInputConnection(reader->GetOutputPort());
boneExtractor->SetValue(0, 200); //设置提取的等值信息
boneExtractor->Update();*/

//DC算法 耗时长,模型有明显缝隙
/*vtkSmartPointer< vtkRecursiveDividingCubes > boneExtractor =
vtkSmartPointer< vtkRecursiveDividingCubes >::New();
boneExtractor->SetInputConnection(reader->GetOutputPort());
boneExtractor->SetValue(500);
boneExtractor->SetDistance(1);
boneExtractor->SetIncrement(2);
boneExtractor->Update();*/

三维重建主要有面绘制体绘制两种方法,其中面绘制又包含轮廓连接法移动立方体法等;而绘制的主要方法为光线投射法

面绘制 (Surface Rendering)

VTK中基于面绘制实现​​三维重建​​​ 使用的是经典的Marching Cubes(移动立方体法)算法。
  
  面绘制是采用分割技术对一系列的二维图像进行轮廓识别、提取等操作,最终还原出被检测物体的三维模型,并以表面的方式显示出来。
  面绘制的数据流管道pipeline结构为:
读取器->提取等值面->数据处理->映射器->实例化角色->绘制器->绘制窗口->交互器->交换方式。
Marching Cubes算法简介:
首先,假定原始数据是离散的三维空间规则数据场;
其次,给出所求等值面的值;
最后,找出等值面经过的体元位置,求出该体元内的等值面并计算出相关参数(以便由常用的图形软件包或图形硬件提供的面绘制功能绘制等值面)。
VTK提供了两种提取等值面的类:

   等值面(线)提取是一种常用的可视化技术,常应用于医学、地质、气象等领域。例如,在医学图像处理中,由于CT、MRI等图像分辨率越来越高,虽然体绘制技术可以清晰地对数据内部结构进行可视化,但是其计算量和效率却制约了其使用。此时可通过等值面提取技术,仅提取感兴趣的一个或者几个组织轮廓,并生成网格模型以供后续的处理和研究。
    根据数据类型的不同,VTK中提供了多个等值面提取类 :
     
    VTK中的等值面提取算法多基于MarchingCube算法来实现。MarchingCube是经典的移动立方体等值面提取算法。该算法是由W.E.Lorenson和H.E.Cline在1987年提出的。由于这一方法原理简单,易于实现,目前已经得到了较为广泛的应用,称为三维数据等值面生成的经典算法。等值面提取类根据数据类型的不同而有所侧重。

        vtkImageMarchingCubes:主要处理三维图像数据
        vtkMarchingCubes:主要针对规则体数据生成等值面
        vtkMarchingSquares:则是针对二维规则网格数据生成等值线
        vtkMarchingContourFilter:可以接受任何类型的数据,其内部根据数据不同生成不同的算法对象实现等值面/线的提取,具有较高的效率
        vtkContourFilter:则是一个更加通用的等值面提取类,其可以接受任意的数据类型生成等值线或等值面。

        vtkDiscreteMarchingCubes继承自vtkMarchingCubes,主要针对Label图像,比如利用图像分割算法对医学图像进行分割后得到含有不同Label值得数据,每个Label对应一个组织,吐过想要得到其中一个或者几个组织的洛括模型,则可以考虑使用该类。

VTK通过vtkPolyDataNormals在等值面上产生法向量;通过vtkStripper在等值面上产生纹理或三角面片。

int showVTKData(vtkImageData* vtkData, vtkImageData* RevtkData, vtkMatrix4x4 *vtkMat = nullptr)
{
// 已知等值面或等值线值500对应于
// 病人的皮肤。
vtkSmartPointer<vtkMarchingCubes> skinExtractor =
vtkSmartPointer<vtkMarchingCubes>::New();
skinExtractor->SetInputData(vtkData);
skinExtractor->SetValue(0, 50);

vtkSmartPointer<vtkDataSetMapper> skinMapper =
vtkSmartPointer<vtkDataSetMapper>::New();
skinMapper->SetInputConnection(skinExtractor->GetOutputPort());
skinMapper->ScalarVisibilityOff();

vtkSmartPointer<vtkActor> skin =
vtkSmartPointer<vtkActor>::New();

if (nullptr != vtkMat)
skin->SetUserMatrix(vtkMat);
skin->SetMapper(skinMapper);
skin->GetProperty()->SetDiffuseColor(1, .49, .25);

vtkSmartPointer<vtkProperty> backProp =
vtkSmartPointer<vtkProperty>::New();
backProp->SetDiffuseColor(0.8900, 0.8100, 0.3400);
skin->SetBackfaceProperty(backProp);

//创建数据的初始视图很方便。的FocalPoint而位置构成一个矢量方向。稍后(ResetCamera()方法)
//这个矢量是用来定位摄像机来查看数据的

//这个方向。
vtkSmartPointer<vtkCamera> aCamera =
vtkSmartPointer<vtkCamera>::New();
aCamera->SetViewUp(0, 0, -1);
aCamera->SetPosition(0, -1, 0);
aCamera->SetFocalPoint(0, 0, 0);
aCamera->ComputeViewPlaneNormal();
aCamera->Azimuth(30.0);
aCamera->Elevation(30.0);

vtkSmartPointer<vtkRenderer> aRenderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renWin =
vtkSmartPointer<vtkRenderWindow>::New();
renWin->AddRenderer(aRenderer);

vtkSmartPointer<vtkRenderWindowInteractor> iren =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
iren->SetRenderWindow(renWin);

aRenderer->AddActor(skin);
//aRenderer->AddActor(getVTKActor(RevtkData));

aRenderer->SetActiveCamera(aCamera);
aRenderer->ResetCamera();
aCamera->Dolly(1.5);


aRenderer->SetBackground(.2, .3, .4);
renWin->SetSize(640, 480);

aRenderer->ResetCameraClippingRange();

renWin->Render();
iren->Initialize();
iren->Start();

return EXIT_SUCCESS;
}

举报

相关推荐

0 条评论