前言:本博文主要研究mimics中Calculate Parts所采用的方法以及VTK中三维重建的方法,希望对各位小伙伴有所帮助,谢谢!
mimics-Calculate parts - Interpolation
Gray Interpolation
灰度值插值是一种真正的3D插值,它考虑了部分体积效应,因此更准确。使用灰度值插值方法,我们假设骨密度给出了一个像素内骨骼数量的指示。根据灰度值确定表面的所有边缘。另外,这两个像素之间的位置是基于这两个像素的灰度值。
灰度值插值的优点是它提供了大量的细节和尺寸是正确的。缺点是,你得到不必要的细节,由于在图像中的噪声。以大腿骨为例,当使用这个灰度值插值时,你会得到更好的结果(意思是:一个很好的圆润边缘)。当然,你也需要做一些平滑来减少噪音。
然而,重要的是要认识到,灰度值插值并不总是产生良好的结果。当扫描的切片距离明显偏离切片厚度时,得到的网格表面会产生噪声。只有当切片厚度和切片距离相同时,灰度值插值才能很好地工作。在扫描(采集)过程中应满足此条件。因此,Z分辨率的变化(参见关于矩阵缩减的段落)不应与灰度值插值结合使用。降低XY分辨率并不违反该条件。
灰度值插值建议用于CT技术应用。
Contour Interpolation
轮廓插值是在图像平面上平滑扩展到三维空间的二维插值。该插值算法在切片内使用灰度值插值,但在Z方向上使用轮廓之间的线性插值(如下图所示)。这种插值方法为医疗目的提供了最好的结果。
vtkContourFilter
描述:vtkContourFilter是一个过滤器,接受任何数据集的输入并输出等值面或等值线。输出的形式取决于输入数据的维数。若输入数据包含3D单元,则输出等值面。若输入数据包含2D单元,则输出等值线。同样的,若输入数据包含1D或0D,则输出等指点。如果输入维度为混合的,则可以输出混合类型。
ComputeNormal():Set/Get法线的计算。计算法线相当耗费时间和内存。如果输出数据将由修改拓扑或几何的过滤器处理,那么关闭法线和梯度可能是明智的。对于vtkImageData, vtklineargrid, vtkStructuredGrid和vtkUnstructuredGrid输入,此设置默认为On,而对于所有其他输入则为Off。
vtkSynchronizedTemplates3D
描述:用于从结构数据生成等值面。vtkSynchronizedTemplates3D是同步模板算法的3D实现。注意,vtkContourFilter将在适当的时候自动使用这个类。该接口只针对3D图像。
核心函数为ContourImage
根据Image以及设定的Contour值,寻找Contour的边界;
根据添加的点以及所在的位置,建立拓扑关系(拓扑关系基于两个Table进行);
若输入图像为多值图像,即不是二值图像,添加的点会进行插值;
测试代码
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);#include "vtkSmartPointer.h"#include "vtkCamera.h"
#include "vtkDoubleArray.h"
#include "vtkImageData.h"
#include "vtkImageProperty.h"
#include "vtkImageReslice.h"
#include "vtkImageSincInterpolator.h"
#include "vtkImageSlice.h"
#include "vtkImageSliceMapper.h"
#include "vtkInteractorStyleImage.h"
#include "vtkPNGReader.h"
#include "vtkPointData.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"#include "vtkTestUtilities.h"
#include <vtkImageData.h>
#include <vtkMetaImageReader.h>
#include <vtkContourFilter.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkSTLWriter.h>
#include <vtkSTLReader.h>
#include <vtkPolyDataNormals.h>
#include <vtkStripper.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkImageResliceMapper.h>#include "zxContourFilter.h"void CreateColorImage(vtkImageData* image);int main()
{vtkSmartPointer<vtkImageData> image = vtkSmartPointer<vtkImageData>::New();CreateColorImage(image);zxContourFilter* filter = zxContourFilter::New();filter->SetInputData(image);filter->SetValue(0, 4);//filter->GenerateValues(3, -10., 10.);filter->Update();vtkSTLWriter* writer = vtkSTLWriter::New();writer->SetFileName("F:\\contourPolyData.stl");writer->SetInputData(filter->GetOutput());writer->Write();/*vtkPolyDataNormals* normals = vtkPolyDataNormals::New();normals->SetInputData(filter->GetOutput());normals->SetFeatureAngle(60);normals->SetComputePointNormals(true);normals->Update();vtkSTLWriter* writer2 = vtkSTLWriter::New();writer2->SetFileName("F:\\contourNormals.stl");writer2->SetInputData(normals->GetOutput());writer2->Write();vtkStripper* stripper = vtkStripper::New();stripper->SetInputData(normals->GetOutput());stripper->Update();*//*vtkSTLWriter* writer3 = vtkSTLWriter::New();writer3->SetFileName("F:\\contourStripper.stl");writer3->SetInputData(stripper->GetOutput());writer3->Write();*/vtkPolyDataMapper* contourMapper = vtkPolyDataMapper::New();contourMapper->SetInputData(filter->GetOutput());vtkActor* contourActor = vtkActor::New();contourActor->SetMapper(contourMapper);// Setup renderersvtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();//renderer->AddViewProp(imageSlice);renderer->AddActor(contourActor);renderer->ResetCamera();// Setup render windowvtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();renderWindow->SetSize(300, 300);renderWindow->AddRenderer(renderer);// Setup render window interactorvtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =vtkSmartPointer<vtkRenderWindowInteractor>::New();vtkSmartPointer<vtkInteractorStyleTrackballCamera> style =vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();renderWindowInteractor->SetInteractorStyle(style);// Render and start interactionrenderWindowInteractor->SetRenderWindow(renderWindow);renderWindow->Render();renderWindowInteractor->Initialize();renderWindowInteractor->Start();return EXIT_SUCCESS;
}void CreateColorImage(vtkImageData* image)
{int directSize = 7;int zSize = 5;image->SetDimensions(directSize, directSize, zSize);image->AllocateScalars(VTK_UNSIGNED_CHAR, 1);for (unsigned int z = 0; z < zSize; z++){for (unsigned int y = 0; y < directSize; y++){for (unsigned int x = 0; x < directSize; x++){unsigned char* pixel = static_cast<unsigned char*>(image->GetScalarPointer(x, y, z));pixel[0] = 0;}}}for (unsigned int z = 1; z < 5; z++){for (unsigned int y = z; y < directSize -z; y++){for (unsigned int x = z; x < directSize - z; x++){unsigned char* pixel = static_cast<unsigned char*>(image->GetScalarPointer(x, y, z));pixel[0] = 4;}}}
}