def removeIslands(self): # # change the label values based on the parameter node # if not self.sliceLogic: self.sliceLogic = self.editUtil.getSliceLogic() parameterNode = self.editUtil.getParameterNode() minimumSize = int(parameterNode.GetParameter("IslandEffect,minimumSize")) fullyConnected = bool(parameterNode.GetParameter("IslandEffect,fullyConnected")) label = self.editUtil.getLabel() # first, create an inverse binary version of the image # so that islands inside segemented object will be detected, along # with a big island of the background preThresh = vtk.vtkImageThreshold() preThresh.SetInValue( 0 ) preThresh.SetOutValue( 1 ) preThresh.ReplaceInOn() preThresh.ReplaceOutOn() preThresh.ThresholdBetween( label,label ) preThresh.SetInput( self.getScopedLabelInput() ) preThresh.SetOutputScalarTypeToUnsignedLong() # now identify the islands in the inverted volume # and find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() islandMath.SetInput( preThresh.GetOutput() ) islandMath.SetFullyConnected( fullyConnected ) islandMath.SetMinimumSize( minimumSize ) # TODO: $this setProgressFilter $islandMath "Calculating Islands..." islandMath.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount print( "%d islands created (%d ignored)" % (islandCount, ignoredIslands) ) # now rethreshold so that everything which is not background becomes the label postThresh = vtk.vtkImageThreshold() postThresh.SetInValue( label ) postThresh.SetOutValue( 0 ) postThresh.ReplaceInOn() postThresh.ReplaceOutOn() postThresh.ThresholdBetween( 0, 0 ) postThresh.SetOutputScalarTypeToShort() postThresh.SetInput( islandMath.GetOutput() ) postThresh.SetOutput( self.getScopedLabelOutput() ) # TODO $this setProgressFilter $postThresh "Applying to Label Map..." postThresh.Update() self.applyScopedLabel()
def onApply(self): # This can be a long operation - indicate it to the user qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor) self.scriptedEffect.saveStateForUndo() # Get parameters fullyConnected = self.scriptedEffect.integerParameter("FullyConnected") minimumSize = self.scriptedEffect.integerParameter("MinimumSize") # Get modifier labelmap selectedSegmentLabelmap = self.scriptedEffect.selectedSegmentLabelmap() castIn = vtk.vtkImageCast() castIn.SetInputData(selectedSegmentLabelmap) castIn.SetOutputScalarTypeToUnsignedLong() # Identify the islands in the inverted volume and # find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() islandMath.SetInputConnection(castIn.GetOutputPort()) islandMath.SetFullyConnected(fullyConnected) islandMath.SetMinimumSize(minimumSize) # Note that island operation happens in unsigned long space # but the segment editor works in unsigned char castOut = vtk.vtkImageCast() castOut.SetInputConnection(islandMath.GetOutputPort()) castOut.SetOutputScalarTypeToUnsignedChar() castOut.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount logging.info("%d islands created (%d ignored)" % (islandCount, ignoredIslands)) # Create oriented image data from output import vtkSegmentationCorePython as vtkSegmentationCore multiLabelImage = vtkSegmentationCore.vtkOrientedImageData() multiLabelImage.DeepCopy(castOut.GetOutput()) selectedSegmentLabelmapImageToWorldMatrix = vtk.vtkMatrix4x4() selectedSegmentLabelmap.GetImageToWorldMatrix( selectedSegmentLabelmapImageToWorldMatrix) multiLabelImage.SetGeometryFromImageToWorldMatrix( selectedSegmentLabelmapImageToWorldMatrix) # Import multi-label labelmap to segmentation segmentationNode = self.scriptedEffect.parameterSetNode( ).GetSegmentationNode() selectedSegmentID = self.scriptedEffect.parameterSetNode( ).GetSelectedSegmentID() selectedSegmentName = segmentationNode.GetSegmentation().GetSegment( selectedSegmentID).GetName() slicer.vtkSlicerSegmentationsModuleLogic.ImportLabelmapToSegmentationNode( \ multiLabelImage, segmentationNode, selectedSegmentName ) segmentationNode.GetSegmentation().RemoveSegment(selectedSegmentID) qt.QApplication.restoreOverrideCursor()
def onApply(self): # TODO: # self.logic.undoRedo = self.undoRedo # Get parameters fullyConnected = self.scriptedEffect.integerParameter("FullyConnected") minimumSize = self.scriptedEffect.integerParameter("MinimumSize") # Get modifier labelmap selectedSegmentLabelmap = self.scriptedEffect.selectedSegmentLabelmap() castIn = vtk.vtkImageCast() castIn.SetInputData(selectedSegmentLabelmap) castIn.SetOutputScalarTypeToUnsignedLong() # Identify the islands in the inverted volume and # find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() islandMath.SetInputConnection(castIn.GetOutputPort()) islandMath.SetFullyConnected(fullyConnected) islandMath.SetMinimumSize(minimumSize) # Note that island operation happens in unsigned long space # but the segment editor works in unsigned char castOut = vtk.vtkImageCast() castOut.SetInputConnection(islandMath.GetOutputPort()) castOut.SetOutputScalarTypeToUnsignedChar() castOut.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount logging.info("%d islands created (%d ignored)" % (islandCount, ignoredIslands)) # Create oriented image data from output import vtkSegmentationCorePython as vtkSegmentationCore multiLabelImage = vtkSegmentationCore.vtkOrientedImageData() multiLabelImage.DeepCopy(castOut.GetOutput()) selectedSegmentLabelmapImageToWorldMatrix = vtk.vtkMatrix4x4() selectedSegmentLabelmap.GetImageToWorldMatrix(selectedSegmentLabelmapImageToWorldMatrix) multiLabelImage.SetGeometryFromImageToWorldMatrix(selectedSegmentLabelmapImageToWorldMatrix) # Import multi-label labelmap to segmentation segmentationNode = self.scriptedEffect.parameterSetNode().GetSegmentationNode() selectedSegmentID = self.scriptedEffect.parameterSetNode().GetSelectedSegmentID() selectedSegmentName = segmentationNode.GetSegmentation().GetSegment(selectedSegmentID).GetName() slicer.vtkSlicerSegmentationsModuleLogic.ImportLabelmapToSegmentationNode( multiLabelImage, segmentationNode, selectedSegmentName ) # Set labelmap visibility to outline for the new segments displayNode = segmentationNode.GetDisplayNode() # for index in xrange(1,islandCount+1): # segmentID = selectedSegmentName + "_" + str(index) # displayNode.SetSegmentVisibility2DFill(segmentID, False) # displayNode.SetSegmentVisibility2DOutline(segmentID, True) displayNode.SetSegmentVisibility(selectedSegmentID, False)
def onApply(self): #TODO: #self.logic.undoRedo = self.undoRedo # Get parameters fullyConnected = self.scriptedEffect.integerParameter("FullyConnected") minimumSize = self.scriptedEffect.integerParameter("MinimumSize") # Get modifier labelmap selectedSegmentLabelmap = self.scriptedEffect.selectedSegmentLabelmap() castIn = vtk.vtkImageCast() castIn.SetInputData(selectedSegmentLabelmap) castIn.SetOutputScalarTypeToUnsignedLong() # Identify the islands in the inverted volume and # find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() islandMath.SetInputConnection(castIn.GetOutputPort()) islandMath.SetFullyConnected(fullyConnected) islandMath.SetMinimumSize(minimumSize) # Note that island operation happens in unsigned long space # but the segment editor works in unsigned char castOut = vtk.vtkImageCast() castOut.SetInputConnection(islandMath.GetOutputPort()) castOut.SetOutputScalarTypeToUnsignedChar() castOut.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount logging.info( "%d islands created (%d ignored)" % (islandCount, ignoredIslands) ) # Create oriented image data from output import vtkSegmentationCorePython as vtkSegmentationCore multiLabelImage = vtkSegmentationCore.vtkOrientedImageData() multiLabelImage.DeepCopy(castOut.GetOutput()) selectedSegmentLabelmapImageToWorldMatrix = vtk.vtkMatrix4x4() selectedSegmentLabelmap.GetImageToWorldMatrix(selectedSegmentLabelmapImageToWorldMatrix) multiLabelImage.SetGeometryFromImageToWorldMatrix(selectedSegmentLabelmapImageToWorldMatrix) # Import multi-label labelmap to segmentation segmentationNode = self.scriptedEffect.parameterSetNode().GetSegmentationNode() selectedSegmentID = self.scriptedEffect.parameterSetNode().GetSelectedSegmentID() selectedSegmentName = segmentationNode.GetSegmentation().GetSegment(selectedSegmentID).GetName() slicer.vtkSlicerSegmentationsModuleLogic.ImportLabelmapToSegmentationNode( \ multiLabelImage, segmentationNode, selectedSegmentName ) # Set labelmap visibility to outline for the new segments displayNode = segmentationNode.GetDisplayNode() #for index in xrange(1,islandCount+1): # segmentID = selectedSegmentName + "_" + str(index) # displayNode.SetSegmentVisibility2DFill(segmentID, False) # displayNode.SetSegmentVisibility2DOutline(segmentID, True) displayNode.SetSegmentVisibility(selectedSegmentID, False)
def onApply(self): # This can be a long operation - indicate it to the user qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor) self.scriptedEffect.saveStateForUndo() # Get parameters fullyConnected = self.scriptedEffect.integerParameter("FullyConnected") minimumSize = self.scriptedEffect.integerParameter("MinimumSize") # Get modifier labelmap selectedSegmentLabelmap = self.scriptedEffect.selectedSegmentLabelmap() castIn = vtk.vtkImageCast() castIn.SetInputData(selectedSegmentLabelmap) castIn.SetOutputScalarTypeToUnsignedLong() # Identify the islands in the inverted volume and # find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() islandMath.SetInputConnection(castIn.GetOutputPort()) islandMath.SetFullyConnected(fullyConnected) islandMath.SetMinimumSize(minimumSize) # Note that island operation happens in unsigned long space # but the segment editor works in unsigned char castOut = vtk.vtkImageCast() castOut.SetInputConnection(islandMath.GetOutputPort()) castOut.SetOutputScalarTypeToUnsignedChar() castOut.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount logging.info( "%d islands created (%d ignored)" % (islandCount, ignoredIslands) ) # Create oriented image data from output import vtkSegmentationCorePython as vtkSegmentationCore multiLabelImage = vtkSegmentationCore.vtkOrientedImageData() multiLabelImage.DeepCopy(castOut.GetOutput()) selectedSegmentLabelmapImageToWorldMatrix = vtk.vtkMatrix4x4() selectedSegmentLabelmap.GetImageToWorldMatrix(selectedSegmentLabelmapImageToWorldMatrix) multiLabelImage.SetGeometryFromImageToWorldMatrix(selectedSegmentLabelmapImageToWorldMatrix) # Import multi-label labelmap to segmentation segmentationNode = self.scriptedEffect.parameterSetNode().GetSegmentationNode() selectedSegmentID = self.scriptedEffect.parameterSetNode().GetSelectedSegmentID() selectedSegmentName = segmentationNode.GetSegmentation().GetSegment(selectedSegmentID).GetName() slicer.vtkSlicerSegmentationsModuleLogic.ImportLabelmapToSegmentationNode( \ multiLabelImage, segmentationNode, selectedSegmentName ) segmentationNode.GetSegmentation().RemoveSegment(selectedSegmentID) qt.QApplication.restoreOverrideCursor()
def removeIslands(self): # # change the label values based on the parameter node # if not self.sliceLogic: self.sliceLogic = self.editUtil.getSliceLogic() parameterNode = self.editUtil.getParameterNode() minimumSize = int( parameterNode.GetParameter("IslandEffect,minimumSize")) fullyConnected = bool( parameterNode.GetParameter("IslandEffect,fullyConnected")) label = self.editUtil.getLabel() # note that island operation happens in unsigned long space # but the slicer editor works in Short castIn = vtk.vtkImageCast() if vtk.VTK_MAJOR_VERSION <= 5: castIn.SetInput(self.getScopedLabelInput()) else: castIn.SetInputData(self.getScopedLabelInput()) castIn.SetOutputScalarTypeToUnsignedLong() # now identify the islands in the inverted volume # and find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() if vtk.VTK_MAJOR_VERSION <= 5: islandMath.SetInput(castIn.GetOutput()) else: islandMath.SetInputConnection(castIn.GetOutputPort()) islandMath.SetFullyConnected(fullyConnected) islandMath.SetMinimumSize(minimumSize) # TODO: $this setProgressFilter $islandMath "Calculating Islands..." # note that island operation happens in unsigned long space # but the slicer editor works in Short castOut = vtk.vtkImageCast() if vtk.VTK_MAJOR_VERSION <= 5: castOut.SetInput(islandMath.GetOutput()) else: castOut.SetInputConnection(islandMath.GetOutputPort()) castOut.SetOutputScalarTypeToShort() castOut.SetOutput(self.getScopedLabelOutput()) # TODO $this setProgressFilter $postThresh "Applying to Label Map..." castOut.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount print("%d islands created (%d ignored)" % (islandCount, ignoredIslands)) self.applyScopedLabel() castOut.SetOutput(None)
def removeIslands(self): # # change the label values based on the parameter node # if not self.sliceLogic: self.sliceLogic = self.editUtil.getSliceLogic() parameterNode = self.editUtil.getParameterNode() minimumSize = int(parameterNode.GetParameter("IslandEffect,minimumSize")) fullyConnected = bool(parameterNode.GetParameter("IslandEffect,fullyConnected")) label = self.editUtil.getLabel() # note that island operation happens in unsigned long space # but the slicer editor works in Short castIn = vtk.vtkImageCast() if vtk.VTK_MAJOR_VERSION <= 5: castIn.SetInput( self.getScopedLabelInput() ) else: castIn.SetInputData( self.getScopedLabelInput() ) castIn.SetOutputScalarTypeToUnsignedLong() # now identify the islands in the inverted volume # and find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() if vtk.VTK_MAJOR_VERSION <= 5: islandMath.SetInput( castIn.GetOutput() ) else: islandMath.SetInputConnection( castIn.GetOutputPort() ) islandMath.SetFullyConnected( fullyConnected ) islandMath.SetMinimumSize( minimumSize ) # TODO: $this setProgressFilter $islandMath "Calculating Islands..." # note that island operation happens in unsigned long space # but the slicer editor works in Short castOut = vtk.vtkImageCast() if vtk.VTK_MAJOR_VERSION <= 5: castOut.SetInput( islandMath.GetOutput() ) else: castOut.SetInputConnection( islandMath.GetOutputPort() ) castOut.SetOutputScalarTypeToShort() castOut.SetOutput( self.getScopedLabelOutput() ) # TODO $this setProgressFilter $postThresh "Applying to Label Map..." castOut.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount print( "%d islands created (%d ignored)" % (islandCount, ignoredIslands) ) self.applyScopedLabel() castOut.SetOutput( None )
def identIslands(self): inputImage=self.volume.GetImageData() labelImage=self.label.GetImageData() #labelImage.SetSpacing(self.label.GetSpacing()) IJKToRAS = vtk.vtkMatrix4x4() self.volume.GetIJKToRASMatrix(IJKToRAS) self.label.SetIJKToRASMatrix(IJKToRAS) eV=slicer.vtkFillVOIImageFilter() eV.SetfillValue(0) eV.SetInputData(inputImage) if self.sliceidx>0: VOIpre=[0,inputImage.GetDimensions()[0],0,inputImage.GetDimensions()[1],0,self.sliceidx-1] eV.AddVOI(VOIpre) if self.sliceidx<inputImage.GetDimensions()[2]: VOIpost=[0,inputImage.GetDimensions()[0],0,inputImage.GetDimensions()[1],self.sliceidx+1,inputImage.GetDimensions()[2]] eV.AddVOI(VOIpost) eV.Update() slice=eV.GetOutput() thresh = vtk.vtkImageThreshold() thresh.SetInputData(slice) thresh.ThresholdBetween(self.thrRange[0],self.thrRange[1]) thresh.SetInValue(1) thresh.SetOutValue(0) thresh.SetOutputScalarType(vtk.VTK_SHORT) thresh.Modified() thresh.Update() islandM=vtkITK.vtkITKIslandMath() islandM.SetInputData(thresh.GetOutput()) islandM.Update() labelImage.DeepCopy(islandM.GetOutput())
def splitSegments(self, minimumSize=0, maxNumberOfSegments=0, split=True): """ minimumSize: if 0 then it means that all islands are kept, regardless of size maxNumberOfSegments: if 0 then it means that all islands are kept, regardless of how many """ # This can be a long operation - indicate it to the user qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor) self.scriptedEffect.saveStateForUndo() # Get modifier labelmap selectedSegmentLabelmap = self.scriptedEffect.selectedSegmentLabelmap() castIn = vtk.vtkImageCast() castIn.SetInputData(selectedSegmentLabelmap) castIn.SetOutputScalarTypeToUnsignedInt() # Identify the islands in the inverted volume and # find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() islandMath.SetInputConnection(castIn.GetOutputPort()) islandMath.SetFullyConnected(False) islandMath.SetMinimumSize(minimumSize) islandMath.Update() # Create a separate image for the first (largest) island labelValue = 1 backgroundValue = 0 thresh = vtk.vtkImageThreshold() if split: thresh.ThresholdBetween(1, 1) else: if maxNumberOfSegments != 0: thresh.ThresholdBetween(1, maxNumberOfSegments) else: thresh.ThresholdByUpper(1) thresh.SetInputData(islandMath.GetOutput()) thresh.SetOutValue(backgroundValue) thresh.SetInValue(labelValue) thresh.SetOutputScalarType(selectedSegmentLabelmap.GetScalarType()) thresh.Update() # Create oriented image data from output import vtkSegmentationCorePython as vtkSegmentationCore largestIslandImage = vtkSegmentationCore.vtkOrientedImageData() largestIslandImage.ShallowCopy(thresh.GetOutput()) selectedSegmentLabelmapImageToWorldMatrix = vtk.vtkMatrix4x4() selectedSegmentLabelmap.GetImageToWorldMatrix( selectedSegmentLabelmapImageToWorldMatrix) largestIslandImage.SetImageToWorldMatrix( selectedSegmentLabelmapImageToWorldMatrix) if split and (maxNumberOfSegments != 1): thresh2 = vtk.vtkImageThreshold() # 0 is background, 1 is largest island; we need label 2 and higher if maxNumberOfSegments != 0: thresh2.ThresholdBetween(2, maxNumberOfSegments) else: thresh2.ThresholdByUpper(2) thresh2.SetInputData(islandMath.GetOutput()) thresh2.SetOutValue(backgroundValue) thresh2.ReplaceInOff() thresh2.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount logging.info("%d islands created (%d ignored)" % (islandCount, ignoredIslands)) # Create oriented image data from output import vtkSegmentationCorePython as vtkSegmentationCore multiLabelImage = vtkSegmentationCore.vtkOrientedImageData() multiLabelImage.DeepCopy(thresh2.GetOutput()) selectedSegmentLabelmapImageToWorldMatrix = vtk.vtkMatrix4x4() selectedSegmentLabelmap.GetImageToWorldMatrix( selectedSegmentLabelmapImageToWorldMatrix) multiLabelImage.SetGeometryFromImageToWorldMatrix( selectedSegmentLabelmapImageToWorldMatrix) # Import multi-label labelmap to segmentation segmentationNode = self.scriptedEffect.parameterSetNode( ).GetSegmentationNode() selectedSegmentID = self.scriptedEffect.parameterSetNode( ).GetSelectedSegmentID() selectedSegmentIndex = segmentationNode.GetSegmentation( ).GetSegmentIndex(selectedSegmentID) insertBeforeSegmentID = segmentationNode.GetSegmentation( ).GetNthSegmentID(selectedSegmentIndex + 1) selectedSegmentName = segmentationNode.GetSegmentation( ).GetSegment(selectedSegmentID).GetName() slicer.vtkSlicerSegmentationsModuleLogic.ImportLabelmapToSegmentationNode( \ multiLabelImage, segmentationNode, selectedSegmentName+" -", insertBeforeSegmentID ) self.scriptedEffect.modifySelectedSegmentByLabelmap( largestIslandImage, slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeSet) qt.QApplication.restoreOverrideCursor()
def removeIslands(self): # # change the label values based on the parameter node # if not self.sliceLogic: self.sliceLogic = self.editUtil.getSliceLogic() parameterNode = self.editUtil.getParameterNode() minimumSize = int(parameterNode.GetParameter("IslandEffect,minimumSize")) fullyConnected = bool(parameterNode.GetParameter("IslandEffect,fullyConnected")) label = self.editUtil.getLabel() # first, create an inverse binary version of the image # so that islands inside segemented object will be detected, along # with a big island of the background preThresh = vtk.vtkImageThreshold() preThresh.SetInValue( 0 ) preThresh.SetOutValue( 1 ) preThresh.ReplaceInOn() preThresh.ReplaceOutOn() preThresh.ThresholdBetween( label,label ) preThresh.SetInput( self.getScopedLabelInput() ) preThresh.SetOutputScalarTypeToUnsignedLong() # now identify the islands in the inverted volume # and find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() islandMath.SetInput( preThresh.GetOutput() ) islandMath.SetFullyConnected( fullyConnected ) islandMath.SetMinimumSize( minimumSize ) # TODO: $this setProgressFilter $islandMath "Calculating Islands..." islandMath.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount print( "%d islands created (%d ignored)" % (islandCount, ignoredIslands) ) if islandCount == 0: return bgPixel = self.findNonZeroBorderPixel(islandMath.GetOutput()) # now rethreshold so that everything which is not background becomes the label postThresh = vtk.vtkImageThreshold() postThresh.SetInValue( 0 ) postThresh.SetOutValue( label ) postThresh.ReplaceInOn() postThresh.ReplaceOutOn() postThresh.ThresholdBetween( bgPixel, bgPixel ) postThresh.SetOutputScalarTypeToShort() postThresh.SetInput( islandMath.GetOutput() ) postThresh.SetOutput( self.getScopedLabelOutput() ) # TODO $this setProgressFilter $postThresh "Applying to Label Map..." postThresh.Update() self.applyScopedLabel() if False: # some code for debugging - leave it in layerLogic = self.sliceLogic.GetLabelLayer() labelNode = layerLogic.GetVolumeNode() volumesLogic = slicer.modules.volumes.logic() thresh1 = volumesLogic.CloneVolume(slicer.mrmlScene, labelNode, 'thres1') islands = volumesLogic.CloneVolume(slicer.mrmlScene, labelNode, 'islands') thresh2 = volumesLogic.CloneVolume(slicer.mrmlScene, labelNode, 'thres2') cast = vtk.vtkImageCast() cast.SetOutputScalarTypeToShort() cast.SetInput(preThresh.GetOutput()) cast.Update() thresh1.SetAndObserveImageData(cast.GetOutput()) cast2 = vtk.vtkImageCast() cast2.SetOutputScalarTypeToShort() cast2.SetInput(islandMath.GetOutput()) cast2.Update() islands.SetAndObserveImageData(cast2.GetOutput()) thresh2.SetAndObserveImageData(postThresh.GetOutput())
def splitSegments(self, minimumSize=0, maxNumberOfSegments=0, split=True): """ minimumSize: if 0 then it means that all islands are kept, regardless of size maxNumberOfSegments: if 0 then it means that all islands are kept, regardless of how many """ # This can be a long operation - indicate it to the user qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor) self.scriptedEffect.saveStateForUndo() # Get modifier labelmap selectedSegmentLabelmap = self.scriptedEffect.selectedSegmentLabelmap() castIn = vtk.vtkImageCast() castIn.SetInputData(selectedSegmentLabelmap) castIn.SetOutputScalarTypeToUnsignedInt() # Identify the islands in the inverted volume and # find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() islandMath.SetInputConnection(castIn.GetOutputPort()) islandMath.SetFullyConnected(False) islandMath.SetMinimumSize(minimumSize) islandMath.Update() islandImage = slicer.vtkOrientedImageData() islandImage.ShallowCopy(islandMath.GetOutput()) selectedSegmentLabelmapImageToWorldMatrix = vtk.vtkMatrix4x4() selectedSegmentLabelmap.GetImageToWorldMatrix( selectedSegmentLabelmapImageToWorldMatrix) islandImage.SetImageToWorldMatrix( selectedSegmentLabelmapImageToWorldMatrix) islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount logging.info("%d islands created (%d ignored)" % (islandCount, ignoredIslands)) baseSegmentName = "Label" selectedSegmentID = self.scriptedEffect.parameterSetNode( ).GetSelectedSegmentID() segmentationNode = self.scriptedEffect.parameterSetNode( ).GetSegmentationNode() with slicer.util.NodeModify(segmentationNode): segmentation = segmentationNode.GetSegmentation() selectedSegment = segmentation.GetSegment(selectedSegmentID) selectedSegmentName = selectedSegment.GetName() if selectedSegmentName is not None and selectedSegmentName != "": baseSegmentName = selectedSegmentName labelValues = vtk.vtkIntArray() slicer.vtkSlicerSegmentationsModuleLogic.GetAllLabelValues( labelValues, islandImage) # Erase segment from in original labelmap. # Individuall islands will be added back later. threshold = vtk.vtkImageThreshold() threshold.SetInputData(selectedSegmentLabelmap) threshold.ThresholdBetween(0, 0) threshold.SetInValue(0) threshold.SetOutValue(0) threshold.Update() emptyLabelmap = slicer.vtkOrientedImageData() emptyLabelmap.ShallowCopy(threshold.GetOutput()) emptyLabelmap.CopyDirections(selectedSegmentLabelmap) self.scriptedEffect.modifySegmentByLabelmap( segmentationNode, selectedSegmentID, emptyLabelmap, slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeSet) for i in range(labelValues.GetNumberOfTuples()): if (maxNumberOfSegments > 0 and i >= maxNumberOfSegments): # We only care about the segments up to maxNumberOfSegments. # If we do not want to split segments, we only care about the first. break labelValue = int(labelValues.GetTuple1(i)) segment = selectedSegment segmentID = selectedSegmentID if i != 0 and split: segment = slicer.vtkSegment() name = baseSegmentName + "_" + str(i + 1) segment.SetName(name) segment.AddRepresentation( slicer.vtkSegmentationConverter. GetSegmentationBinaryLabelmapRepresentationName(), selectedSegment.GetRepresentation( slicer.vtkSegmentationConverter. GetSegmentationBinaryLabelmapRepresentationName())) segmentation.AddSegment(segment) segmentID = segmentation.GetSegmentIdBySegment(segment) segment.SetLabelValue( segmentation.GetUniqueLabelValueForSharedLabelmap( selectedSegmentID)) threshold = vtk.vtkImageThreshold() threshold.SetInputData(islandMath.GetOutput()) threshold.ThresholdBetween(labelValue, labelValue) threshold.SetInValue(1) threshold.SetOutValue(0) threshold.Update() modificationMode = slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeAdd if i == 0: modificationMode = slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeSet # Create oriented image data from output modifierImage = slicer.vtkOrientedImageData() modifierImage.DeepCopy(threshold.GetOutput()) selectedSegmentLabelmapImageToWorldMatrix = vtk.vtkMatrix4x4() selectedSegmentLabelmap.GetImageToWorldMatrix( selectedSegmentLabelmapImageToWorldMatrix) modifierImage.SetGeometryFromImageToWorldMatrix( selectedSegmentLabelmapImageToWorldMatrix) # We could use a single slicer.vtkSlicerSegmentationsModuleLogic.ImportLabelmapToSegmentationNode # method call to import all the resulting segments at once but that would put all the imported segments # in a new layer. By using modifySegmentByLabelmap, the number of layers will not increase. self.scriptedEffect.modifySegmentByLabelmap( segmentationNode, segmentID, modifierImage, modificationMode) qt.QApplication.restoreOverrideCursor()
def splitSegments(self, minimumSize = 0, maxNumberOfSegments = 0, split = True): """ minimumSize: if 0 then it means that all islands are kept, regardless of size maxNumberOfSegments: if 0 then it means that all islands are kept, regardless of how many """ # This can be a long operation - indicate it to the user qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor) self.scriptedEffect.saveStateForUndo() # Get modifier labelmap selectedSegmentLabelmap = self.scriptedEffect.selectedSegmentLabelmap() castIn = vtk.vtkImageCast() castIn.SetInputData(selectedSegmentLabelmap) castIn.SetOutputScalarTypeToUnsignedInt() # Identify the islands in the inverted volume and # find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() islandMath.SetInputConnection(castIn.GetOutputPort()) islandMath.SetFullyConnected(False) islandMath.SetMinimumSize(minimumSize) islandMath.Update() # Create a separate image for the first (largest) island labelValue = 1 backgroundValue = 0 thresh = vtk.vtkImageThreshold() if split: thresh.ThresholdBetween(1, 1) else: if maxNumberOfSegments != 0: thresh.ThresholdBetween(1, maxNumberOfSegments) else: thresh.ThresholdByUpper(1) thresh.SetInputData(islandMath.GetOutput()) thresh.SetOutValue(backgroundValue) thresh.SetInValue(labelValue) thresh.SetOutputScalarType(selectedSegmentLabelmap.GetScalarType()) thresh.Update() # Create oriented image data from output import vtkSegmentationCorePython as vtkSegmentationCore largestIslandImage = vtkSegmentationCore.vtkOrientedImageData() largestIslandImage.ShallowCopy(thresh.GetOutput()) selectedSegmentLabelmapImageToWorldMatrix = vtk.vtkMatrix4x4() selectedSegmentLabelmap.GetImageToWorldMatrix(selectedSegmentLabelmapImageToWorldMatrix) largestIslandImage.SetImageToWorldMatrix(selectedSegmentLabelmapImageToWorldMatrix) if split and (maxNumberOfSegments != 1): thresh2 = vtk.vtkImageThreshold() # 0 is background, 1 is largest island; we need label 2 and higher if maxNumberOfSegments != 0: thresh2.ThresholdBetween(2, maxNumberOfSegments) else: thresh2.ThresholdByUpper(2) thresh2.SetInputData(islandMath.GetOutput()) thresh2.SetOutValue(backgroundValue) thresh2.ReplaceInOff() thresh2.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount logging.info( "%d islands created (%d ignored)" % (islandCount, ignoredIslands) ) # Create oriented image data from output import vtkSegmentationCorePython as vtkSegmentationCore multiLabelImage = vtkSegmentationCore.vtkOrientedImageData() multiLabelImage.DeepCopy(thresh2.GetOutput()) selectedSegmentLabelmapImageToWorldMatrix = vtk.vtkMatrix4x4() selectedSegmentLabelmap.GetImageToWorldMatrix(selectedSegmentLabelmapImageToWorldMatrix) multiLabelImage.SetGeometryFromImageToWorldMatrix(selectedSegmentLabelmapImageToWorldMatrix) # Import multi-label labelmap to segmentation segmentationNode = self.scriptedEffect.parameterSetNode().GetSegmentationNode() selectedSegmentID = self.scriptedEffect.parameterSetNode().GetSelectedSegmentID() selectedSegmentIndex = segmentationNode.GetSegmentation().GetSegmentIndex(selectedSegmentID) insertBeforeSegmentID = segmentationNode.GetSegmentation().GetNthSegmentID(selectedSegmentIndex + 1) selectedSegmentName = segmentationNode.GetSegmentation().GetSegment(selectedSegmentID).GetName() slicer.vtkSlicerSegmentationsModuleLogic.ImportLabelmapToSegmentationNode( \ multiLabelImage, segmentationNode, selectedSegmentName+" -", insertBeforeSegmentID ) self.scriptedEffect.modifySelectedSegmentByLabelmap(largestIslandImage, slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeSet) qt.QApplication.restoreOverrideCursor()
def removeIslandsMorphologyDecruft(self, image, foregroundLabel, backgroundLabel, iterations=1): # # make binary mask foregroundLabel->1, backgroundLabel->0 # binThresh = vtk.vtkImageThreshold() binThresh.SetInputData(image) binThresh.ThresholdBetween(foregroundLabel, foregroundLabel) binThresh.SetInValue(1) binThresh.SetOutValue(0) binThresh.Update() # # first, erode iterations number of times # eroder = slicer.vtkImageErode() eroderImage = vtk.vtkImageData() eroderImage.DeepCopy(binThresh.GetOutput()) eroder.SetInputData(eroderImage) for iteration in range(iterations): eroder.SetForeground(1) eroder.SetBackground(0) eroder.SetNeighborTo8() eroder.Update() eroderImage.DeepCopy(eroder.GetOutput()) # # now save only islands bigger than a specified size # # note that island operation happens in unsigned long space # but the slicer editor works in Short castIn = vtk.vtkImageCast() castIn.SetInputConnection(eroder.GetInputConnection(0, 0)) castIn.SetOutputScalarTypeToUnsignedLong() # now identify the islands in the inverted volume # and find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() islandMath.SetInputConnection(castIn.GetOutputPort()) islandMath.SetFullyConnected(self.fullyConnected) islandMath.SetMinimumSize(self.minimumSize) # note that island operation happens in unsigned long space # but the slicer editor works in Short castOut = vtk.vtkImageCast() castOut.SetInputConnection(islandMath.GetOutputPort()) castOut.SetOutputScalarTypeToShort() castOut.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount print("%d islands created (%d ignored)" % (islandCount, ignoredIslands)) # # now map everything back to 0 and 1 # thresh = vtk.vtkImageThreshold() thresh.SetInputConnection(castOut.GetOutputPort()) thresh.ThresholdByUpper(1) thresh.SetInValue(1) thresh.SetOutValue(0) thresh.Update() # # now, dilate back (erode background) iterations_plus_one number of times # dilater = slicer.vtkImageErode() dilaterImage = vtk.vtkImageData() dilaterImage.DeepCopy(thresh.GetOutput()) dilater.SetInputData(dilaterImage) for iteration in range(1 + iterations): dilater.SetForeground(0) dilater.SetBackground(1) dilater.SetNeighborTo8() dilater.Update() dilaterImage.DeepCopy(dilater.GetOutput()) # # only keep pixels in both original and dilated result # logic = vtk.vtkImageLogic() logic.SetInputConnection(0, dilater.GetInputConnection(0, 0)) logic.SetInputConnection(1, binThresh.GetOutputPort()) #if foregroundLabel == 0: # logic.SetOperationToNand() #else: logic.SetOperationToAnd() logic.SetOutputTrueValue(1) logic.Update() # # convert from binary mask to 1->foregroundLabel, 0->backgroundLabel # unbinThresh = vtk.vtkImageThreshold() unbinThresh.SetInputConnection(logic.GetOutputPort()) unbinThresh.ThresholdBetween(1, 1) unbinThresh.SetInValue(foregroundLabel) unbinThresh.SetOutValue(backgroundLabel) unbinThresh.Update() image.DeepCopy(unbinThresh.GetOutput())
def removeIslandsConnectivity(self): # # change the label values based on the parameter node # if not self.sliceLogic: self.sliceLogic = self.editUtil.getSliceLogic() parameterNode = self.editUtil.getParameterNode() minimumSize = int( parameterNode.GetParameter("IslandEffect,minimumSize")) fullyConnected = bool( parameterNode.GetParameter("IslandEffect,fullyConnected")) label = self.editUtil.getLabel() # first, create an inverse binary version of the image # so that islands inside segemented object will be detected, along # with a big island of the background preThresh = vtk.vtkImageThreshold() preThresh.SetInValue(0) preThresh.SetOutValue(1) preThresh.ReplaceInOn() preThresh.ReplaceOutOn() preThresh.ThresholdBetween(label, label) preThresh.SetInputData(self.getScopedLabelInput()) preThresh.SetOutputScalarTypeToUnsignedLong() # now identify the islands in the inverted volume # and find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() islandMath.SetInputConnection(preThresh.GetOutputPort()) islandMath.SetFullyConnected(fullyConnected) islandMath.SetMinimumSize(minimumSize) # TODO: $this setProgressFilter $islandMath "Calculating Islands..." islandMath.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount print("%d islands created (%d ignored)" % (islandCount, ignoredIslands)) if islandCount == 0: return bgPixel = self.findNonZeroBorderPixel(islandMath.GetOutput()) # now rethreshold so that everything which is not background becomes the label postThresh = vtk.vtkImageThreshold() postThresh.SetInValue(0) postThresh.SetOutValue(label) postThresh.ReplaceInOn() postThresh.ReplaceOutOn() postThresh.ThresholdBetween(bgPixel, bgPixel) postThresh.SetOutputScalarTypeToShort() postThresh.SetInputConnection(islandMath.GetOutputPort()) postThresh.SetOutput(self.getScopedLabelOutput()) # TODO $this setProgressFilter $postThresh "Applying to Label Map..." postThresh.Update() self.applyScopedLabel() postThresh.SetOutput(None) if False: # some code for debugging - leave it in layerLogic = self.sliceLogic.GetLabelLayer() labelNode = layerLogic.GetVolumeNode() volumesLogic = slicer.modules.volumes.logic() thresh1 = volumesLogic.CloneVolume(slicer.mrmlScene, labelNode, 'thres1') islands = volumesLogic.CloneVolume(slicer.mrmlScene, labelNode, 'islands') thresh2 = volumesLogic.CloneVolume(slicer.mrmlScene, labelNode, 'thres2') cast = vtk.vtkImageCast() cast.SetOutputScalarTypeToShort() cast.SetInputConnection(preThresh.GetOutputPort()) thresh1.SetImageDataConnection(cast.GetOutputPort()) cast2 = vtk.vtkImageCast() cast2.SetOutputScalarTypeToShort() cast2.SetInputConnection(islandMath.GetOutputPort()) islands.SetImageDataConnection(cast2.GetOutputPort()) thresh2.SetImageDataConnection(postThresh.GetOutputPort())
def removeIslandsMorphologyDecruft(self, image, foregroundLabel, backgroundLabel, iterations=1): # # make binary mask foregroundLabel->1, backgroundLabel->0 # binThresh = vtk.vtkImageThreshold() if vtk.VTK_MAJOR_VERSION <= 5: binThresh.SetInput(image) else: binThresh.SetInputData(image) binThresh.ThresholdBetween(foregroundLabel, foregroundLabel) binThresh.SetInValue(1) binThresh.SetOutValue(0) binThresh.Update() # # first, erode iterations number of times # eroder = slicer.vtkImageErode() eroderImage = vtk.vtkImageData() eroderImage.DeepCopy(binThresh.GetOutput()) if vtk.VTK_MAJOR_VERSION <= 5: eroder.SetInput(eroderImage) else: eroder.SetInputData(eroderImage) for iteration in range(iterations): eroder.SetForeground(1) eroder.SetBackground(0) eroder.SetNeighborTo8() eroder.Update() eroderImage.DeepCopy(eroder.GetOutput()) # # now save only islands bigger than a specified size # # note that island operation happens in unsigned long space # but the slicer editor works in Short castIn = vtk.vtkImageCast() if vtk.VTK_MAJOR_VERSION <= 5: castIn.SetInput(eroderImage) else: castIn.SetInputConnection(eroder.GetInputConnection(0, 0)) castIn.SetOutputScalarTypeToUnsignedLong() # now identify the islands in the inverted volume # and find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() if vtk.VTK_MAJOR_VERSION <= 5: islandMath.SetInput(castIn.GetOutput()) else: islandMath.SetInputConnection(castIn.GetOutputPort()) islandMath.SetFullyConnected(self.fullyConnected) islandMath.SetMinimumSize(self.minimumSize) # note that island operation happens in unsigned long space # but the slicer editor works in Short castOut = vtk.vtkImageCast() if vtk.VTK_MAJOR_VERSION <= 5: castOut.SetInput(islandMath.GetOutput()) else: castOut.SetInputConnection(islandMath.GetOutputPort()) castOut.SetOutputScalarTypeToShort() castOut.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount print("%d islands created (%d ignored)" % (islandCount, ignoredIslands)) # # now map everything back to 0 and 1 # thresh = vtk.vtkImageThreshold() if vtk.VTK_MAJOR_VERSION <= 5: thresh.SetInput(castOut.GetOutput()) else: thresh.SetInputConnection(castOut.GetOutputPort()) thresh.ThresholdByUpper(1) thresh.SetInValue(1) thresh.SetOutValue(0) thresh.Update() # # now, dilate back (erode background) iterations_plus_one number of times # dilater = slicer.vtkImageErode() dilaterImage = vtk.vtkImageData() dilaterImage.DeepCopy(thresh.GetOutput()) if vtk.VTK_MAJOR_VERSION <= 5: dilater.SetInput(dilaterImage) else: dilater.SetInputData(dilaterImage) for iteration in range(1 + iterations): dilater.SetForeground(0) dilater.SetBackground(1) dilater.SetNeighborTo8() dilater.Update() dilaterImage.DeepCopy(dilater.GetOutput()) # # only keep pixels in both original and dilated result # logic = vtk.vtkImageLogic() if vtk.VTK_MAJOR_VERSION <= 5: logic.SetInput1(dilaterImage) logic.SetInput2(binThresh.GetOutput()) else: logic.SetInputConnection(0, dilater.GetInputConnection(0, 0)) logic.SetInputConnection(1, binThresh.GetOutputPort()) # if foregroundLabel == 0: # logic.SetOperationToNand() # else: logic.SetOperationToAnd() logic.SetOutputTrueValue(1) logic.Update() # # convert from binary mask to 1->foregroundLabel, 0->backgroundLabel # unbinThresh = vtk.vtkImageThreshold() if vtk.VTK_MAJOR_VERSION <= 5: unbinThresh.SetInput(logic.GetOutput()) else: unbinThresh.SetInputConnection(logic.GetOutputPort()) unbinThresh.ThresholdBetween(1, 1) unbinThresh.SetInValue(foregroundLabel) unbinThresh.SetOutValue(backgroundLabel) unbinThresh.Update() image.DeepCopy(unbinThresh.GetOutput())
def apply(self, ijkPoints): kernelSizePixel = self.getKernelSizePixel() if kernelSizePixel[0]<=0 and kernelSizePixel[1]<=0 and kernelSizePixel[2]<=0: return qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor) # Get parameter set node parameterSetNode = self.scriptedEffect.parameterSetNode() # Get parameters minimumThreshold = self.scriptedEffect.doubleParameter("MinimumThreshold") maximumThreshold = self.scriptedEffect.doubleParameter("MaximumThreshold") # Get modifier labelmap modifierLabelmap = self.scriptedEffect.defaultModifierLabelmap() # Get master volume image data masterImageData = self.scriptedEffect.masterVolumeImageData() # Set intensity range oldMasterVolumeIntensityMask = parameterSetNode.GetMasterVolumeIntensityMask() parameterSetNode.MasterVolumeIntensityMaskOn() oldIntensityMaskRange = parameterSetNode.GetMasterVolumeIntensityMaskRange() intensityRange = [265.00, 1009.00] if oldMasterVolumeIntensityMask: intensityRange = [max(oldIntensityMaskRange[0], minimumThreshold), min(oldIntensityMaskRange[1], maximumThreshold)] parameterSetNode.SetMasterVolumeIntensityMaskRange(intensityRange) roiNode = lumbarSeed ##self.roiSelector.currentNode() clippedMasterImageData = masterImageData if roiNode is not None: worldToImageMatrix = vtk.vtkMatrix4x4() masterImageData.GetWorldToImageMatrix(worldToImageMatrix) bounds = [0,0,0,0,0,0] roiNode.GetRASBounds(bounds) corner1RAS = [bounds[0], bounds[2], bounds[4], 1] corner1IJK = [0, 0, 0, 0] worldToImageMatrix.MultiplyPoint(corner1RAS, corner1IJK) corner2RAS = [bounds[1], bounds[3], bounds[5], 1] corner2IJK = [0, 0, 0, 0] worldToImageMatrix.MultiplyPoint(corner2RAS, corner2IJK) extent = [0, -1, 0, -1, 0, -1] for i in range(3): lowerPoint = min(corner1IJK[i], corner2IJK[i]) upperPoint = max(corner1IJK[i], corner2IJK[i]) extent[2*i] = int(math.floor(lowerPoint)) extent[2*i+1] = int(math.ceil(upperPoint)) imageToWorldMatrix = vtk.vtkMatrix4x4() masterImageData.GetImageToWorldMatrix(imageToWorldMatrix) clippedMasterImageData = slicer.vtkOrientedImageData() self.padder = vtk.vtkImageConstantPad() self.padder.SetInputData(masterImageData) self.padder.SetOutputWholeExtent(extent) self.padder.Update() clippedMasterImageData.ShallowCopy(self.padder.GetOutput()) clippedMasterImageData.SetImageToWorldMatrix(imageToWorldMatrix) # Pipeline self.thresh = vtk.vtkImageThreshold() self.thresh.SetInValue(LABEL_VALUE) self.thresh.SetOutValue(BACKGROUND_VALUE) self.thresh.SetInputData(clippedMasterImageData) self.thresh.ThresholdBetween(minimumThreshold, maximumThreshold) self.thresh.SetOutputScalarTypeToUnsignedChar() self.thresh.Update() self.erode = vtk.vtkImageDilateErode3D() self.erode.SetInputConnection(self.thresh.GetOutputPort()) self.erode.SetDilateValue(BACKGROUND_VALUE) self.erode.SetErodeValue(LABEL_VALUE) self.erode.SetKernelSize( kernelSizePixel[0], kernelSizePixel[1], kernelSizePixel[2]) self.erodeCast = vtk.vtkImageCast() self.erodeCast.SetInputConnection(self.erode.GetOutputPort()) self.erodeCast.SetOutputScalarTypeToUnsignedInt() self.erodeCast.Update() # Remove small islands self.islandMath = vtkITK.vtkITKIslandMath() self.islandMath.SetInputConnection(self.erodeCast.GetOutputPort()) self.islandMath.SetFullyConnected(False) self.islandMath.SetMinimumSize(125) # remove regions smaller than 5x5x5 voxels self.islandThreshold = vtk.vtkImageThreshold() self.islandThreshold.SetInputConnection(self.islandMath.GetOutputPort()) self.islandThreshold.ThresholdByLower(BACKGROUND_VALUE) self.islandThreshold.SetInValue(BACKGROUND_VALUE) self.islandThreshold.SetOutValue(LABEL_VALUE) self.islandThreshold.SetOutputScalarTypeToUnsignedChar() self.islandThreshold.Update() # Points may be outside the region after it is eroded. # Snap the points to LABEL_VALUE voxels, snappedIJKPoints = self.snapIJKPointsToLabel(ijkPoints, self.islandThreshold.GetOutput()) if snappedIJKPoints.GetNumberOfPoints() == 0: qt.QApplication.restoreOverrideCursor() return # Convert points to real data coordinates. Required for vtkImageThresholdConnectivity. seedPoints = vtk.vtkPoints() origin = masterImageData.GetOrigin() spacing = masterImageData.GetSpacing() for i in range(snappedIJKPoints.GetNumberOfPoints()): ijkPoint = snappedIJKPoints.GetPoint(i) seedPoints.InsertNextPoint( origin[0]+ijkPoint[0]*spacing[0], origin[1]+ijkPoint[1]*spacing[1], origin[2]+ijkPoint[2]*spacing[2]) segmentationAlgorithm = self.scriptedEffect.parameter(SEGMENTATION_ALGORITHM_PARAMETER_NAME) if segmentationAlgorithm == SEGMENTATION_ALGORITHM_MASKING: self.runMasking(seedPoints, self.islandThreshold.GetOutput(), modifierLabelmap) else: self.floodFillingFilterIsland = vtk.vtkImageThresholdConnectivity() self.floodFillingFilterIsland.SetInputConnection(self.islandThreshold.GetOutputPort()) self.floodFillingFilterIsland.SetInValue(SELECTED_ISLAND_VALUE) self.floodFillingFilterIsland.ReplaceInOn() self.floodFillingFilterIsland.ReplaceOutOff() self.floodFillingFilterIsland.ThresholdBetween(265.00, 1009.00) self.floodFillingFilterIsland.SetSeedPoints(seedPoints) self.floodFillingFilterIsland.Update() self.maskCast = vtk.vtkImageCast() self.maskCast.SetInputData(self.thresh.GetOutput()) self.maskCast.SetOutputScalarTypeToUnsignedChar() self.maskCast.Update() self.imageMask = vtk.vtkImageMask() self.imageMask.SetInputConnection(self.floodFillingFilterIsland.GetOutputPort()) self.imageMask.SetMaskedOutputValue(OUTSIDE_THRESHOLD_VALUE) self.imageMask.SetMaskInputData(self.maskCast.GetOutput()) self.imageMask.Update() imageMaskOutput = slicer.vtkOrientedImageData() imageMaskOutput.ShallowCopy(self.imageMask.GetOutput()) imageMaskOutput.CopyDirections(clippedMasterImageData) imageToWorldMatrix = vtk.vtkMatrix4x4() imageMaskOutput.GetImageToWorldMatrix(imageToWorldMatrix) segmentOutputLabelmap = slicer.vtkOrientedImageData() if segmentationAlgorithm == SEGMENTATION_ALGORITHM_GROWCUT: self.runGrowCut(clippedMasterImageData, imageMaskOutput, segmentOutputLabelmap) elif segmentationAlgorithm == SEGMENTATION_ALGORITHM_WATERSHED: self.runWatershed(clippedMasterImageData, imageMaskOutput, segmentOutputLabelmap) else: logging.error("Unknown segmentation algorithm: \"" + segmentationAlgorithm + "\"") segmentOutputLabelmap.SetImageToWorldMatrix(imageToWorldMatrix) self.selectedSegmentThreshold = vtk.vtkImageThreshold() self.selectedSegmentThreshold.SetInputData(segmentOutputLabelmap) self.selectedSegmentThreshold.ThresholdBetween(SELECTED_ISLAND_VALUE, SELECTED_ISLAND_VALUE) self.selectedSegmentThreshold.SetInValue(LABEL_VALUE) self.selectedSegmentThreshold.SetOutValue(BACKGROUND_VALUE) self.selectedSegmentThreshold.SetOutputScalarType(modifierLabelmap.GetScalarType()) self.selectedSegmentThreshold.Update() modifierLabelmap.ShallowCopy(self.selectedSegmentThreshold.GetOutput()) self.scriptedEffect.saveStateForUndo() self.scriptedEffect.modifySelectedSegmentByLabelmap(modifierLabelmap, slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeAdd) parameterSetNode.SetMasterVolumeIntensityMask(oldMasterVolumeIntensityMask) parameterSetNode.SetMasterVolumeIntensityMaskRange(oldIntensityMaskRange) qt.QApplication.restoreOverrideCursor()