149 self.
thresholdSliderLabel.setToolTip(
"Set the range of the background values that should be labeled.")
163 " Threshold above/below: sets the range from the computed value to maximum/minimum."
164 " Set as lower/upper value: only modifies one side of the threshold range.")
188 +
" Useful for iterating through all available methods.")
193 +
" Useful for iterating through all available methods.")
199 qSize = qt.QSizePolicy()
200 qSize.setHorizontalPolicy(qt.QSizePolicy.Expanding)
203 autoThresholdFrame = qt.QGridLayout()
210 autoThresholdGroupBox = ctk.ctkCollapsibleGroupBox()
211 autoThresholdGroupBox.setTitle(
"Automatic threshold")
212 autoThresholdGroupBox.setLayout(autoThresholdFrame)
213 autoThresholdGroupBox.collapsed =
True
214 self.scriptedEffect.addOptionsWidget(autoThresholdGroupBox)
216 histogramFrame = qt.QVBoxLayout()
218 histogramBrushFrame = qt.QHBoxLayout()
219 histogramFrame.addLayout(histogramBrushFrame)
255 histogramBrushFrame.addStretch()
304 histogramItemFrame = qt.QHBoxLayout()
305 histogramFrame.addLayout(histogramItemFrame)
310 lowerGroupBox = qt.QGroupBox(
"Lower")
311 lowerHistogramLayout = qt.QHBoxLayout()
312 lowerHistogramLayout.setContentsMargins(0, 3, 0, 3)
313 lowerGroupBox.setLayout(lowerHistogramLayout)
314 histogramItemFrame.addWidget(lowerGroupBox)
343 upperGroupBox = qt.QGroupBox(
"Upper")
344 upperHistogramLayout = qt.QHBoxLayout()
345 upperHistogramLayout.setContentsMargins(0, 3, 0, 3)
346 upperGroupBox.setLayout(upperHistogramLayout)
347 histogramItemFrame.addWidget(upperGroupBox)
373 histogramGroupBox = ctk.ctkCollapsibleGroupBox()
374 histogramGroupBox.setTitle(
"Local histogram")
375 histogramGroupBox.setLayout(histogramFrame)
376 histogramGroupBox.collapsed =
True
377 self.scriptedEffect.addOptionsWidget(histogramGroupBox)
380 self.
useForPaintButton.setToolTip(
"Use specified intensity range for masking and switch to Paint effect.")
384 self.
applyButton.objectName = self.__class__.__name__ +
'Apply'
385 self.
applyButton.setToolTip(
"Fill selected segment in regions that are in the specified intensity range.")
386 self.scriptedEffect.addOptionsWidget(self.
applyButton)
423 self.
thresholdSlider.setMinimumValue(self.scriptedEffect.doubleParameter(
"MinimumThreshold"))
424 self.
thresholdSlider.setMaximumValue(self.scriptedEffect.doubleParameter(
"MaximumThreshold"))
437 histogramBrushType = self.scriptedEffect.parameter(HISTOGRAM_BRUSH_TYPE_PARAMETER_NAME)
438 self.
boxROIButton.checked = (histogramBrushType == HISTOGRAM_BRUSH_TYPE_BOX)
439 self.
circleROIButton.checked = (histogramBrushType == HISTOGRAM_BRUSH_TYPE_CIRCLE)
440 self.
drawROIButton.checked = (histogramBrushType == HISTOGRAM_BRUSH_TYPE_DRAW)
441 self.
lineROIButton.checked = (histogramBrushType == HISTOGRAM_BRUSH_TYPE_LINE)
443 histogramSetModeLower = self.scriptedEffect.parameter(HISTOGRAM_SET_LOWER_PARAMETER_NAME)
448 histogramSetModeUpper = self.scriptedEffect.parameter(HISTOGRAM_SET_UPPER_PARAMETER_NAME)
456 with slicer.util.NodeModify(self.scriptedEffect.parameterSetNode()):
457 self.scriptedEffect.setParameter(
"MinimumThreshold", self.
thresholdSlider.minimumValue)
458 self.scriptedEffect.setParameter(
"MaximumThreshold", self.
thresholdSlider.maximumValue)
462 self.scriptedEffect.setParameter(
"AutoThresholdMethod", autoThresholdMethod)
466 self.scriptedEffect.setParameter(
"AutoThresholdMode", autoThresholdMode)
468 histogramParameterChanged =
False
470 histogramBrushType = HISTOGRAM_BRUSH_TYPE_CIRCLE
472 histogramBrushType = HISTOGRAM_BRUSH_TYPE_BOX
474 histogramBrushType = HISTOGRAM_BRUSH_TYPE_CIRCLE
476 histogramBrushType = HISTOGRAM_BRUSH_TYPE_DRAW
478 histogramBrushType = HISTOGRAM_BRUSH_TYPE_LINE
480 if histogramBrushType != self.scriptedEffect.parameter(HISTOGRAM_BRUSH_TYPE_PARAMETER_NAME):
481 self.scriptedEffect.setParameter(HISTOGRAM_BRUSH_TYPE_PARAMETER_NAME, histogramBrushType)
482 histogramParameterChanged =
True
484 histogramSetModeLower = HISTOGRAM_SET_LOWER
486 histogramSetModeLower = HISTOGRAM_SET_MINIMUM
488 histogramSetModeLower = HISTOGRAM_SET_LOWER
490 histogramSetModeLower = HISTOGRAM_SET_AVERAGE
491 if histogramSetModeLower != self.scriptedEffect.parameter(HISTOGRAM_SET_LOWER_PARAMETER_NAME):
492 self.scriptedEffect.setParameter(HISTOGRAM_SET_LOWER_PARAMETER_NAME, histogramSetModeLower)
493 histogramParameterChanged =
True
495 histogramSetModeUpper = HISTOGRAM_SET_UPPER
497 histogramSetModeUpper = HISTOGRAM_SET_AVERAGE
499 histogramSetModeUpper = HISTOGRAM_SET_UPPER
501 histogramSetModeUpper = HISTOGRAM_SET_MAXIMUM
502 if histogramSetModeUpper != self.scriptedEffect.parameter(HISTOGRAM_SET_UPPER_PARAMETER_NAME):
503 self.scriptedEffect.setParameter(HISTOGRAM_SET_UPPER_PARAMETER_NAME, histogramSetModeUpper)
504 histogramParameterChanged =
True
506 if histogramParameterChanged:
543 if autoThresholdMethod == METHOD_HUANG:
545 elif autoThresholdMethod == METHOD_INTERMODES:
547 elif autoThresholdMethod == METHOD_ISO_DATA:
549 elif autoThresholdMethod == METHOD_KITTLER_ILLINGWORTH:
551 elif autoThresholdMethod == METHOD_LI:
553 elif autoThresholdMethod == METHOD_MAXIMUM_ENTROPY:
555 elif autoThresholdMethod == METHOD_MOMENTS:
557 elif autoThresholdMethod == METHOD_OTSU:
559 elif autoThresholdMethod == METHOD_RENYI_ENTROPY:
561 elif autoThresholdMethod == METHOD_SHANBHAG:
563 elif autoThresholdMethod == METHOD_TRIANGLE:
565 elif autoThresholdMethod == METHOD_YEN:
568 logging.error(f
"Unknown AutoThresholdMethod {autoThresholdMethod}")
570 masterImageData = self.scriptedEffect.sourceVolumeImageData()
576 sourceVolumeMin, sourceVolumeMax = masterImageData.GetScalarRange()
578 if autoThresholdMode == MODE_SET_UPPER:
579 self.scriptedEffect.setParameter(
"MaximumThreshold", computedThreshold)
580 elif autoThresholdMode == MODE_SET_LOWER:
581 self.scriptedEffect.setParameter(
"MinimumThreshold", computedThreshold)
582 elif autoThresholdMode == MODE_SET_MIN_UPPER:
583 self.scriptedEffect.setParameter(
"MinimumThreshold", sourceVolumeMin)
584 self.scriptedEffect.setParameter(
"MaximumThreshold", computedThreshold)
585 elif autoThresholdMode == MODE_SET_LOWER_MAX:
586 self.scriptedEffect.setParameter(
"MinimumThreshold", computedThreshold)
587 self.scriptedEffect.setParameter(
"MaximumThreshold", sourceVolumeMax)
589 logging.error(f
"Unknown AutoThresholdMode {autoThresholdMode}")
592 if not self.scriptedEffect.confirmCurrentSegmentVisible():
597 masterImageData = self.scriptedEffect.sourceVolumeImageData()
599 modifierLabelmap = self.scriptedEffect.defaultModifierLabelmap()
600 originalImageToWorldMatrix = vtk.vtkMatrix4x4()
601 modifierLabelmap.GetImageToWorldMatrix(originalImageToWorldMatrix)
603 min = self.scriptedEffect.doubleParameter(
"MinimumThreshold")
604 max = self.scriptedEffect.doubleParameter(
"MaximumThreshold")
606 self.scriptedEffect.saveStateForUndo()
609 thresh = vtk.vtkImageThreshold()
610 thresh.SetInputData(masterImageData)
611 thresh.ThresholdBetween(min, max)
613 thresh.SetOutValue(0)
614 thresh.SetOutputScalarType(modifierLabelmap.GetScalarType())
616 modifierLabelmap.DeepCopy(thresh.GetOutput())
618 logging.error(
'apply: Failed to threshold source volume!')
622 self.scriptedEffect.modifySelectedSegmentByLabelmap(modifierLabelmap, slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeSet)
625 self.scriptedEffect.selectEffect(
"")
666 min = self.scriptedEffect.doubleParameter(
"MinimumThreshold")
667 max = self.scriptedEffect.doubleParameter(
"MaximumThreshold")
670 segmentationNode = self.scriptedEffect.parameterSetNode().GetSegmentationNode()
671 if not segmentationNode:
674 displayNode = segmentationNode.GetDisplayNode()
675 if displayNode
is None:
676 logging.error(
"preview: Invalid segmentation display node!")
677 color = [0.5, 0.5, 0.5]
678 segmentID = self.scriptedEffect.parameterSetNode().GetSelectedSegmentID()
684 r, g, b = segmentationNode.GetSegmentation().GetSegment(segmentID).GetColor()
689 pipeline.lookupTable.SetTableValue(1, r, g, b, opacity)
691 pipeline.thresholdFilter.SetInputConnection(layerLogic.GetReslice().GetOutputPort())
692 pipeline.thresholdFilter.ThresholdBetween(min, max)
693 pipeline.actor.VisibilityOn()
694 sliceWidget.sliceView().scheduleRender()
705 masterImageData = self.scriptedEffect.sourceVolumeImageData()
706 if masterImageData
is None:
710 if viewWidget.className() !=
"qMRMLSliceWidget":
713 anyModifierKeyPressed = callerInteractor.GetShiftKey()
or callerInteractor.GetControlKey()
or callerInteractor.GetAltKey()
716 if eventId == vtk.vtkCommand.LeftButtonPressEvent
and not anyModifierKeyPressed:
722 xy = callerInteractor.GetEventPosition()
723 ras = self.xyToRas(xy, viewWidget)
725 if eventId == vtk.vtkCommand.LeftButtonPressEvent
and not anyModifierKeyPressed:
730 elif eventId == vtk.vtkCommand.LeftButtonReleaseEvent:
734 elif eventId == vtk.vtkCommand.MouseMoveEvent:
778 sourceVolumeNode = self.scriptedEffect.parameterSetNode().GetSourceVolumeNode()
779 sliceLogic = sliceWidget.sliceLogic()
781 backgroundLogic = sliceLogic.GetBackgroundLayer()
782 backgroundVolumeNode = backgroundLogic.GetVolumeNode()
783 if sourceVolumeNode == backgroundVolumeNode:
784 return backgroundLogic
786 foregroundLogic = sliceLogic.GetForegroundLayer()
787 foregroundVolumeNode = foregroundLogic.GetVolumeNode()
788 if sourceVolumeNode == foregroundVolumeNode:
789 return foregroundLogic
791 logging.warning(
"Source volume is not set as either the foreground or background")
793 foregroundOpacity = 0.0
794 if foregroundVolumeNode:
795 compositeNode = sliceLogic.GetSliceCompositeNode()
796 foregroundOpacity = compositeNode.GetForegroundOpacity()
798 if foregroundOpacity > 0.5:
799 return foregroundLogic
801 return backgroundLogic
804 masterImageData = self.scriptedEffect.sourceVolumeImageData()
816 brushBounds = brushPolydata.GetBounds()
817 brushExtent = [0, -1, 0, -1, 0, -1]
819 brushExtent[2 * i] = vtk.vtkMath.Floor(brushBounds[2 * i])
820 brushExtent[2 * i + 1] = vtk.vtkMath.Ceil(brushBounds[2 * i + 1])
821 if brushExtent[0] > brushExtent[1]
or brushExtent[2] > brushExtent[3]
or brushExtent[4] > brushExtent[5]:
826 self.
reslice.SetInputConnection(layerLogic.GetReslice().GetInputConnection(0, 0))
827 self.
reslice.SetResliceTransform(layerLogic.GetReslice().GetResliceTransform())
828 self.
reslice.SetInterpolationMode(layerLogic.GetReslice().GetInterpolationMode())
829 self.
reslice.SetOutputExtent(brushExtent)
831 maxNumberOfBins = 1000
832 masterImageData = self.scriptedEffect.sourceVolumeImageData()
833 scalarRange = masterImageData.GetScalarRange()
834 scalarType = masterImageData.GetScalarType()
835 if scalarType == vtk.VTK_FLOAT
or scalarType == vtk.VTK_DOUBLE:
836 numberOfBins = maxNumberOfBins
838 numberOfBins = int(scalarRange[1] - scalarRange[0]) + 1
839 if numberOfBins > maxNumberOfBins:
840 numberOfBins = maxNumberOfBins
841 binSpacing = (scalarRange[1] - scalarRange[0] + 1) / numberOfBins
843 self.
imageAccumulate.SetComponentExtent(0, numberOfBins - 1, 0, 0, 0, 0)
844 self.
imageAccumulate.SetComponentSpacing(binSpacing, binSpacing, binSpacing)
845 self.
imageAccumulate.SetComponentOrigin(scalarRange[0], scalarRange[0], scalarRange[0])
850 tableSize = self.
imageAccumulate.GetOutput().GetPointData().GetScalars().GetNumberOfTuples()
851 for i
in range(tableSize):
852 value = self.
imageAccumulate.GetOutput().GetPointData().GetScalars().GetTuple1(i)
867 lower = min(startX, endX)
868 average = (startX + endX) / 2.0
869 upper = max(startX, endX)
887 minimumThreshold = lower
888 maximumThreshold = upper
890 histogramSetModeLower = self.scriptedEffect.parameter(HISTOGRAM_SET_LOWER_PARAMETER_NAME)
891 if histogramSetModeLower == HISTOGRAM_SET_MINIMUM:
892 minimumThreshold = scalarRange[0]
893 elif histogramSetModeLower == HISTOGRAM_SET_LOWER:
894 minimumThreshold = lower
895 elif histogramSetModeLower == HISTOGRAM_SET_AVERAGE:
896 minimumThreshold = average
898 histogramSetModeUpper = self.scriptedEffect.parameter(HISTOGRAM_SET_UPPER_PARAMETER_NAME)
899 if histogramSetModeUpper == HISTOGRAM_SET_AVERAGE:
900 maximumThreshold = average
901 elif histogramSetModeUpper == HISTOGRAM_SET_UPPER:
902 maximumThreshold = upper
903 elif histogramSetModeUpper == HISTOGRAM_SET_MAXIMUM:
904 maximumThreshold = scalarRange[1]
906 self.scriptedEffect.setParameter(
"MinimumThreshold", minimumThreshold)
907 self.scriptedEffect.setParameter(
"MaximumThreshold", maximumThreshold)
912 masterImageData = self.scriptedEffect.sourceVolumeImageData()
913 if masterImageData
is None:
916 scalarRange = masterImageData.GetScalarRange()
919 low = self.scriptedEffect.doubleParameter(
"MinimumThreshold")
920 upper = self.scriptedEffect.doubleParameter(
"MaximumThreshold")
921 low = max(scalarRange[0] + epsilon, low)
922 upper = min(scalarRange[1] - epsilon, upper)