Centerline smoothing by vmtkCenterlineSmoothing does not work

Hello, everyone,

I’m interested in smoothing the centerlines of the cerebral arteries.

Following the parameters recommended by “Kjeldsberg et al. BioMedical Engineering OnLine (2021) Automated landmarking of bends in vascular structures: a comparative study with application to the internal carotid artery (Automated landmarking of bends in vascular structures: a comparative study with application to the internal carotid artery | BioMedical Engineering OnLine | Full Text)”, I set the smoothing factor to 1.2 and the iteration number to 100. I’ve written a script using Python 3.8.10 (Anaconda) and VMTK 1.5.0.

Comparing with the original centerlines, there’s hardly any change in their trajectories. Even when I tried a significantly larger number for the smoothing factor, there was no variation, and the individual coordinates remained unchanged as well. Do you have any suggestions for improvement?

For the vascular data, I’m using the freely available AneuriskWeb’s C0002 (http://ecm2.mathcs.emory.edu/aneuriskweb/repository#).

Thank you.

from vmtk import vmtkscripts

def vmtk_centerline_smoothing(centerlines, num_iteration=100, smooth_factor=1.2):
    # smooth centerlines with a moving average filter
    # args: centerlines: centerlines (vtkPolydata)
    #       num_iteration: number of iterations (str)
    #       smooth_factor: smooth factor (float)
    # returns: smoothed centerline (vtkPolyData)
 
    smoother = vmtkscripts.vmtkCenterlineSmoothing()
    smoother.Centerlines = centerlines
    smoother.SetNumberOfSmoothingIterations = num_iteration
    smoother.SetSmoothingFactor = smooth_factor
    smoother.Execute()
    smoothed_centerlines = smoother.Centerlines
    return smoothed_centerlines

CL # original centerlines
smoothed_centerlines1 = vmtk_centerline_smoothing(CL, num_iteration=100, smooth_factor=0.1)
smoothed_centerlines2 = vmtk_centerline_smoothing(CL, num_iteration=100, smooth_factor=1000)

# check the coordinate
print(CL.GetPoints().GetPoint(10))
print(smoothed_centerlines1.GetPoints().GetPoint(10))
print(smoothed_centerlines2.GetPoints().GetPoint(10))

(62.38236999511719, 4.450344562530518, 63.071693420410156)
(62.37776184082031, 4.44761848449707, 63.0672607421875)
(62.37776184082031, 4.44761848449707, 63.0672607421875)

Everything seems to work very well. Since the centerline is already very much smoothed and the curve points are very close to each other, you wont see much if you just use 100 iterations and not too strong smoothing factor.

You can copy-paste this code snippet into 3D Slicer’s Python console to see the effect of smoothing:

centerlineFilePath = 'path/to/C0002/morphology/centerlines.vtp'

reader = vtk.vtkXMLPolyDataReader()
reader.SetFileName(centerlineFilePath)
reader.Update()

try:
    import vtkvmtkComputationalGeometryPython as vtkvmtkComputationalGeometry
except ImportError:
    raise ImportError("Please install VMTK extension")
smoothing = vtkvmtkComputationalGeometry.vtkvmtkCenterlineSmoothing()
smoothing.SetInputConnection(reader.GetOutputPort())
smoothing.SetSmoothingFactor(0.1)
smoothing.SetNumberOfSmoothingIterations(100)
smoothing.Update()

modelNode = slicer.modules.models.logic().AddModel(smoothing.GetOutputPort())
modelNode.GetDisplayNode().SetLineWidth(2)

After this you can adjust the smoothing parameters and see the result immediately:

smoothing.SetNumberOfSmoothingIterations(1000)

smoothing.SetSmoothingFactor(0.5)

@lassoan

Thank you for your reply.

I didn’t have a good understanding of this smoothing. Looking at your display, it seems to be smoothed properly, but when I write a script with the same in Python, it’s clearly not working well. I wonder what the cause might be?

centerlineFilePath = “path/to/C0002/morphology/centerlines.vtp”

def load_vtp(file_path):
reader = vtk.vtkXMLPolyDataReader()
reader.SetFileName(file_path)
reader.Update()
vtkpolydata = reader.GetOutput()
return vtkpolydata

def vmtk_centerline_smoothing(centerlines, num_iteration, smooth_factor):
smoother = vmtkscripts.vmtkCenterlineSmoothing()
smoother.Centerlines = centerlines
smoother.SetNumberOfSmoothingIterations = num_iteration
smoother.SetSmoothingFactor = smooth_factor
smoother.Execute()
smoothed_centerlines = smoother.Centerlines
return smoothed_centerlines

CL = load_vtp(centerlineFilePath)

smoothed_centerlines1 = vmtk_centerline_smoothing(centerlines=CL, num_iteration=100, smooth_factor=0.1)

smoothed_centerlines2 = vmtk_centerline_smoothing(centerlines=CL, num_iteration=1000, smooth_factor=0.1)

smoothed_centerlines3 = vmtk_centerline_smoothing(centerlines=CL, num_iteration=1000, smooth_factor=0.5)

Compared to the original centerlines, all of them are smoothed, but all smoothed centerlines seem to be the same even if the parameters are adjusted…

Incidentally, smoothing once does not change the smoothing situation even if the parameters are adjusted, but further smoothing of centerlines that have been smoothed (smoothing 2 times) seems to result in the intended smoothed centerlines.

One more question, is this smoothing with Moving Average? Is it smoothing using a Laplacian filter? I don’t understand the definition of lambda.

I’m not sure from the VMTK document.

Thank you.

I would recommend to start in the Slicer Python console and confirm that everything works well. You can then change things step by step and see what change breaks it.

The documentation mentions Laplacian smoothing and implementation seems to be that, too.

It worked perfectly with the method you described. I have since realized the mistake in my script. When using the VMTK’s vmtkCenterlineSmoothing class in Python, the ‘Set’ prefix is not required, and direct assignment to properties is necessary.

The correct script is:
def vmtk_centerline_smoothing(centerlines, num_iteration, smooth_factor):
smoother = vmtkscripts.vmtkCenterlineSmoothing()
smoother.Centerlines = centerlines
smoother.NumberOfSmoothingIterations = num_iteration
smoother.SmoothingFactor = smooth_factor
smoother.Execute()
smoothed_centerlines = smoother.centerlines
return smoothed_centerlines

Thank you @lassoan and everyone !

1 Like