VMTK Extract Centerline with python console

OK, I looked a little deeper into the ExtractCenterline.py code, and I think what you need is the vtkPolyData for the closed surface representation of the segment.

segmentation = aorta_seg.GetSegmentation()
segmentID = segmentation.GetSegmentIDBySegmentName('Segment_1')
aorta_seg.CreateClosedSurfaceRepresentation() # just to ensure this representation exists
segmentVtkPolyData = vtk.vtkPolyData() # create empty vtkPolyData object
# Get vtkPolyData representation of segment surface into segmentVtkPolyData variable
aorta_seg.GetClosedSurfaceRepresentation(segmentID, segmentVtkPolyData)

For the rest of the details of how to use the VMTK centerline extraction from python inside Slicer, the best place to look is at the code from ExtractCenterline.py, available here: https://github.com/vmtk/SlicerExtension-VMTK/blob/3787ea4a300da28ec5f0824f0715f2713b631155/ExtractCenterline/ExtractCenterline.py

Some longer example code which might be helpful

In some old code, I found a method from inside a custom scripted Slicer module I had developed which uses the ExtractCenterline module’s logic.

    def onGenerateCenterlineButtonClick(self):
        """Trying to mimic the implementation in ExtractCenterline.py from VMTK module"""
        qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor)
        try:
            ## Gather inputs ##
            linkedAirwaySegmentationNode = self._parameterNode.GetNodeReference(
                "LinkedAirwaySegmentationNode"
            )
            linkedAirwaySegmentID = (
                self.ui.linkedAirwaySegmentSelectorWidget.currentSegmentID()
            )
            endPointsMarkupsNode = self._parameterNode.GetNodeReference(
                "EndpointsFiducialNode"
            )
            import ExtractCenterline

            extractLogic = ExtractCenterline.ExtractCenterlineLogic()
            ## Preprocess ##
            inputSurfacePolyData = extractLogic.polyDataFromNode(
                linkedAirwaySegmentationNode, linkedAirwaySegmentID
            )
            if (
                not inputSurfacePolyData
                or inputSurfacePolyData.GetNumberOfPoints() == 0
            ):
                raise ValueError("Valid input surface is required")
            # These are the default values in the VMTK module, which I have never had to change (until I ran into an error)
            # OK, now I've had to change decimationAggressiveness down to 3.5 from 4.0.  Preprocessed surface had inverted segments after decimation
            # which lead to failed centerline curve.  It is possible that we could detect failed curve if it has only two control points? (That was the
            # case in the single failure so far). If so, we could re-run with lower decimation aggressiveness.
            preprocessEnabled = True  # (self._parameterNode.GetParameter("PreprocessInputSurface") == "true")
            targetNumberOfPoints = 5000.0  # float(self._parameterNode.GetParameter("TargetNumberOfPoints"))
            decimationAggressiveness = 3.5  # 4.0 #float(self._parameterNode.GetParameter("DecimationAggressiveness"))
            subdivideInputSurface = False  # (self._parameterNode.GetParameter("SubdivideInputSurface") == "true")
            slicer.util.showStatusMessage(
                "Preprocessing surface before centerline extraction..."
            )
            slicer.app.processEvents()
            preprocessedPolyData = extractLogic.preprocess(
                inputSurfacePolyData,
                targetNumberOfPoints,
                decimationAggressiveness,
                subdivideInputSurface,
            )
            ## Extract centerline ##
            centerlineCurveNode = self._parameterNode.GetNodeReference(
                "CenterlineCurveNode"
            )
            if centerlineCurveNode is None:
                centerlineCurveNode = slicer.mrmlScene.AddNewNodeByClass(
                    "vtkMRMLMarkupsCurveNode", "Centerline curve"
                )
            slicer.util.showStatusMessage("Extracting centerline...")
            slicer.app.processEvents()  # force update
            centerlinePolyData, voronoiDiagramPolyData = extractLogic.extractCenterline(
                preprocessedPolyData, endPointsMarkupsNode
            )
            slicer.util.showStatusMessage(
                "Generating curves and quantification results table..."
            )
            slicer.app.processEvents()  # force update
            centerlinePropertiesTableNode = None
            extractLogic.createCurveTreeFromCenterline(
                centerlinePolyData, centerlineCurveNode, centerlinePropertiesTableNode
            )
            if centerlineCurveNode.GetNumberOfControlPoints() == 2:
                # Extraction had an error, likely due to too high decimation aggressiveness
                # Try again
                slicer.util.errorDisplay(
                    "Centerline generation failed, possibly due to decimationAggressiveness being too high."
                )
                # TODO TODO TODO: implement automatically trying again, with message to user about what's going on
        except Exception as e:
            slicer.util.errorDisplay("Failed to compute results: " + str(e))
            import traceback

            traceback.print_exc()
        qt.QApplication.restoreOverrideCursor()
        slicer.util.showStatusMessage("Centerline analysis complete.", 3000)
        self._parameterNode.SetNodeReferenceID(
            "CenterlineCurveNode", centerlineCurveNode.GetID()
        )
2 Likes