Convert mesh to volume

Thank you for this information, but i ran into some problems with the code and the model is not displayed.
I’m trying to convert a .VTK file from an atlas (unstructured grid) into a mesh or volume to create a .nrrd or nifti file for a medical project.
Here is a link to the VTK - M1_cf_face.1k.vtk - Google Drive

These are the errors im running into:

'[success, modelNode] = slicer.util.loadModel(sampleModelFile, returnNode=True)'
Error: loadNodeFromFile `returnNode` argument is deprecated. Loaded node is now returned directly if `returnNode` is not specified.

'modelNode.GetBounds(bounds)'
Error: Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'GetBounds'

'transformer.SetInputConnection(modelNode.GetMeshConnection())'
Error: Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'GetMeshConnection'

'modelNode.GetDisplayNode().BackfaceCullingOff()'
Error: Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'GetDisplayNode'

'display()'
Error: Traceback (most recent call last):
File "<console>", line 1, in <module>
NameError: name 'display' is not defined

The file that you linked above is not an unstructured grid but a polydata containing 1000 line cells.

image

Since lines are one-dimensional objects (have zero volume), before you can convert this to a labelmap, you need to give it some thickness. You can use vtkTubeFilter or vtkImplicitModeller+vtkContourFilter or Delaunay triangulation for this.

For example:

modelNode = getNode('M1*')
outputModelNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelNode')
outputModelNode.CreateDefaultDisplayNodes()

decimate = vtk.vtkDecimatePolylineFilter()
decimate.SetInputData(modelNode.GetPolyData())
decimate.SetTargetReduction(0.9)

delaunay = vtk.vtkDelaunay3D()
delaunay.SetInputConnection(decimate.GetOutputPort())
delaunay.SetAlpha(5.0)
delaunay.BoundingTriangulationOn()
delaunay.AlphaTetsOn()
delaunay.AlphaLinesOff()
delaunay.AlphaTrisOff()

geometry = vtk.vtkDataSetSurfaceFilter()
geometry.SetInputConnection(delaunay.GetOutputPort())

normals = vtk.vtkPolyDataNormals()
normals.SetInputConnection(geometry.GetOutputPort())
outputModelNode.SetPolyDataConnection(normals.GetOutputPort())

image

You can then convert this model to a segmentation node and get a binary labelmap representation.

Thanks for the help!

Hi!

First of all, thanks a lot for the helpful comments regarding this issue. I found this topic recently as I actually have exactly the same issue with the same vtk files.

I tried out your code, but I get this error “NameError: name ‘normals’ is not defined” referring to the last command “outputModelNode.SetPolyDataConnection(normals.GetOutputPort())”. The Model is not displayed like in the second image you showed.

Since it worked for you, it has to be an issue with my setup. Is there a solution for this?

Thanks a lot in advance!

Best,
Mehmet

You can change ‘normals’ to ‘geometry’.

outputModelNode.SetPolyDataConnection(geometry.GetOutputPort())

Or, you can add a normal filter, which would create a smoother looking surface:

modelNode = getNode('M1*')
outputModelNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelNode')
outputModelNode.CreateDefaultDisplayNodes()

decimate = vtk.vtkDecimatePolylineFilter()
decimate.SetInputData(modelNode.GetPolyData())
decimate.SetTargetReduction(0.9)

delaunay = vtk.vtkDelaunay3D()
delaunay.SetInputConnection(decimate.GetOutputPort())
delaunay.SetAlpha(5.0)
delaunay.BoundingTriangulationOn()
delaunay.AlphaTetsOn()
delaunay.AlphaLinesOff()
delaunay.AlphaTrisOff()

geometry = vtk.vtkDataSetSurfaceFilter()
geometry.SetInputConnection(delaunay.GetOutputPort())

normals = vtk.vtkPolyDataNormals()
normals.SetInputConnection(geometry.GetOutputPort())
outputModelNode.SetPolyDataConnection(normals.GetOutputPort())
2 Likes

works! Thanks a lot!

1 Like