Generate segmentation node (binary label map) from centerline

Hi,

I want to obtain a label map corresponding to centerline generated by VMTK. I would also like to get a different label for voxels belonging to different branches.

I have generated centerline tree for a vessel label map using the ‘extract centerline’ option in VTMK extension Tree → Centerline Model.

I can right click the Centerline model_1 and select ‘convert model to segmentation node’ which I suppose should result in a binary label map and I can see it in the 3d view but not in any other views. I also exported the label map as .nrrd file and checked the data for any non-zero values, but all the values in the data are zero. Also, when I reload the label map in 3d slicer, I don’t see the centerline at all. Am I understanding the ‘convert model to segmentation node’ option correctly, if so what am I doing wrong here?

I also have another question, I would like to have a heirarchical tree for the whole centerline such that each point on the centerline is associated to a branch of the centerline tree. I can generate this tree using Tree → Centerline Curve option but I have a couple of problems. First, the centerline curve does not match the centerline model, especially at bifurcations. Second, even if would like to use it, I cannot convert this Centerline curve_3 to a segmentation node as there is no option to do that. How can I convert it to a segmentation map?

The centerline models just contain the lines that you can see inside the input segmentation. Extracting the parts of the segmentation that belong to each branch is not so simple. First, you need to run vtkvmtkPolyDataCenterlineGroupsClipper on the vtkPolyData of the surface representation of the segmentation. Currently you can only do this from the Python console (I may have missed something and there maybe such module already).

Then to get labelmaps, first you need to “close” down the open-ended surface models so that they can be voxelized to become labelmaps. It is far from simple so I will give you some ideas once you get this far.

1 Like

I managed to voxelize the centerline curve and get the label map using the Bresenham’s line algorithm. For the centerline model, I see that there are a few arrays that can be useful.

Screenshot from 2022-11-11 16-36-14

For arrays like Points and Radius, it seems straight forward. EdgeArray should be straight forward as well but I see that the first few edges are connecting to themselves, which is strange in a tree centerline. I have no idea What EdgePCoordArray is. CellPointIds contains 42 lists of ids which I assume can be 42 different branches but I am not sure since the centerline curve for the same segmentation mask contains 72 branches. Can you please help me in understanding what EdgeArray, EdgePCoordArray and CellPointIds are? I think after that I can just use the Bresenham’s line algorithm on the centerline model as well to get my label maps.

1 Like

You can get a high-level description in Luca Antiga’s thesis and you can see examples in how this point and cell data arrays are used in VMTK source code, example scripts, and command-line “pypes”.

For example, here are complete solutions for converting centerline to branching tube mesh or image (that don’t require any external dependencies and blunt methods like Bresenham’s line drawing) here:

I have been meaning to read the Luca’s thesis but I would have to dedicate some time to it later. I tried to use “image output: vmtk/vmtkcenterlinemodeller.py at master · vmtk/vmtk · GitHub” but maybe I am doing something wrong because after ~2 hours I get an image that looks like a smooth gradient.

Screenshot from 2022-11-14 16-02-20

My code looks like this.

import vtk
from vmtk import vtkvmtk
import timeit


def centerline_to_image(centerline, ref_image):
    # Read centerline as polydata
    reader = vtk.vtkPolyDataReader()
    reader.SetFileName(centerline)
    reader.Update()
    centerline = reader.GetOutput()

    # Read image
    nifti_reader = vtk.vtkNIFTIImageReader()
    nifti_reader.SetFileName(ref_image)
    nifti_reader.Update()

    modeller = vtkvmtk.vtkvmtkPolyBallModeller()
    modeller.SetInputData(centerline)
    modeller.SetRadiusArrayName("Radius")
    modeller.UsePolyBallLineOn()
    modeller.SetReferenceImage(nifti_reader.GetOutput())
    modeller.SetNegateFunction(0)
    modeller.Update()
    image = modeller.GetOutput()

    return image


if __name__ == '__main__':
    centerline = "path to .vtk centerline"
    ref_image = "path to reference nifty image"

    start = timeit.default_timer()
    image = centerline_to_image(centerline, ref_image)
    stop = timeit.default_timer()
    print('Time: ', stop - start)

    # Write image
    writer = vtk.vtkNIFTIImageWriter()
    writer.SetFileName("path to save nifty image")
    writer.SetInputData(image)
    writer.Write()