Slicer 5.4
Slicer is a multi-platform, free and open source software package for visualization and medical image computing
Loading...
Searching...
No Matches
SegmentEditorGrowFromSeedsEffect.py
Go to the documentation of this file.
1import logging
2import os
3import time
4
5import qt
6import vtk
7
8import slicer
9
10from SegmentEditorEffects import *
11
12
13class SegmentEditorGrowFromSeedsEffect(AbstractScriptedSegmentEditorAutoCompleteEffect):
14 """ AutoCompleteEffect is an effect that can create a full segmentation
15 from a partial segmentation (not all slices are segmented or only
16 part of the target structures are painted).
17 """
18
19 def __init__(self, scriptedEffect):
20 AbstractScriptedSegmentEditorAutoCompleteEffect.__init__(self, scriptedEffect)
21 scriptedEffect.name = 'Grow from seeds'
23 self.clippedMasterImageDataRequired = True # source volume intensities are used by this effect
24 self.clippedMaskImageDataRequired = True # masking is used
25 self.growCutFilter = None
26
27 def clone(self):
28 import qSlicerSegmentationsEditorEffectsPythonQt as effects
29 clonedEffect = effects.qSlicerSegmentEditorScriptedEffect(None)
30 clonedEffect.setPythonSource(__file__.replace('\\', '/'))
31 return clonedEffect
32
33 def icon(self):
34 iconPath = os.path.join(os.path.dirname(__file__), 'Resources/Icons/GrowFromSeeds.png')
35 if os.path.exists(iconPath):
36 return qt.QIcon(iconPath)
37 return qt.QIcon()
38
39 def helpText(self):
40 return """<html>Growing segments to create complete segmentation<br>.
41Location, size, and shape of initial segments and content of source volume are taken into account.
42Final segment boundaries will be placed where source volume brightness changes abruptly. Instructions:<p>
43<ul style="margin: 0">
44<li>Use Paint or other offects to draw seeds in each region that should belong to a separate segment.
45Paint each seed with a different segment. Minimum two segments are required.</li>
46<li>Click <dfn>Initialize</dfn> to compute preview of full segmentation.</li>
47<li>Browse through image slices. If previewed segmentation result is not correct then switch to
48Paint or other effects and add more seeds in the misclassified region. Full segmentation will be
49updated automatically within a few seconds</li>
50<li>Click <dfn>Apply</dfn> to update segmentation with the previewed result.</li>
51</ul><p>
52If segments overlap, segment higher in the segments table will have priority.
53The effect uses <a href="http://interactivemedical.org/imic2014/CameraReadyPapers/Paper%204/IMIC_ID4_FastGrowCut.pdf">fast grow-cut method</a>.
54<p></html>"""
55
56 def reset(self):
57 self.growCutFilter = None
58 AbstractScriptedSegmentEditorAutoCompleteEffect.reset(self)
60
62 AbstractScriptedSegmentEditorAutoCompleteEffect.setupOptionsFrame(self)
63
64 # Object scale slider
65 self.seedLocalityFactorSlider = slicer.qMRMLSliderWidget()
66 self.seedLocalityFactorSlider.setMRMLScene(slicer.mrmlScene)
67 self.seedLocalityFactorSlider.minimum = 0
68 self.seedLocalityFactorSlider.maximum = 10
69 self.seedLocalityFactorSlider.value = 0.0
70 self.seedLocalityFactorSlider.decimals = 1
71 self.seedLocalityFactorSlider.singleStep = 0.1
72 self.seedLocalityFactorSlider.pageStep = 1.0
73 self.seedLocalityFactorSlider.setToolTip('Increasing this value makes the effect of seeds more localized,'
74 ' thereby reducing leaks, but requires seed regions to be more evenly distributed in the image.'
75 ' The value is specified as an additional "intensity level difference" per "unit distance."')
76 self.scriptedEffect.addLabeledOptionsWidget("Seed locality:", self.seedLocalityFactorSlider)
78
79 def setMRMLDefaults(self):
80 AbstractScriptedSegmentEditorAutoCompleteEffect.setMRMLDefaults(self)
81 self.scriptedEffect.setParameterDefault("SeedLocalityFactor", 0.0)
82
84 AbstractScriptedSegmentEditorAutoCompleteEffect.updateGUIFromMRML(self)
85 if self.scriptedEffect.parameterDefined("SeedLocalityFactor"):
86 seedLocalityFactor = self.scriptedEffect.doubleParameter("SeedLocalityFactor")
87 else:
88 seedLocalityFactor = 0.0
89 wasBlocked = self.seedLocalityFactorSlider.blockSignals(True)
90 self.seedLocalityFactorSlider.value = abs(seedLocalityFactor)
91 self.seedLocalityFactorSlider.blockSignals(wasBlocked)
92
94 AbstractScriptedSegmentEditorAutoCompleteEffect.updateMRMLFromGUI(self)
95 self.scriptedEffect.setParameter("SeedLocalityFactor", self.seedLocalityFactorSlider.value)
96
99
100 # Trigger preview update
101 if self.getPreviewNode():
102 self.delayedAutoUpdateTimer.start()
103
104 def computePreviewLabelmap(self, mergedImage, outputLabelmap):
105 import vtkITK
106
107 if not self.growCutFilter:
108 self.growCutFilter = vtkITK.vtkITKGrowCut()
109 self.growCutFilter.SetIntensityVolume(self.clippedMasterImageData)
110 self.growCutFilter.SetMaskVolume(self.clippedMaskImageData)
111 maskExtent = self.clippedMaskImageData.GetExtent() if self.clippedMaskImageData else None
112 if maskExtent is not None and maskExtent[0] <= maskExtent[1] and maskExtent[2] <= maskExtent[3] and maskExtent[4] <= maskExtent[5]:
113 # Mask is used.
114 # Grow the extent more, as background segment does not surround region of interest.
116 else:
117 # No masking is used.
118 # Background segment is expected to surround region of interest, so narrower margin is enough.
119 self.extentGrowthRatio = 0.20
120
121 if self.scriptedEffect.parameterDefined("SeedLocalityFactor"):
122 seedLocalityFactor = self.scriptedEffect.doubleParameter("SeedLocalityFactor")
123 else:
124 seedLocalityFactor = 0.0
125 self.growCutFilter.SetDistancePenalty(seedLocalityFactor)
126 self.growCutFilter.SetSeedLabelVolume(mergedImage)
127 startTime = time.time()
128 self.growCutFilter.Update()
129 logging.info('Grow-cut operation on volume of {}x{}x{} voxels was completed in {:3.1f} seconds.'.format(
130 self.clippedMasterImageData.GetDimensions()[0],
131 self.clippedMasterImageData.GetDimensions()[1],
132 self.clippedMasterImageData.GetDimensions()[2],
133 time.time() - startTime))
134
135 outputLabelmap.DeepCopy(self.growCutFilter.GetOutput())
136 imageToWorld = vtk.vtkMatrix4x4()
137 mergedImage.GetImageToWorldMatrix(imageToWorld)
138 outputLabelmap.SetImageToWorldMatrix(imageToWorld)