I am attempting to segment out a pelvis bone model from a volume. I have noticed that the model generated from code is not the same as the one created from the GUI using the same parameters. take a look at the image below, the same parameters and effects in the same order were used to obtain both models, but the green section only shows up when applying the effects from the GUI. the rest of the green overlaps the tan.
through testing, it is apparent that the combination of Threshold > Smoothing (with median, opening, either or both) > Islands remove small islands operations cause this issue. I am wondering if this is because the previous operations are not fully complete when the islands operation begins, and since the voxels are still being placed, some are small enough to be removed by the islands operation. However, using self.delayMs does not appear to affect it in any way so i’m not sure about that.
does anyone know if this is the reason, or how to prevent it?
some more info:
i’m calling my operations like the skin surface example here: https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#How_to_run_segment_editor_effects_from_a_script
I’ve modified it to be more similar to my calls, i’m going to paste the modified code at the bottom if you want to replicate this.
if you follow the same operations in the gui on the sample data, it is clear that the python script has lost a fair portion of the model, it should look like this image with green being python code and tan being GUI generated:
import SampleData sampleDataLogic = SampleData.SampleDataLogic() masterVolumeNode = sampleDataLogic.downloadCTChest() # Create segmentation segmentationNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLSegmentationNode") segmentationNode.CreateDefaultDisplayNodes() # only needed for display segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(masterVolumeNode) addedSegmentID = segmentationNode.GetSegmentation().AddEmptySegment("bone") # Create segment editor to get access to effects segmentEditorWidget = slicer.qMRMLSegmentEditorWidget() segmentEditorWidget.setMRMLScene(slicer.mrmlScene) segmentEditorNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLSegmentEditorNode") segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode) segmentEditorWidget.setSegmentationNode(segmentationNode) segmentEditorWidget.setMasterVolumeNode(masterVolumeNode) # Thresholding segmentEditorWidget.setActiveEffectByName("Threshold") effect = segmentEditorWidget.activeEffect() effect.setParameter("MinimumThreshold","300") effect.setParameter("MaximumThreshold","3778") effect.self().onApply() # Smoothing segmentEditorWidget.setActiveEffectByName("Smoothing") effect = segmentEditorWidget.activeEffect() effect.setParameter("SmoothingMethod", "MEDIAN") effect.setParameter("KernelSizeMm", 3) effect.self().onApply() # Islands segmentEditorWidget.setActiveEffectByName("Islands") effect = segmentEditorWidget.activeEffect() effect.setParameter("Minimumsize", "1000") effect.setParameter("EditIslands", "RsEMOVE_SMALL_ISLANDS") effect.self().onApply() # Clean up segmentEditorWidget = None slicer.mrmlScene.RemoveNode(segmentEditorNode) # Make segmentation results visible in 3D segmentationNode.CreateClosedSurfaceRepresentation() # Make sure surface mesh cells are consistently oriented surfaceMesh = segmentationNode.GetClosedSurfaceRepresentation(addedSegmentID) normals = vtk.vtkPolyDataNormals() normals.AutoOrientNormalsOn() normals.ConsistencyOn() normals.SetInputData(surfaceMesh) normals.Update() surfaceMesh = normals.GetOutput()