VMTK是一个基于VTK和ITK的工具包,主要用于血管的3D重建、几何分析、网格生成、血管分割。可以直接官网下载下来按照它的PypeS规则,结合Python,命令行直接使用;也可以下载源码自己编译,在代码中使用。
算法
VMTK提供了一个准确的血管或管状物体的中线生成算法。这个算法是由 Luca Antiga 在他的博士论文中提出,算法的输入是血管的表面数据和中线的起止点。主要思路是用Delaunay三角剖分算法算出血管Voronoi图,图上的点是血管最大内接球的球心,再由提供的起止点,在这些球心点中根据半径找到最短路径。查找最短路径的算法是Fast Marching算法。算法的最后输出可以得到中线上点的坐标和半径。
参考
基本使用方法
void getCenterline(vtkSmartPointer<vtkPolyData> data) {
vtkSmartPointer<vtkDiscreteMarchingCubes> marchingCubes = vtkSmartPointer<vtkDiscreteMarchingCubes>::New();
marchingCubes->SetInputData(data);
marchingCubes->GenerateValues(1, 1, 1);
marchingCubes->Update();
vtkSmartPointer<vtkWindowedSincPolyDataFilter> smoother = vtkSmartPointer<vtkWindowedSincPolyDataFilter>::New();
smoother->SetInputConnection(marchingCubes->GetOutputPort());
smoother->SetNumberOfIterations(8);
smoother->BoundarySmoothingOn();
smoother->Update();
vtkSmartPointer<vtkCleanPolyData> cleaner = vtkSmartPointer<vtkCleanPolyData>::New();
cleaner->SetInputConnection(smoother->GetOutputPort());
cleaner->Update();
vtkSmartPointer<vtkTriangleFilter> triangleFilter = vtkSmartPointer<vtkTriangleFilter>::New();
triangleFilter->SetInputConnection(cleaner->GetOutputPort());
triangleFilter->PassLinesOff();
triangleFilter->PassVertsOff();
triangleFilter->Update();
vtkSmartPointer<vtkPolyData> surface = triangleFilter->GetOutput();
vtkSmartPointer<vtkvmtkCapPolyData> capper = vtkSmartPointer<vtkvmtkCapPolyData>::New();
capper->SetInputConnection(surface->GetOutputPort());
capper->SetDisplacement(0);
capper->SetInPlaneDisplacement(0);
capper->Update();
vtkSmartPointer<vtkIdList> sourceSeeds, targetSeeds;
sourceSeeds->InsertNextId(0);
targetSeeds->InsertNextId(1);
vtkvmtkPolyDataCenterlines* centerlineFilter = vtkvmtkPolyDataCenterlines::New();
centerlineFilter->SetInputData(capper->GetOutput());
centerlineFilter->SetSourceSeedIds(sourceSeeds);
centerlineFilter->SetTargetSeedIds(targetSeeds);
centerlineFilter->SetRadiusArrayName("MaximumInscribedSphereRadius");
centerlineFilter->SetCostFunction("1/R");
centerlineFilter->SetFlipNormals(0);
centerlineFilter->SetAppendEndPointsToCenterlines(1);
centerlineFilter->SetSimplifyVoronoi(0);
centerlineFilter->SetCenterlineResampling(1);
centerlineFilter->SetResamplingStepLength(1);
centerlineFilter->Update();
vtkSmartPointer<vtkPolyData> output = centerlineFilter->GetOutput();
vtkDoubleArray* centerlinesRadiusArray = output->GetPointData()->GetArray("MaximumInscribedSphereRadius");
for (int i = 0; i < output->GetNumberOfPoints(); i++) {
double* point = new double[3];
output->GetPoint(i, point);
double radius = centerlinesRadiusArray->GetValue(i);
}
}
|