Search code examples
vtk

How can make the smoothed vtk mesh vertices distribute evenly?


After smoothing the contour constructed by MatchingCubes with below codes,

contour=vtk.vtkMarchingCubes()
smoother = vtk.vtkWindowedSincPolyDataFilter()

The result seem like below. Some vertices are unevenly distributed. Is there any method to make them more 'evenly segmented'?

enter image description here


Solution

  • For other users looking for an answer from this post:

    C++ using VTK https://github.com/valette/ACVD

    python using pyvista / VTK https://github.com/pyvista/pyacvd ($ pip install pyacvd)

    Example using pyacvd from a function that converts a simpleITK binary image to a VTK polydata:

    import numpy as np
    import SimpleITK as sitk
    import vtk
    from vtk.util import numpy_support
    import pyvista as pv
    import pyacvd
    
    def sitk2vtk(self, sitk_pointer, nb_points=None):    
        numpy_array = sitk.GetArrayFromImage(sitk_pointer)
        size = list(sitk_pointer.GetSize())
        origin = list(sitk_pointer.GetOrigin())
        spacing = list(sitk_pointer.GetSpacing())
        label = numpy_support.numpy_to_vtk(num_array=numpy_array.ravel(), deep=True, array_type=vtk.VTK_FLOAT)
        
        # Convert the VTK array to vtkImageData
        img_vtk = vtk.vtkImageData()
        img_vtk.SetDimensions(size)
        img_vtk.SetSpacing(spacing)
        img_vtk.SetOrigin(origin)
        img_vtk.GetPointData().SetScalars(label)
    
        MarchingCubeFilter = vtk.vtkDiscreteMarchingCubes()   
        MarchingCubeFilter.SetInputData(img_vtk)
        MarchingCubeFilter.GenerateValues(1, 1, 1)   
        MarchingCubeFilter.Update() 
    
        if nb_points:        
            # wrapper vtk polydata to pyvista polydata        
            pv_temp = pv.PolyData(MarchingCubeFilter.GetOutput())        
            cluster = pyacvd.Clustering(pv_temp)        
            cluster.cluster(int(nb_points))        
            remesh = cluster.create_mesh()        
            remesh_vtk = vtk.vtkPolyData()        
            remesh_vtk.SetPoints(remesh.GetPoints())        
            remesh_vtk.SetVerts(remesh.GetVerts())        
            remesh_vtk.SetPolys(remesh.GetPolys())        
            return remesh_vtk    
        else:        
            return MarchingCubeFilter.GetOutput()
    

    Some examples for ITK/VTK reader/writer/converter: https://github.com/guatavita/IOTools