diff --git a/CMakeLists.txt b/CMakeLists.txt index 15d9532..7ea990c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,12 +4,12 @@ project(CleverSeg) #----------------------------------------------------------------------------- # Extension meta-information -set(EXTENSION_HOMEPAGE "http://slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/CleverSeg") +set(EXTENSION_HOMEPAGE "https://github.com/lassoan/SlicerCleverSegmentation#cleversegmentation") set(EXTENSION_CATEGORY "Segmentation") -set(EXTENSION_CONTRIBUTORS "Jonathan Ramos (University of São Paulo)") -set(EXTENSION_DESCRIPTION "This is an example of a simple extension") -set(EXTENSION_ICONURL "http://www.example.com/Slicer/Extensions/CleverSeg.png") -set(EXTENSION_SCREENSHOTURLS "http://www.example.com/Slicer/Extensions/CleverSeg/Screenshots/1.png") +set(EXTENSION_CONTRIBUTORS "Jonathan Ramos (ICMC, University of São Paulo - USP)") +set(EXTENSION_DESCRIPTION "This is the implementation of the CleverSeg method that supports multi-label segmentations") +set(EXTENSION_ICONURL "https://raw.githubusercontent.com/lassoan/SlicerCleverSegmentation/master/CleverSegmentation/Resources/Icons/CleverSegmentation.png") +set(EXTENSION_SCREENSHOTURLS "https://user-images.githubusercontent.com/3834596/66679138-d7dc1700-ec43-11e9-8c36-51976a1121d3.png" "https://user-images.githubusercontent.com/3834596/66679174-f215f500-ec43-11e9-84f1-85f8b5c4d568.png") set(EXTENSION_DEPENDS "NA") # Specified as a space separated string, a list or 'NA' if any #----------------------------------------------------------------------------- diff --git a/CleverSegmentation/Resources/Icons/CleverSegmentation.png b/CleverSegmentation/Resources/Icons/CleverSegmentation.png new file mode 100644 index 0000000..7a872f8 Binary files /dev/null and b/CleverSegmentation/Resources/Icons/CleverSegmentation.png differ diff --git a/CleverSegmentation/SegmentEditorCleverSegmentationLib/SegmentEditorEffect.py b/CleverSegmentation/SegmentEditorCleverSegmentationLib/SegmentEditorEffect.py index 61b26f2..69ffb7e 100644 --- a/CleverSegmentation/SegmentEditorCleverSegmentationLib/SegmentEditorEffect.py +++ b/CleverSegmentation/SegmentEditorCleverSegmentationLib/SegmentEditorEffect.py @@ -1,79 +1,82 @@ -import os -import vtk, qt, ctk, slicer -import logging -from SegmentEditorEffects import * - -class SegmentEditorEffect(AbstractScriptedSegmentEditorAutoCompleteEffect): - """ AutoCompleteEffect is an effect that can create a full segmentation - from a partial segmentation (not all slices are segmented or only - part of the target structures are painted). - """ - - def __init__(self, scriptedEffect): - AbstractScriptedSegmentEditorAutoCompleteEffect.__init__(self, scriptedEffect) - scriptedEffect.name = 'CleverSegmentation' - self.minimumNumberOfSegments = 2 - self.clippedMasterImageDataRequired = True # master volume intensities are used by this effect - self.clippedMaskImageDataRequired = True # masking is used - self.cleverSegFilter = None - - def clone(self): - import qSlicerSegmentationsEditorEffectsPythonQt as effects - clonedEffect = effects.qSlicerSegmentEditorScriptedEffect(None) - clonedEffect.setPythonSource(__file__.replace('\\','/')) - return clonedEffect - - def icon(self): - iconPath = os.path.join(os.path.dirname(__file__), 'SegmentEditorEffect.png') - if os.path.exists(iconPath): - return qt.QIcon(iconPath) - return qt.QIcon() - - def helpText(self): - return """Growing segments to create complete segmentation
. -Location, size, and shape of initial segments and content of master volume are taken into account. -Final segment boundaries will be placed where master volume brightness changes abruptly. Instructions:

-

-If segments overlap, segment higher in the segments table will have priority. -The effect uses fast clever-segmentation method. -

""" - - - def reset(self): - self.cleverSegFilter = None - AbstractScriptedSegmentEditorAutoCompleteEffect.reset(self) - self.updateGUIFromMRML() - - def computePreviewLabelmap(self, mergedImage, outputLabelmap): - import vtkCleverSegModuleLogicPython as vtkCleverSeg - - - - if not self.cleverSegFilter: - self.cleverSegFilter = vtkCleverSeg.vtkCleverSeg() - self.cleverSegFilter.SetIntensityVolume(self.clippedMasterImageData) - self.cleverSegFilter.SetMaskVolume(self.clippedMaskImageData) - maskExtent = self.clippedMaskImageData.GetExtent() if self.clippedMaskImageData else None - if maskExtent is not None and maskExtent[0] <= maskExtent[1] and maskExtent[2] <= maskExtent[3] and maskExtent[4] <= maskExtent[5]: - # Mask is used. - # Grow the extent more, as background segment does not surround region of interest. - self.extentGrowthRatio = 0.50 - else: - # No masking is used. - # Background segment is expected to surround region of interest, so narrower margin is enough. - self.extentGrowthRatio = 0.20 - - self.extentGrowthRatio - - self.cleverSegFilter.SetSeedLabelVolume(mergedImage) - self.cleverSegFilter.Update() - - outputLabelmap.DeepCopy( self.cleverSegFilter.GetOutput() ) +import os +import vtk, qt, ctk, slicer +import logging +from SegmentEditorEffects import * + +class SegmentEditorEffect(AbstractScriptedSegmentEditorAutoCompleteEffect): + """ AutoCompleteEffect is an effect that can create a full segmentation + from a partial segmentation (not all slices are segmented or only + part of the target structures are painted). + """ + + def __init__(self, scriptedEffect): + AbstractScriptedSegmentEditorAutoCompleteEffect.__init__(self, scriptedEffect) + scriptedEffect.name = 'CleverSegmentation' + self.minimumNumberOfSegments = 2 + self.clippedMasterImageDataRequired = True # master volume intensities are used by this effect + self.clippedMaskImageDataRequired = True # masking is used + self.cleverSegFilter = None + + def clone(self): + import qSlicerSegmentationsEditorEffectsPythonQt as effects + clonedEffect = effects.qSlicerSegmentEditorScriptedEffect(None) + clonedEffect.setPythonSource(__file__.replace('\\','/')) + return clonedEffect + + def icon(self): + iconPath = os.path.join(os.path.dirname(__file__), 'SegmentEditorEffect.png') + if os.path.exists(iconPath): + return qt.QIcon(iconPath) + return qt.QIcon() + + def helpText(self): + return """Growing segments to create complete segmentation
. +Location, size, and shape of initial segments and content of master volume are taken into account. +Final segment boundaries will be placed where master volume brightness changes abruptly. Instructions:

+

+If segments overlap, segment higher in the segments table will have priority. +The effect uses fast clever-segmentation method. +

""" + + + def reset(self): + self.cleverSegFilter = None + AbstractScriptedSegmentEditorAutoCompleteEffect.reset(self) + self.updateGUIFromMRML() + + def computePreviewLabelmap(self, mergedImage, outputLabelmap): + import vtkCleverSegModuleLogicPython as vtkCleverSeg + + + + if not self.cleverSegFilter: + self.cleverSegFilter = vtkCleverSeg.vtkCleverSeg() + self.cleverSegFilter.SetIntensityVolume(self.clippedMasterImageData) + self.cleverSegFilter.SetMaskVolume(self.clippedMaskImageData) + maskExtent = self.clippedMaskImageData.GetExtent() if self.clippedMaskImageData else None + if maskExtent is not None and maskExtent[0] <= maskExtent[1] and maskExtent[2] <= maskExtent[3] and maskExtent[4] <= maskExtent[5]: + # Mask is used. + # Grow the extent more, as background segment does not surround region of interest. + self.extentGrowthRatio = 0.50 + else: + # No masking is used. + # Background segment is expected to surround region of interest, so narrower margin is enough. + self.extentGrowthRatio = 0.20 + + self.extentGrowthRatio + + self.cleverSegFilter.SetSeedLabelVolume(mergedImage) + self.cleverSegFilter.Update() + + outputLabelmap.DeepCopy( self.cleverSegFilter.GetOutput() ) + imageToWorld = vtk.vtkMatrix4x4() + mergedImage.GetImageToWorldMatrix(imageToWorld) + outputLabelmap.SetImageToWorldMatrix(imageToWorld)