Threshold on Segment

I’m trying to threshold a volume to a created segment. Unfortunately the segment will be empty. What did I forget?

    # create SegmentationNode and Segment #

    self.segmentationNode = slicer.vtkMRMLSegmentationNode()
    slicer.mrmlScene.AddNode(self.segmentationNode)
    self.segmentPrintId = self.segmentationNode.GetSegmentation().AddEmptySegment("ThresholdSegment", "Segment_Threshold", [4,4,4])

    # threshold #

    import vtkSegmentationCorePython as vtkSegmentationCore
    segmentationsLogic = slicer.vtkSlicerSegmentationsModuleLogic()

    volumeNode = self.inputSelector.currentNode()  #volumeNode of a selector
    inputImageData = volumeNode.GetImageData()

    outputImageData = vtkSegmentationCore.vtkOrientedImageData()

    thresh = vtk.vtkImageThreshold()
    thresh.SetInputData(volumeNode.GetImageData())
    thresh.ThresholdBetween(self.imageThresholdSliderWidget.minimumValue, self.imageThresholdSliderWidget.maximumValue)
    thresh.SetInValue(1000)
    thresh.SetOutValue(0)
    thresh.SetOutputScalarType(outputImageData.GetScalarType())
    thresh.Update()
    outputImageData.DeepCopy(thresh.GetOutput())

    segmentationsLogic.SetBinaryLabelmapToSegment(outputImageData, self.segmentationNode, self.segmentPrintId)

Thank you again!

Hi Basti,

Thanks for the detailed report!

First of all, it is best to use the actual module logic, that has the MRML scene and everything:
segmentationsLogic = slicer.modules.segmentations.logic()

Second, I’d check if the output image actually contains a meaningful image, just for the sake of debugging. For example like this:
acc = vtk.vtkImageAccumulate() acc.SetInputData(outputImageData) acc.SetIgnoreZero(1) acc.Update() acc.GetVoxelCount() # Get number of non-zero voxels (should be >0) acc.SetIgnoreZero(0) acc.Update() acc.GetVoxelCount() # Get number of all voxels (should be different than the non-zero one) acc.GetMin() # Should be 0 acc.GetMax() # Should be 1000

Third, what is the return value of the last call? True or False? if it’s false, is there any error in the log? Circle button with X in it in bottom right corner, or whole log in Help/Report a bug.

Fourth, I think I found a bug that might explain the problem if the above three are all good. I did this to get the IDs in the segmentation:
ids=vtk.vtkStringArray() segmentationNode.GetSegmentation().GetSegmentIDs(ids) ids.GetValue(0)
and it is not the same as segmentPrintId, which should be. It seems that the names and IDs are not handled correctly by vtkSegmentation::AddEmptySegment. I will debug into it and see what the exact problem is.

For a short term solution you can just get the IDs the same way I did for testing.

The bug should be fixed in the commit below. Please download tomorrow’s nightly and try again.

1 Like

In tomorrow’s nightly version (that contains Csaba’s fixes) this will work:

import vtkSegmentationCorePython as vtkSegmentationCore

segmentationNode = slicer.vtkMRMLSegmentationNode()
slicer.mrmlScene.AddNode(segmentationNode)
segmentPrintId = segmentationNode.GetSegmentation().AddEmptySegment("ThresholdSegment", "Segment_Threshold", [1.0,1.0,0.0])

segmentationsLogic = slicer.modules.segmentations.logic()

volumeNode = getNode('MRHead')
inputImageData = segmentationsLogic.CreateOrientedImageDataFromVolumeNode(volumeNode)
inputImageData.UnRegister(None)

minThreshold = 20
maxThreshold = 80
thresh = vtk.vtkImageThreshold()
thresh.SetInputData(volumeNode.GetImageData())
thresh.ThresholdBetween(minThreshold, maxThreshold)
thresh.SetInValue(1000)
thresh.SetOutValue(0)
thresh.Update()

outputImageData = vtkSegmentationCore.vtkOrientedImageData()
outputImageData.ShallowCopy(thresh.GetOutput())
imageToWorldMatrix = vtk.vtkMatrix4x4()
inputImageData.GetImageToWorldMatrix(imageToWorldMatrix)
outputImageData.SetImageToWorldMatrix(imageToWorldMatrix)

segmentationsLogic.SetBinaryLabelmapToSegment(outputImageData, segmentationNode, segmentPrintId)

Thank you very much, now it works! I also added

segmentationNode.CreateDefaultDisplayNodes()

to display the Node.

2 Likes