How to convert .stl file to mesh data

Hi, I am trying to convert a .stl file to mesh data. It seems there is no direct way to implement it. So, my idea is first convert the file to a temporary .vtk file and then using itk.meshread() to get the mesh data.

However, when I tried to run this program, it just exited at itk.meshread(). To be more exact, I looked into the code of meshread, and the code stopped at reader.Update() at the second line from the bottom in that function. There is no error message and the only message is Process finished with exit code 139 (interrupted by signal 11: SIGSEGV).

Do you have any suggestions on how to solve this problem? How can I determine whether it is because the impropriate input .vtk file or something else?

Also, please tell me if there is a better way to get the mesh data from .stl file.
Thank you!

I assume you are unaware of ITKIOMeshSTL remote module?

I tried that module before and the code is like this:

from itk import itkSTLMeshIOPython
reader = itk.itkSTLMeshIOPython.itkSTLMeshIO_New(f"{in_root}stls/{structure['name']}.stl")
reader.Update()
mesh = reader.GetOutput()

But it throws an error for the first line saying that:

Traceback (most recent call last):
  File "/Users/anthony/.conda/envs/dicom-rt/lib/python3.7/unittest/loader.py", line 154, in loadTestsFromName
    module = __import__(module_name)
  File "/Users/anthony/Desktop/DICOM/dicom-rt/tests/dicom_rt/test_dicomrt.py", line 6, in <module>
    from itk import itkSTLMeshIOPython
  File "/Users/anthony/.conda/envs/dicom-rt/lib/python3.7/site-packages/itk/itkSTLMeshIOPython.py", line 32, in <module>
    _itkSTLMeshIOPython = swig_import_helper()
  File "/Users/anthony/.conda/envs/dicom-rt/lib/python3.7/site-packages/itk/itkSTLMeshIOPython.py", line 24, in swig_import_helper
    import _itkSTLMeshIOPython
ModuleNotFoundError: No module named '_itkSTLMeshIOPython'

I checked that module but don’t know how to solve that. So I just tried to find another way to solve my problem.

I don’t think we support remote/custom mesh IOs in Python as we do image IOs. @matt.mccormick can you confirm this?

Code sample from Scanco image IO

imageio = itk.ScancoImageIO.New()
image = itk.imread('myvolume.ISQ', imageio=imageio)

@Tom_Birdsong and @Pranjal_Sahu might have some suggestions.

Can you please follow this post and convert to a .vtk file and then try to read using ITK ?
If this also fails then will it be possible to share the .vtk file with me ?

Also try to write the file by calling SetFileVersion(42).

Let me know what you observe.

2 Likes

Thank you so much!

I made it by setting the .vtk version number. The latest vtk library will write the .vtk file with version 5.4(I forget about it but it is over 5), but it seems meshread() function does not support this version right now.

Yes, please call method SetFileVersion(42)

By the way, so right now, is it impossible to convert a .stl to mesh data directly instead of converting to .vtk first and then load it? Or are there any other simpler ways to implement it?

No, there is no support to directly read STL files directly in ITK.
I also faced this issue and wrote that post last year.
If you want to avoid writing to file, then you can also convert from VTK mesh to ITK mesh in python by inserting points and cells in a new ITK mesh.

You can try this code snippet to convert from vtk to itk mesh. This sample code only handles triangle meshes.

# Convert from VTK Mesh to ITK Mesh
def get_itk_mesh(vtk_mesh):
    Dimension = 3
    PixelType = itk.D

    MeshType = itk.Mesh[PixelType, Dimension]
    itk_mesh = MeshType.New()

    # Get points array from VTK mesh
    points = vtk_mesh.GetPoints().GetData()
    points_numpy = np.array(points).flatten().astype("float32")

    polys = vtk_mesh.GetPolys().GetData()
    polys_numpy = np.array(polys).flatten()

    # Triangle Mesh
    vtk_cells_count = vtk_mesh.GetNumberOfPolys()
    polys_numpy = np.reshape(polys_numpy, [vtk_cells_count, Dimension + 1])

    # Extracting only the points by removing first column that denotes the VTK cell type
    polys_numpy = polys_numpy[:, 1:]
    polys_numpy = polys_numpy.flatten().astype(np.uint64)

    # Get point data from VTK mesh to insert in ITK Mesh
    point_data_numpy = np.array(
        vtk_mesh.GetPointData().GetScalars()
    )  # .astype('float64')

    # Get cell data from VTK mesh to insert in ITK Mesh
    cell_data_numpy = np.array(
        vtk_mesh.GetCellData().GetScalars()
    )  # .astype('float64')

    itk_mesh.SetPoints(itk.vector_container_from_array(points_numpy))
    itk_mesh.SetCellsArray(
        itk.vector_container_from_array(polys_numpy),
        itk.CommonEnums.CellGeometry_TRIANGLE_CELL,
    )
    itk_mesh.SetPointData(itk.vector_container_from_array(point_data_numpy))
    itk_mesh.SetCellData(itk.vector_container_from_array(cell_data_numpy))
    return itk_mesh

I am trying this one. Here the type of my input is <class 'vtkCommonDataModelPython.vtkPolyData'>, and when I called this method, it throws an error for line itk_mesh.SetPoints(itk.vector_container_from_array(points_numpy)) saying that RuntimeError: No suitable template parameter can be found. May I ask is it because of the version number or I should convert this input type to vtkmesh?

It is because of ITK version. Which version are you using ?
You can install the latest version “pip install itk==5.3rc04.post3”