[vtkusers] DICOM to Model Mesh

Marco Nawijn nawijn at gmail.com
Wed Nov 27 04:44:42 EST 2013


Would it be acceptable to step out of VTK for meshing?
You could try to do something like the following:
1. Import DICOM data
2. Select region of interest
3. Export region of interest to STL
4. Use dedicated mesh generator like netgen

http://sourceforge.net/apps/mediawiki/netgen-mesher/index.php?title=Main_Page
    to mesh the geometry
5. Import mesh into VTK

Export/Import can ofcourse also be replaced by
direct calls from C++ into the netgen library.
I am not sure if direct VTK support is available in
netgen.


Regards,

Marco



On Wed, Nov 27, 2013 at 5:20 AM, Harold <boogiedoll at yahoo.com> wrote:

> Hi Miro,
>
> Thank you for the guide. I'm new to vtk so while messing around, I managed
> to apply the followings to a set of dicom images (in a very crude way) and
> save it as a .vtk file.
> 1. Marching Cubes - get mesh
> 2. Decimation - reduce the number of triangles
> 3. Smoothing - smooth the mesh
> 4. Cropping - select the largest region using connectivity filter
>
> I guess my next step is to find out how to do pre-processing and refining
> of the defected mesh, and also making statistical models (if there are
> enough training images...).
>
> By the way, here's my crude code based on the the  MarchingCubes Example
> at http://www.vtk.org/Wiki/VTK/Examples/Cxx/Modelling/MarchingCubes".
> Hopefully it can be a small help to other novice like me out there.
>
> /////////////////////////////////
> int main(int argc, char *argv[])
> {
>   vtkSmartPointer<vtkImageData> volume =
>     vtkSmartPointer<vtkImageData>::New();
>   double isoValue;
>
>   if (argc < 3)
>     {
> // Create a sphere if there's no dicom input
>     vtkSmartPointer<vtkSphereSource> sphereSource =
>       vtkSmartPointer<vtkSphereSource>::New();
>     sphereSource->SetPhiResolution(20);
>     sphereSource->SetThetaResolution(20);
>     sphereSource->Update();
>
>     double bounds[6];
>     sphereSource->GetOutput()->GetBounds(bounds);
>     for (unsigned int i = 0; i < 6; i += 2)
>       {
>       double range = bounds[i+1] - bounds[i];
>       bounds[i]   = bounds[i] - .1 * range;
>       bounds[i+1] = bounds[i+1] + .1 * range;
>       }
>     vtkSmartPointer<vtkVoxelModeller> voxelModeller =
>       vtkSmartPointer<vtkVoxelModeller>::New();
>     voxelModeller->SetSampleDimensions(50,50,50);
>     voxelModeller->SetModelBounds(bounds);
>     voxelModeller->SetScalarTypeToFloat();
>     voxelModeller->SetMaximumDistance(.1);
>
>     voxelModeller->SetInputConnection(sphereSource->GetOutputPort());
>     voxelModeller->Update();
>     isoValue = 0.5;
>     volume->DeepCopy(voxelModeller->GetOutput());
>     }
>   else
>     {
>     // Read dicom image when dicom image folder path is specified
>     vtkSmartPointer<vtkDICOMImageReader> reader =
>       vtkSmartPointer<vtkDICOMImageReader>::New();
>     reader->SetDirectoryName(argv[1]);
>     reader->Update();
>     volume->DeepCopy(reader->GetOutput());
>     isoValue = atof(argv[2]);
>     }
>
>   // Use MarchingCubes to generate iso-surface
>   vtkSmartPointer<vtkMarchingCubes> surface =
>     vtkSmartPointer<vtkMarchingCubes>::New();
>
>   #if VTK_MAJOR_VERSION <= 5
>     surface->SetInput(volume);
>   #else
>     surface->SetInputData(volume);
>   #endif
>   surface->ComputeNormalsOn();
>   surface->ComputeScalarsOn();
>   surface->SetValue(0, isoValue);
>   std::cout << "Marching Cube finished..." << std::endl;
>
>   // Create polydata from iso-surface
>   vtkSmartPointer<vtkPolyData> marched =
>     vtkSmartPointer<vtkPolyData>::New();
>   surface->Update();
>   marched->DeepCopy(surface->GetOutput());
>   std::cout<<"Number of points: " << marched->GetNumberOfPoints() <<
> std::endl;
>
>   // Decimation to reduce the number of triangles
>   vtkSmartPointer<vtkDecimatePro> decimator =
>     vtkDecimatePro::New();
>   decimator->SetInputData(marched);
>   decimator->SetTargetReduction(0.5);
>   decimator->SetPreserveTopology(1);
>   decimator->Update();
>   std::cout << "Decimation finished...." << std::endl;
>   // Smoothing
>   vtkSmartPointer<vtkSmoothPolyDataFilter> smoother =
> vtkSmartPointer<vtkSmoothPolyDataFilter>::New();
>   smoother->SetInputData(decimator->GetOutput());
>   smoother->SetNumberOfIterations(5);
>   smoother->SetFeatureAngle(60);
>   smoother->SetRelaxationFactor(0.05);
>   smoother->FeatureEdgeSmoothingOff();
>   std::cout << "Smoothing mesh finished...." << std::endl;
>
>  // Select the largest region
>   vtkSmartPointer<vtkPolyDataConnectivityFilter> connectivityFilter =
> vtkSmartPointer<vtkPolyDataConnectivityFilter>::New();
>   connectivityFilter->SetInputConnection(smoother->GetOutputPort());
>   connectivityFilter->ScalarConnectivityOff();
>   connectivityFilter->SetExtractionModeToLargestRegion();
>   connectivityFilter->Update();
>
>  // Create final polygon mesh
>   vtkSmartPointer<vtkPolyData> mesh =
>     vtkSmartPointer<vtkPolyData>::New();
>   mesh->ShallowCopy(connectivityFilter->GetOutput());
>   std::cout<<"Number of points in the final polygon: " <<
> mesh->GetNumberOfPoints() << std::endl;
>
>   // Visualization
>   vtkSmartPointer<vtkRenderer> renderer =
>     vtkSmartPointer<vtkRenderer>::New();
>   renderer->SetBackground(.1, .2, .3);
>
>   vtkSmartPointer<vtkRenderWindow> renderWindow =
>     vtkSmartPointer<vtkRenderWindow>::New();
>   renderWindow->AddRenderer(renderer);
>   vtkSmartPointer<vtkRenderWindowInteractor> interactor =
>     vtkSmartPointer<vtkRenderWindowInteractor>::New();
>   interactor->SetRenderWindow(renderWindow);
>
>   vtkSmartPointer<vtkPolyDataMapper> mapper =
>     vtkSmartPointer<vtkPolyDataMapper>::New();
>   mapper->SetInputData(mesh);
>   mapper->ScalarVisibilityOff();
>
>   vtkSmartPointer<vtkActor> actor =
>     vtkSmartPointer<vtkActor>::New();
>   actor->SetMapper(mapper);
>
>   renderer->AddActor(actor);
>
>   renderWindow->Render();
>   interactor->Start();
>
>   // Save the mesh as a .vtk file
>   vtkSmartPointer<vtkPolyDataWriter> writer = vtkPolyDataWriter::New();
>   writer->SetFileName("mesh.vtk");
>   writer->SetInputData(mesh);
>   writer->SetFileTypeToASCII();
>   writer->Write();
>
>   return EXIT_SUCCESS;
> }
>
>
> Best Regards,
> Harold
>
>
>   On Wednesday, November 27, 2013 12:06 PM, Miro Drahos <
> mdrahos at robodoc.com> wrote:
>  This is basically a segmentation problem, which in general is a
> difficult problem.
> One such pipeline could be as follows:
> 1.) image preprocessing (cropping, smoothing, etc).
> 2.) thresholding to get a filled binary mask of your object (vertebra)
> 3.) running Marching Cubes to get a mesh.
>
> This is a very crude and basic approach, but something to get you
> started. Note that marching cubes might give you a mesh with topological
> defects (holes, handles), from the noise in your data.
>
> There are a variety of other sophisticated algorithms, e.g. using
> statistical methods if you have some already segmented data (like
> creating a mean shape from the previously segmented data, and using PCA
> to do shape analysis, or some machine learning approach).
>
> Another approach would be to use deformable models, i.e. define forces
> that would (iteratively) drive an initial mesh to fit the image. The
> forces would be based on image intensity, gradient and/or laplacian, and
> internal forces to keep the mesh regular and relatively smooth.
>
> There is a lot that has been done in this domain, so look at some
> articles on segmentation.
>
> HTH,
> Miro
>
>
> On 11/25/2013 06:20 AM, Boogiedoll wrote:
> > Hi,
> > I would like to ask the experts about common way in vtk to create a
> spine bone (e.g L1) mesh from a CT DICOM stack, including the
> pre-processing.
> >
> > Thanks & Regards,
> > Harold
> > _______________________________________________
> > Powered by www.kitware.com
> >
> > Visit other Kitware open-source projects at
> http://www.kitware.com/opensource/opensource.html
> >
> > Please keep messages on-topic and check the VTK FAQ at:
> http://www.vtk.org/Wiki/VTK_FAQ
> >
> > Follow this link to subscribe/unsubscribe:
> > http://www.vtk.org/mailman/listinfo/vtkusers
>
>
>
>
> _______________________________________________
> Powered by www.kitware.com
>
> Visit other Kitware open-source projects at
> http://www.kitware.com/opensource/opensource.html
>
> Please keep messages on-topic and check the VTK FAQ at:
> http://www.vtk.org/Wiki/VTK_FAQ
>
> Follow this link to subscribe/unsubscribe:
> http://www.vtk.org/mailman/listinfo/vtkusers
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.vtk.org/pipermail/vtkusers/attachments/20131127/751f1ddc/attachment.htm>


More information about the vtkusers mailing list