2 import vtk, qt, ctk, slicer, logging
3 from AbstractScriptedSegmentEditorEffect
import *
5 __all__ = [
'AbstractScriptedSegmentEditorAutoCompleteEffect']
15 """ AutoCompleteEffect is an effect that can create a full segmentation 16 from a partial segmentation (not all slices are segmented or only 17 part of the target structures are painted). 23 scriptedEffect.perSegment =
False 24 AbstractScriptedSegmentEditorEffect.__init__(self, scriptedEffect)
41 autoUpdateDelaySec = 1.0
51 super(SegmentEditorAutoCompleteEffect,self).
__del__()
57 if labelmapOrientedImageData
is None:
60 extent = labelmapOrientedImageData.GetExtent()
61 if extent[0] > extent[1]
or extent[2] > extent[3]
or extent[4] > extent[5]:
63 numberOfFilledCorners = 0
67 if labelmapOrientedImageData.GetScalarComponentAsFloat(extent[i],extent[j],extent[k],0) > 0:
68 numberOfFilledCorners += 1
69 if numberOfFilledCorners > 4:
75 self.
autoUpdateCheckBox.setToolTip(
"Auto-update results preview when input segments change.")
80 self.
previewButton.objectName = self.__class__.__name__ +
'Preview' 81 self.
previewButton.setToolTip(
"Preview complete segmentation")
84 qSize = qt.QSizePolicy()
85 qSize.setHorizontalPolicy(qt.QSizePolicy.Expanding)
88 previewFrame = qt.QHBoxLayout()
91 self.
scriptedEffect.addLabeledOptionsWidget(
"Preview:", previewFrame)
106 displayFrame = qt.QHBoxLayout()
107 displayFrame.addWidget(qt.QLabel(
"inputs"))
109 displayFrame.addWidget(qt.QLabel(
"results"))
111 self.
scriptedEffect.addLabeledOptionsWidget(
"Display:", displayFrame)
114 self.
cancelButton.objectName = self.__class__.__name__ +
'Cancel' 115 self.
cancelButton.setToolTip(
"Clear preview and cancel auto-complete")
118 self.
applyButton.objectName = self.__class__.__name__ +
'Apply' 119 self.
applyButton.setToolTip(
"Replace segments by previewed result")
121 finishFrame = qt.QHBoxLayout()
135 return slicer.util.mainWindow().cursor
145 import vtkSegmentationCorePython
as vtkSegmentationCore
146 segmentationNode = self.
scriptedEffect.parameterSetNode().GetSegmentationNode()
147 segmentation = segmentationNode.GetSegmentation()
152 segment = segmentation.GetSegment(segmentID)
155 logging.debug(
"Segmentation cancelled because an input segment was deleted")
158 segmentLabelmap = segment.GetRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationBinaryLabelmapRepresentationName())
170 logging.debug(
"Segmentation update requested")
176 import vtkSegmentationCorePython
as vtkSegmentationCore
177 segmentation = self.
scriptedEffect.parameterSetNode().GetSegmentationNode().GetSegmentation()
190 if observationEnabled
and segmentation
is not None:
193 vtkSegmentationCore.vtkSegmentation.SegmentAdded,
194 vtkSegmentationCore.vtkSegmentation.SegmentRemoved,
195 vtkSegmentationCore.vtkSegmentation.SegmentModified,
196 vtkSegmentationCore.vtkSegmentation.MasterRepresentationModified ]
197 for eventId
in observedEvents:
201 previewNode = self.
scriptedEffect.parameterSetNode().GetNodeReference(ResultPreviewNodeReferenceRole)
212 self.
applyButton.setEnabled(previewNode
is not None)
231 autoUpdate = qt.Qt.Unchecked
if self.
scriptedEffect.integerParameter(
"AutoUpdate") == 0
else qt.Qt.Checked
237 segmentationNode = self.
scriptedEffect.parameterSetNode().GetSegmentationNode()
247 slicer.util.showStatusMessage(
"Running {0} auto-complete...".format(self.
scriptedEffect.name), 2000)
250 qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor)
253 qt.QApplication.restoreOverrideCursor()
258 previewNode = self.
scriptedEffect.parameterSetNode().GetNodeReference(ResultPreviewNodeReferenceRole)
260 self.
scriptedEffect.parameterSetNode().SetNodeReferenceID(ResultPreviewNodeReferenceRole,
None)
261 slicer.mrmlScene.RemoveNode(previewNode)
262 self.
scriptedEffect.setCommonParameter(
"SegmentationResultPreviewOwnerEffect",
"")
263 segmentationNode = self.
scriptedEffect.parameterSetNode().GetSegmentationNode()
264 segmentationNode.GetDisplayNode().SetOpacity(1.0)
278 import vtkSegmentationCorePython
as vtkSegmentationCore
279 segmentationNode = self.
scriptedEffect.parameterSetNode().GetSegmentationNode()
280 segmentationDisplayNode = segmentationNode.GetDisplayNode()
285 previewContainsClosedSurfaceRepresentation = previewNode.GetSegmentation().ContainsRepresentation(
286 slicer.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())
289 segmentIDs = vtk.vtkStringArray()
290 previewNode.GetSegmentation().GetSegmentIDs(segmentIDs)
291 for index
in xrange(segmentIDs.GetNumberOfValues()):
292 segmentID = segmentIDs.GetValue(index)
293 previewSegment = previewNode.GetSegmentation().GetSegment(segmentID)
294 previewSegmentLabelmap = previewSegment.GetRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationBinaryLabelmapRepresentationName())
295 slicer.vtkSlicerSegmentationsModuleLogic.SetBinaryLabelmapToSegment(previewSegmentLabelmap, segmentationNode, segmentID)
298 segmentationDisplayNode.SetSegmentVisibility(segmentID,
False)
299 previewNode.GetSegmentation().RemoveSegment(segmentID)
301 if previewContainsClosedSurfaceRepresentation:
302 segmentationNode.CreateClosedSurfaceRepresentation()
307 segmentationNode = self.
scriptedEffect.parameterSetNode().GetSegmentationNode()
308 segmentationNode.GetDisplayNode().SetOpacity(1.0-opacity)
311 previewNode.GetDisplayNode().SetOpacity(opacity)
312 previewNode.GetDisplayNode().SetOpacity3D(opacity)
321 return previewNode.GetDisplayNode().GetOpacity()
if previewNode
else 0.6
327 previewNode.CreateClosedSurfaceRepresentation()
329 previewNode.RemoveClosedSurfaceRepresentation()
340 containsClosedSurfaceRepresentation = previewNode.GetSegmentation().ContainsRepresentation(
341 slicer.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())
342 return containsClosedSurfaceRepresentation
346 import vtkSegmentationCorePython
as vtkSegmentationCore
350 segmentationNode = self.
scriptedEffect.parameterSetNode().GetSegmentationNode()
361 logging.error(
"Auto-complete operation skipped: at least {0} visible segments are required".format(self.
minimumNumberOfSegments))
365 commonGeometryString = segmentationNode.GetSegmentation().DetermineCommonLabelmapGeometry(
366 vtkSegmentationCore.vtkSegmentation.EXTENT_UNION_OF_EFFECTIVE_SEGMENTS, self.
selectedSegmentIds)
367 if not commonGeometryString:
368 logging.info(
"Auto-complete operation skipped: all visible segments are empty")
372 masterImageExtent = masterImageData.GetExtent()
377 int(max(3, self.
extentGrowthRatio * (labelsEffectiveExtent[1]-labelsEffectiveExtent[0]))),
378 int(max(3, self.
extentGrowthRatio * (labelsEffectiveExtent[3]-labelsEffectiveExtent[2]))),
379 int(max(3, self.
extentGrowthRatio * (labelsEffectiveExtent[5]-labelsEffectiveExtent[4]))) ]
380 labelsExpandedExtent = [
381 max(masterImageExtent[0], labelsEffectiveExtent[0]-margin[0]),
382 min(masterImageExtent[1], labelsEffectiveExtent[1]+margin[0]),
383 max(masterImageExtent[2], labelsEffectiveExtent[2]-margin[1]),
384 min(masterImageExtent[3], labelsEffectiveExtent[3]+margin[1]),
385 max(masterImageExtent[4], labelsEffectiveExtent[4]-margin[2]),
386 min(masterImageExtent[5], labelsEffectiveExtent[5]+margin[2]) ]
387 print(
"masterImageExtent = "+repr(masterImageExtent))
388 print(
"labelsEffectiveExtent = "+repr(labelsEffectiveExtent))
389 print(
"labelsExpandedExtent = "+repr(labelsExpandedExtent))
393 previewNode = slicer.mrmlScene.AddNewNodeByClass(
"vtkMRMLSegmentationNode")
394 previewNode.CreateDefaultDisplayNodes()
395 previewNode.GetDisplayNode().SetVisibility2DOutline(
False)
396 if segmentationNode.GetParentTransformNode():
397 previewNode.SetAndObserveTransformNodeID(segmentationNode.GetParentTransformNode().GetID())
398 self.
scriptedEffect.parameterSetNode().SetNodeReferenceID(ResultPreviewNodeReferenceRole, previewNode.GetID())
403 previewNode.GetSegmentation().SetConversionParameter(
404 slicer.vtkBinaryLabelmapToClosedSurfaceConversionRule.GetSmoothingFactorParameterName(),
407 inputContainsClosedSurfaceRepresentation = segmentationNode.GetSegmentation().ContainsRepresentation(
408 slicer.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())
414 masterImageClipper = vtk.vtkImageConstantPad()
415 masterImageClipper.SetInputData(masterImageData)
417 masterImageClipper.Update()
424 intensityBasedMasking = self.
scriptedEffect.parameterSetNode().GetMasterVolumeIntensityMask()
431 self.
scriptedEffect.parameterSetNode().GetMasterVolumeIntensityMaskRange()
if intensityBasedMasking
else None)
433 logging.error(
"Failed to create edit mask")
436 previewNode.SetName(segmentationNode.GetName()+
" preview")
438 mergedImage = vtkSegmentationCore.vtkOrientedImageData()
439 segmentationNode.GenerateMergedLabelmapForAllSegments(mergedImage,
442 outputLabelmap = vtkSegmentationCore.vtkOrientedImageData()
444 self.computePreviewLabelmap(mergedImage, outputLabelmap)
449 segment = segmentationNode.GetSegmentation().GetSegment(segmentID)
453 thresh = vtk.vtkImageThreshold()
455 thresh.ReplaceOutOn()
457 thresh.SetOutValue(0)
458 labelValue = index + 1
459 thresh.ThresholdBetween(labelValue, labelValue);
460 thresh.SetOutputScalarType(vtk.VTK_UNSIGNED_CHAR)
461 thresh.SetInputData(outputLabelmap)
465 newSegmentLabelmap = vtkSegmentationCore.vtkOrientedImageData()
466 newSegmentLabelmap.ShallowCopy(thresh.GetOutput())
467 newSegmentLabelmap.CopyDirections(mergedImage)
468 newSegment = previewNode.GetSegmentation().GetSegment(segmentID)
470 newSegment = vtkSegmentationCore.vtkSegment()
471 newSegment.SetName(segment.GetName())
472 color = segmentationNode.GetSegmentation().GetSegment(segmentID).GetColor()
473 newSegment.SetColor(color)
474 previewNode.GetSegmentation().AddSegment(newSegment, segmentID)
475 slicer.vtkSlicerSegmentationsModuleLogic.SetBinaryLabelmapToSegment(newSegmentLabelmap, previewNode, segmentID)
478 previewNode.GetDisplayNode().SetSegmentVisibility3D(segmentID,
not self.
isBackgroundLabelmap(newSegmentLabelmap))
482 ResultPreviewNodeReferenceRole =
"SegmentationResultPreview"
clippedMaskImageDataRequired
def getPreviewShow3D(self)
def updateGUIFromMRML(self)
segmentationNodeObserverTags
def getPreviewOpacity(self)
def updateMRMLFromGUI(self)
def __del__(self, scriptedEffect)
def setMRMLDefaults(self)
selectedSegmentModifiedTimes
def observeSegmentation(self, observationEnabled)
def __init__(self, scriptedEffect)
mergedLabelmapGeometryImage
def setupOptionsFrame(self)
clippedMasterImageDataRequired
def createCursor(self, widget)
def isBackgroundLabelmap(labelmapOrientedImageData)
def setPreviewShow3D(self, show)
def setPreviewOpacity(self, opacity)
def onSegmentationModified(self, caller, event)