def runWatershed(self, masterImageData, seedLabelmap, outputLabelmap):

    masterVolumeNode = slicer.vtkMRMLScalarVolumeNode()
    slicer.mrmlScene.AddNode(masterVolumeNode)
    slicer.vtkSlicerSegmentationsModuleLogic.CopyOrientedImageDataToVolumeNode(masterImageData, masterVolumeNode)

    seedLabelmapNode = slicer.vtkMRMLLabelMapVolumeNode()
    slicer.mrmlScene.AddNode(seedLabelmapNode)
    slicer.vtkSlicerSegmentationsModuleLogic.CopyOrientedImageDataToVolumeNode(seedLabelmap, seedLabelmapNode)

    # Read input data from Slicer into SimpleITK
    labelImage = sitk.ReadImage(sitkUtils.GetSlicerITKReadWriteAddress(seedLabelmapNode.GetName()))
    backgroundImage = sitk.ReadImage(sitkUtils.GetSlicerITKReadWriteAddress(masterVolumeNode.GetName()))
    # Run watershed filter
    featureImage = sitk.GradientMagnitudeRecursiveGaussian(backgroundImage, float(self.scriptedEffect.doubleParameter(FEATURE_SIZE_MM_PARAMETER_NAME)))
    del backgroundImage
    f = sitk.MorphologicalWatershedFromMarkersImageFilter()
    f.SetMarkWatershedLine(False)
    f.SetFullyConnected(False)
    labelImage = f.Execute(featureImage, labelImage)
    del featureImage
    # Pixel type of watershed output is the same as the input. Convert it to int16 now.
    if labelImage.GetPixelID() != sitk.sitkInt16:
      labelImage = sitk.Cast(labelImage, sitk.sitkInt16)
    # Write result from SimpleITK to Slicer. This currently performs a deep copy of the bulk data.
    sitk.WriteImage(labelImage, sitkUtils.GetSlicerITKReadWriteAddress(seedLabelmapNode.GetName()))

    # Update segmentation from labelmap node and remove temporary nodes
    outputLabelmap.ShallowCopy(seedLabelmapNode.GetImageData())
    outputLabelmap.SetExtent(masterImageData.GetExtent())

    slicer.mrmlScene.RemoveNode(masterVolumeNode)
    slicer.mrmlScene.RemoveNode(seedLabelmapNode)
예제 #2
0
  def apply(self):

    if not self.editUtil.getBackgroundImage() or not self.editUtil.getLabelImage():
      return
    node = self.editUtil.getParameterNode()

    self.undoRedo.saveState()

    #
    # get the label and background images
    #
    sliceLogic = self.sliceWidget.sliceLogic()
    labelLogic = sliceLogic.GetLabelLayer()
    labelNode = labelLogic.GetVolumeNode()
    labelNodeName = labelNode.GetName()

    backgroundLogic = sliceLogic.GetBackgroundLayer()
    backgroundNode = backgroundLogic.GetVolumeNode()
    backgroundNodeName = backgroundNode.GetName()
    backgroundImage = sitk.ReadImage( sitkUtils.GetSlicerITKReadWriteAddress( backgroundNodeName ) )

    
    filter = sitk.DoubleThresholdImageFilter()
    filter.SetThreshold1( self.outer_min )
    filter.SetThreshold2( self.min )
    filter.SetThreshold3( self.max )
    filter.SetThreshold4( self.outer_max )
    filter.FullyConnectedOn()
    filter.SetInsideValue( self.editUtil.getLabel() )
    filter.SetOutsideValue( 0 )

    # todo
    # cast to output scalar type
    
    sitk.WriteImage( filter.Execute(backgroundImage), sitkUtils.GetSlicerITKReadWriteAddress( labelNodeName ) )
예제 #3
0
    def getBoundingBox(self, fixedLabelNodeID, movingLabelNodeID):

        ls = sitk.LabelStatisticsImageFilter()

        fixedLabelNode = slicer.mrmlScene.GetNodeByID(fixedLabelNodeID)
        movingLabelNode = slicer.mrmlScene.GetNodeByID(movingLabelNodeID)

        fixedLabelAddress = sitkUtils.GetSlicerITKReadWriteAddress(
            fixedLabelNode.GetName())
        movingLabelAddress = sitkUtils.GetSlicerITKReadWriteAddress(
            movingLabelNode.GetName())

        fixedLabelImage = sitk.ReadImage(fixedLabelAddress)
        movingLabelImage = sitk.ReadImage(movingLabelAddress)

        cast = sitk.CastImageFilter()
        cast.SetOutputPixelType(2)
        unionLabelImage = (cast.Execute(fixedLabelImage) +
                           cast.Execute(movingLabelImage)) > 0
        unionLabelImage = cast.Execute(unionLabelImage)

        ls.Execute(unionLabelImage, unionLabelImage)
        bb = ls.GetBoundingBox(1)
        print(str(bb))

        size = unionLabelImage.GetSize()
        bbMin = (max(0, bb[0] - 30), max(0, bb[2] - 30), max(0, bb[4] - 5))
        bbMax = (size[0] - min(size[0], bb[1] + 30),
                 size[1] - min(size[1], bb[3] + 30),
                 size[2] - (min(size[2], bb[5] + 5)))

        return (bbMin, bbMax)
예제 #4
0
    def computePreviewLabelmap(self, mergedImage, outputLabelmap):

        import vtkSegmentationCorePython as vtkSegmentationCore
        import vtkSlicerSegmentationsModuleLogicPython as vtkSlicerSegmentationsModuleLogic

        # This can be a long operation - indicate it to the user
        qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor)

        masterVolumeNode = slicer.vtkMRMLScalarVolumeNode()
        slicer.mrmlScene.AddNode(masterVolumeNode)
        slicer.vtkSlicerSegmentationsModuleLogic.CopyOrientedImageDataToVolumeNode(
            self.clippedMasterImageData, masterVolumeNode)

        mergedLabelmapNode = slicer.vtkMRMLLabelMapVolumeNode()
        slicer.mrmlScene.AddNode(mergedLabelmapNode)
        slicer.vtkSlicerSegmentationsModuleLogic.CopyOrientedImageDataToVolumeNode(
            mergedImage, mergedLabelmapNode)

        outputRasToIjk = vtk.vtkMatrix4x4()
        mergedImage.GetImageToWorldMatrix(outputRasToIjk)
        outputExtent = mergedImage.GetExtent()

        # Run segmentation algorithm
        import SimpleITK as sitk
        import sitkUtils
        # Read input data from Slicer into SimpleITK
        labelImage = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(
                mergedLabelmapNode.GetName()))
        backgroundImage = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(masterVolumeNode.GetName()))
        # Run watershed filter
        featureImage = sitk.GradientMagnitudeRecursiveGaussian(
            backgroundImage,
            float(self.scriptedEffect.doubleParameter("ObjectScaleMm")))
        del backgroundImage
        f = sitk.MorphologicalWatershedFromMarkersImageFilter()
        f.SetMarkWatershedLine(False)
        f.SetFullyConnected(False)
        labelImage = f.Execute(featureImage, labelImage)
        del featureImage
        # Pixel type of watershed output is the same as the input. Convert it to int16 now.
        if labelImage.GetPixelID() != sitk.sitkInt16:
            labelImage = sitk.Cast(labelImage, sitk.sitkInt16)
        # Write result from SimpleITK to Slicer. This currently performs a deep copy of the bulk data.
        sitk.WriteImage(
            labelImage,
            sitkUtils.GetSlicerITKReadWriteAddress(
                mergedLabelmapNode.GetName()))

        # Update segmentation from labelmap node and remove temporary nodes
        outputLabelmap.ShallowCopy(mergedLabelmapNode.GetImageData())
        outputLabelmap.SetImageToWorldMatrix(outputRasToIjk)
        outputLabelmap.SetExtent(outputExtent)

        slicer.mrmlScene.RemoveNode(masterVolumeNode)
        slicer.mrmlScene.RemoveNode(mergedLabelmapNode)

        qt.QApplication.restoreOverrideCursor()
예제 #5
0
  def onApply(self):

    # Get list of visible segment IDs, as the effect ignores hidden segments.
    segmentationNode = self.scriptedEffect.parameterSetNode().GetSegmentationNode()
    visibleSegmentIds = vtk.vtkStringArray()
    segmentationNode.GetDisplayNode().GetVisibleSegmentIDs(visibleSegmentIds)
    if visibleSegmentIds.GetNumberOfValues() == 0:
      logging.info("Smoothing operation skipped: there are no visible segments")
      return

    # This can be a long operation - indicate it to the user
    qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor)

    # Allow users revert to this state by clicking Undo
    self.scriptedEffect.saveStateForUndo()

    # Export master image data to temporary new volume node.
    # Note: Although the original master volume node is already in the scene, we do not use it here,
    # because the master volume may have been resampled to match segmentation geometry.
    import vtkSegmentationCorePython as vtkSegmentationCore
    masterVolumeNode = slicer.vtkMRMLScalarVolumeNode()
    slicer.mrmlScene.AddNode(masterVolumeNode)
    masterVolumeNode.SetAndObserveTransformNodeID(segmentationNode.GetTransformNodeID())
    slicer.vtkSlicerSegmentationsModuleLogic.CopyOrientedImageDataToVolumeNode(self.scriptedEffect.masterVolumeImageData(), masterVolumeNode)
    # Generate merged labelmap of all visible segments, as the filter expects a single labelmap with all the labels.
    mergedLabelmapNode = slicer.vtkMRMLLabelMapVolumeNode()
    slicer.mrmlScene.AddNode(mergedLabelmapNode)
    slicer.vtkSlicerSegmentationsModuleLogic.ExportSegmentsToLabelmapNode(segmentationNode, visibleSegmentIds, mergedLabelmapNode, masterVolumeNode)

    # Run segmentation algorithm
    import SimpleITK as sitk
    import sitkUtils
    # Read input data from Slicer into SimpleITK
    labelImage = sitk.ReadImage(sitkUtils.GetSlicerITKReadWriteAddress(mergedLabelmapNode.GetName()))
    backgroundImage = sitk.ReadImage(sitkUtils.GetSlicerITKReadWriteAddress(masterVolumeNode.GetName()))
    # Run watershed filter
    featureImage = sitk.GradientMagnitudeRecursiveGaussian(backgroundImage, float(self.scriptedEffect.doubleParameter("ObjectScaleMm")))
    del backgroundImage
    f = sitk.MorphologicalWatershedFromMarkersImageFilter()
    f.SetMarkWatershedLine(False)
    f.SetFullyConnected(False)
    labelImage = f.Execute(featureImage, labelImage)
    del featureImage
    # Pixel type of watershed output is the same as the input. Convert it to int16 now.
    if labelImage.GetPixelID() != sitk.sitkInt16:
      labelImage = sitk.Cast(labelImage, sitk.sitkInt16)
    # Write result from SimpleITK to Slicer. This currently performs a deep copy of the bulk data.
    sitk.WriteImage(labelImage, sitkUtils.GetSlicerITKReadWriteAddress(mergedLabelmapNode.GetName()))
    mergedLabelmapNode.GetImageData().Modified()
    mergedLabelmapNode.Modified()

    # Update segmentation from labelmap node and remove temporary nodes
    slicer.vtkSlicerSegmentationsModuleLogic.ImportLabelmapToSegmentationNode(mergedLabelmapNode, segmentationNode, visibleSegmentIds)
    slicer.mrmlScene.RemoveNode(masterVolumeNode)
    slicer.mrmlScene.RemoveNode(mergedLabelmapNode)

    qt.QApplication.restoreOverrideCursor()
예제 #6
0
  def prepareLabelsFromSegmentation(self, segmentationNode, grayscaleImage, labelsDict):
    import vtkSegmentationCorePython as vtkSegmentationCore
    segLogic = slicer.modules.segmentations.logic()

    segmentation = segmentationNode.GetSegmentation()
    binaryRepresentationDef = vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationBinaryLabelmapRepresentationName()
    if not segmentation.ContainsRepresentation(binaryRepresentationDef):
      segmentation.CreateRepresentation(binaryRepresentationDef)

    segmentLabelmapNode = slicer.vtkMRMLLabelMapVolumeNode()
    slicer.mrmlScene.AddNode(segmentLabelmapNode)

    for segmentID in range(segmentation.GetNumberOfSegments()):
      segment = segmentation.GetNthSegment(segmentID)
      segmentLabelmap = segment.GetRepresentation(
        vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationBinaryLabelmapRepresentationName())
      if not segLogic.CreateLabelmapVolumeFromOrientedImageData(segmentLabelmap, segmentLabelmapNode):
        self.logger.error("Failed to convert label map")
        return labelsDict
      labelmapImage = sitk.ReadImage(sitkUtils.GetSlicerITKReadWriteAddress(segmentLabelmapNode.GetName()))
      labelmapImage = self.resampleITKLabel(labelmapImage, grayscaleImage)
      labelsDict[segmentationNode.GetName()+"_segment_"+segment.GetName()] = labelmapImage

    displayNode = segmentLabelmapNode.GetDisplayNode()
    if displayNode:
      slicer.mrmlScene.RemoveNode(displayNode)
    slicer.mrmlScene.RemoveNode(segmentLabelmapNode)

    return labelsDict
예제 #7
0
    def onFiducialNode(self, name, mrmlWidget, isPoint):
        if not mrmlWidget.visible:
            return
        annotationFiducialNode = mrmlWidget.currentNode()

        # point in physical space
        coord = [0, 0, 0]

        if annotationFiducialNode.GetClassName(
        ) == "vtkMRMLMarkupsFiducialNode":
            # slicer4 Markups node
            if annotationFiducialNode.GetNumberOfFiducials() < 1:
                return
            annotationFiducialNode.GetNthFiducialPosition(0, coord)
        else:
            annotationFiducialNode.GetFiducialCoordinates(coord)

        # HACK transform from RAS to LPS
        coord = [-coord[0], -coord[1], coord[2]]

        # FIXME: we should not need to copy the image
        if not isPoint and len(self.inputs) and self.inputs[0]:
            imgNodeName = self.inputs[0].GetName()
            img = sitk.ReadImage(
                sitkUtils.GetSlicerITKReadWriteAddress(imgNodeName))
            coord = img.TransformPhysicalPointToIndex(coord)
        exec('self.filter.Set{0}(coord)'.format(name))
예제 #8
0
    def run(self, filter, outputMRMLNode, outputLabelMap, *inputs):
        """
    Run the actual algorithm
    """

        if self.thread.is_alive():
            import sys
            sys.stderr.write("FilterLogic is already executing!")
            return

        inputImages = []

        for i in inputs:
            if i is None:
                break

            imgNodeName = i.GetName()

            img = sitk.ReadImage(
                sitkUtils.GetSlicerITKReadWriteAddress(imgNodeName))
            inputImages.append(img)

        self.output = None
        # check
        self.outputNodeName = outputMRMLNode.GetName()
        self.outputLabelMap = outputLabelMap

        self.abort = False

        self.thread = threading.Thread(target=lambda f=filter, i=inputImages:
                                       self.thread_doit(f, *inputImages))

        self.main_queue_start()
        self.thread.start()
예제 #9
0
    def calculateFeatures(self, imageNode, labelNode, segmentationNode,
                          extractor):
        """
    Calculate the feature on the image node for each ROI contained in the labelNode and/or the segmentation node, using
    an instantiated RadiomicsFeatureExtractor (with customization already configured).
    """
        # Prepare the input volume
        self.logger.debug('Read the input image node')
        grayscaleImage = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(imageNode.GetName()))

        # Prepare the input label map
        self.logger.debug('Read and prepare the input ROI(s)')
        labelsDict = {}
        if labelNode:
            labelsDict = self.prepareLabelsFromLabelmap(
                labelNode, grayscaleImage, labelsDict)
        if segmentationNode:
            labelsDict = self.prepareLabelsFromSegmentation(
                segmentationNode, grayscaleImage, labelsDict)

        # Calculate the features
        featuresDict = {}
        for l in labelsDict.keys():
            self.logger.debug("Calculating features for " + l)
            try:
                self.logger.debug('Starting feature calculation')
                featuresDict[l] = extractor.execute(grayscaleImage,
                                                    labelsDict[l])
                self.logger.debug('Features calculated')
            except:
                self.logger.error('calculateFeatures() failed')
                traceback.print_exc()

        return featuresDict
예제 #10
0
    def run(self, imageNode, labelNode, segmentationNode, featureClasses,
            **kwargs):
        """
    Run the actual algorithm
    """

        self.logger.info('Processing started')

        grayscaleImage = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(imageNode.GetName()))

        #sitkUtils.PushToSlicer(label, labelNode.GetName(), overwrite=True, compositeView=2)

        labelsDict = {}
        if labelNode:
            labelsDict = self.prepareLabelsFromLabelmap(
                labelNode, grayscaleImage, labelsDict)
        if segmentationNode:
            labelsDict = self.prepareLabelsFromSegmentation(
                segmentationNode, grayscaleImage, labelsDict)

        #self.featureValues = extractor.execute(grayscaleImage, labelImage, image, **kwargs)

        featuresDict = {}
        for l in labelsDict.keys():
            self.logger.debug("Calculating features for " + l)
            featuresDict[l] = self.calculateFeatures(grayscaleImage,
                                                     labelsDict[l],
                                                     featureClasses, **kwargs)

        return featuresDict
예제 #11
0
  def _getLabelGeneratorFromLabelMap(self, labelNode, imageNode):
    combinedLabelImage = sitk.ReadImage(sitkUtils.GetSlicerITKReadWriteAddress(labelNode.GetName()))
    combinedLabelArray = sitk.GetArrayFromImage(combinedLabelImage)
    labels = numpy.unique(combinedLabelArray)

    for l in labels:
      if l == 0:
        continue
      yield '%s_label_%d' % (labelNode.GetName(), l), labelNode, int(l), imageNode
예제 #12
0
    def onInputSelect(self, mrmlNode, n):
        self.inputs[n] = mrmlNode

        if n == 0 and self.inputs[0]:
            # if the input zero is a label assume the output is too, test widgets
            self.onOutputLabelMapChanged(mrmlNode.GetLabelMap())

            imgNodeName = self.inputs[0].GetName()
            img = sitk.ReadImage(
                sitkUtils.GetSlicerITKReadWriteAddress(imgNodeName))
예제 #13
0
    def doit(self):

        import SimpleITK as sitk
        import sitkUtils

        labelLogic = self.sliceLogic.GetLabelLayer()
        labelNode = labelLogic.GetVolumeNode()
        labelNodeName = labelNode.GetName()
        labelImage = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(labelNodeName))

        backgroundLogic = self.sliceLogic.GetBackgroundLayer()
        backgroundNode = backgroundLogic.GetVolumeNode()
        backgroundNodeName = backgroundNode.GetName()
        backgroundImage = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(backgroundNodeName))

        # store a backup copy of the label map for undo
        # (this happens in it's own thread, so it is cheap)
        if self.undoRedo:
            self.undoRedo.saveState()

        featureImage = sitk.GradientMagnitudeRecursiveGaussian(
            backgroundImage, float(self.sigma))
        del backgroundImage
        f = sitk.MorphologicalWatershedFromMarkersImageFilter()
        f.SetMarkWatershedLine(False)
        f.SetFullyConnected(False)
        labelImage = f.Execute(featureImage, labelImage)
        del featureImage

        # The output of the watershed is the same as the input.
        # But Slicer expects labelMaps to be Int16, so convert to that
        # type to improve compatibility, just in case if needed.
        if labelImage.GetPixelID() != sitk.sitkInt16:
            labelImage = sitk.Cast(labelImage, sitk.sitkInt16)

        # This currently performs a deep copy of the bulk data.
        sitk.WriteImage(labelImage,
                        sitkUtils.GetSlicerITKReadWriteAddress(labelNodeName))
        labelNode.GetImageData().Modified()
        labelNode.Modified()
예제 #14
0
def getDice(reference, moving):
    moving = runBRAINSResample(moving, reference)

    referenceAddress = sitkUtils.GetSlicerITKReadWriteAddress(
        reference.GetName())
    image_reference = sitk.ReadImage(referenceAddress)

    movingAddress = sitkUtils.GetSlicerITKReadWriteAddress(moving.GetName())
    image_input = sitk.ReadImage(movingAddress)

    # make sure both labels have the same value
    threshold = sitk.BinaryThresholdImageFilter()
    threshold.SetUpperThreshold(100)
    threshold.SetLowerThreshold(1)
    threshold.SetInsideValue(1)
    image_reference = threshold.Execute(image_reference)
    image_input = threshold.Execute(image_input)

    measureFilter = sitk.LabelOverlapMeasuresImageFilter()
    if measureFilter.Execute(image_reference, image_input):
        print 'filter executed'
    value = measureFilter.GetDiceCoefficient()

    return value
예제 #15
0
  def prepareLabelsFromLabelmap(self, labelmapNode, grayscaleImage, labelsDict):

    combinedLabelImage = sitk.ReadImage(sitkUtils.GetSlicerITKReadWriteAddress(labelmapNode.GetName()))
    resampledLabelImage = self.resampleITKLabel(combinedLabelImage, grayscaleImage)

    ls = sitk.LabelStatisticsImageFilter()
    ls.Execute(resampledLabelImage,resampledLabelImage)
    th = sitk.BinaryThresholdImageFilter()
    th.SetInsideValue(1)
    th.SetOutsideValue(0)

    for l in ls.GetLabels()[1:]:
      th.SetUpperThreshold(l)
      th.SetLowerThreshold(l)
      labelsDict[labelmapNode.GetName()+"_label_"+str(l)] = th.Execute(combinedLabelImage)

    return labelsDict
예제 #16
0
    def onFiducialListNode(self, name, mrmlNode):
        annotationHierarchyNode = mrmlNode

        # list of points in physical space
        coords = []

        if annotationHierarchyNode.GetClassName(
        ) == "vtkMRMLMarkupsFiducialNode":
            # slicer4 Markups node

            for i in range(annotationHierarchyNode.GetNumberOfFiducials()):
                coord = [0, 0, 0]
                annotationHierarchyNode.GetNthFiducialPosition(i, coord)
                coords.append(coord)
        else:
            # slicer4 style hierarchy nodes

            # get the first in the list
            for listIndex in range(
                    annotationHierarchyNode.GetNumberOfChildrenNodes()):
                if annotationHierarchyNode.GetNthChildNode(listIndex) is None:
                    continue

                annotation = annotationHierarchyNode.GetNthChildNode(
                    listIndex).GetAssociatedNode()
                if annotation is None:
                    continue

                coord = [0, 0, 0]
                annotation.GetFiducialCoordinates(coord)
                coords.append(coord)

        if self.inputs[0]:
            imgNodeName = self.inputs[0].GetName()
            img = sitk.ReadImage(
                sitkUtils.GetSlicerITKReadWriteAddress(imgNodeName))

            # HACK transform from RAS to LPS
            coords = [[-pt[0], -pt[1], pt[2]] for pt in coords]

            idx_coords = [
                img.TransformPhysicalPointToIndex(pt) for pt in coords
            ]

            exec('self.filter.Set{0}(idx_coords)'.format(name))
    def updateOutput(self, img):

        nodeWriteAddress = sitkUtils.GetSlicerITKReadWriteAddress(
            self.outputNodeName)
        sitk.WriteImage(img, nodeWriteAddress)

        node = slicer.util.getNode(self.outputNodeName)

        applicationLogic = slicer.app.applicationLogic()
        selectionNode = applicationLogic.GetSelectionNode()

        if self.outputLabelMap:
            selectionNode.SetReferenceActiveLabelVolumeID(node.GetID())
        else:
            selectionNode.SetReferenceActiveVolumeID(node.GetID())

        applicationLogic.PropagateVolumeSelection(0)
        applicationLogic.FitSliceToAll()
    def getCentroidForLabel(labelNode, value):
        if not labelNode:
            return None
        labelAddress = sitkUtils.GetSlicerITKReadWriteAddress(
            labelNode.GetName())
        labelImage = sitk.ReadImage(labelAddress)

        ls = sitk.LabelStatisticsImageFilter()
        ls.Execute(labelImage, labelImage)
        bb = ls.GetBoundingBox(value)

        centroid = None  # sagittal, coronal, axial
        if len(bb) > 0:
            centerIJK = [((bb[0] + bb[1]) / 2), ((bb[2] + bb[3]) / 2),
                         ((bb[4] + bb[5]) / 2)]
            logging.debug('BB is: ' + str(bb))
            logging.debug('i_center = ' + str(centerIJK[0]))
            logging.debug('j_center = ' + str(centerIJK[1]))
            logging.debug('k_center = ' + str(centerIJK[2]))

            IJKtoRAS = vtk.vtkMatrix4x4()
            labelNode.GetIJKToRASMatrix(IJKtoRAS)
            IJKtoRASDir = vtk.vtkMatrix4x4()
            labelNode.GetIJKToRASDirectionMatrix(IJKtoRASDir)
            RAScoord = IJKtoRAS.MultiplyPoint(
                (centerIJK[0], centerIJK[1], centerIJK[2], 1))

            order = labelNode.ComputeScanOrderFromIJKToRAS(IJKtoRAS)
            if order == 'IS':
                RASDir = IJKtoRASDir.MultiplyPoint(
                    (RAScoord[0], RAScoord[1], RAScoord[2], 1))
                centroid = [-RASDir[0], -RASDir[1], RASDir[2]]
            elif order == 'AP':
                RASDir = IJKtoRASDir.MultiplyPoint(
                    (RAScoord[0], RAScoord[1], RAScoord[2], 1))
                centroid = [-RASDir[0], -RASDir[2], -RASDir[1]]
            elif order == 'LR':
                RASDir = IJKtoRASDir.MultiplyPoint(
                    (RAScoord[2], RAScoord[1], RAScoord[0], 1))
                centroid = [RASDir[0], -RASDir[2], -RASDir[1]]
        return centroid
예제 #19
0
    def __init__(self, grayscaleNode, labelNode, fileName=None):
        #import numpy

        self.keys = [
            "Label", "Count", "Volume mm^3", "Volume cc", "Min", "Max", "Mean",
            "StdDev"
        ]
        cubicMMPerVoxel = reduce(lambda x, y: x * y, labelNode.GetSpacing())
        ccPerCubicMM = 0.001

        # TODO: progress and status updates
        # this->InvokeEvent(vtkLabelStatisticsLogic::StartLabelStats, (void*)"start label stats")

        self.labelStats = {}
        self.labelStats['Labels'] = []

        labelNodeName = labelNode.GetName()
        labelImage = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(labelNodeName))

        grayscaleNodeName = grayscaleNode.GetName()
        grayscaleImage = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(grayscaleNodeName))

        sitkStats = sitk.LabelStatisticsImageFilter()

        sitkStats.Execute(grayscaleImage, labelImage)

        for l in sitkStats.GetLabels():

            # add an entry to the LabelStats list
            self.labelStats["Labels"].append(l)
            self.labelStats[l, "Label"] = l
            self.labelStats[l, "Count"] = sitkStats.GetCount(l)
            self.labelStats[
                l,
                "Volume mm^3"] = self.labelStats[l, "Count"] * cubicMMPerVoxel
            self.labelStats[
                l,
                "Volume cc"] = self.labelStats[l, "Volume mm^3"] * ccPerCubicMM
            self.labelStats[l, "Min"] = sitkStats.GetMinimum(l)
            self.labelStats[l, "Max"] = sitkStats.GetMaximum(l)
            self.labelStats[l, "Mean"] = sitkStats.GetMean(l)
            self.labelStats[l, "StdDev"] = sitkStats.GetSigma(l)
            self.labelStats[l, "Sum"] = sitkStats.GetSum(l)

        del sitkStats

        sitkShapeStats = sitk.LabelShapeStatisticsImageFilter()
        sitkShapeStats.ComputeFeretDiameterOff()
        sitkShapeStats.ComputePerimeterOn()

        sitkShapeStats.Execute(labelImage)

        # use a set to accumulate attributes to make sure they are unuque
        shapeAttributes = [
            #      'Number Of Pixels',
            #      'Physical Size',
            #      'Centroid',
            #      'Bounding Box',
            'Number Of Pixels On Border',
            'Perimeter On Border',
            'Perimeter On Border Ratio',
            #      'Principal Moments',
            'Principal Axes',
            'Elongation',
            'Perimeter',
            'Roundness',
            'Equivalent Spherical Radius',
            'Equivalent Spherical Perimeter',
            #      'Equivalent Ellipsoid Diameter',
            'Flatness',
            'Feret Diameter'
        ]

        if not sitkShapeStats.GetComputeFeretDiameter():
            shapeAttributes.remove('Feret Diameter')

        if not sitkShapeStats.GetComputePerimeter():
            shapeAttributes.remove('Perimeter')

        # We don't have a good way to show
        shapeAttributes.remove('Principal Axes')

        self.keys += shapeAttributes

        for l in sitkShapeStats.GetLabels():
            # add attributes form the Shape label object
            for name in shapeAttributes:
                attr = getattr(sitkShapeStats,
                               "Get" + name.replace(' ', ''))(l)

                self.labelStats[l, name] = attr

        for l in sitkShapeStats.GetLabels():
            attr = getattr(sitkShapeStats, "Get" + "PrincipalMoments")(l)
            for i in range(1, 4):
                self.labelStats[l, "Principal Moments " + str(i)] = attr[i - 1]

        self.keys += ["Principal Moments " + str(i) for i in range(1, 4)]
예제 #20
0
    def createModels(self):
        self.deleteModels()
        self.labelScores = []
        self.selectedLableList = []
        if self.calcinationType == 0 and self.volumeNode and self.roiNode:
            #print 'in Heart Create Models'

            slicer.vtkSlicerCropVolumeLogic().CropVoxelBased(self.roiNode, self.volumeNode, self.croppedNode)
            croppedImage    = sitk.ReadImage( sitkUtils.GetSlicerITKReadWriteAddress(self.croppedNode.GetName()))
            thresholdImage  = sitk.BinaryThreshold(croppedImage,self.ThresholdMin, self.ThresholdMax, 1, 0)
            connectedCompImage  =sitk.ConnectedComponent(thresholdImage, True)
            relabelImage  =sitk.RelabelComponent(connectedCompImage)
            labelStatFilter =sitk.LabelStatisticsImageFilter()
            labelStatFilter.Execute(croppedImage, relabelImage)
            if relabelImage.GetPixelID() != sitk.sitkInt16:
                relabelImage = sitk.Cast( relabelImage, sitk.sitkInt16 )
            sitk.WriteImage( relabelImage, sitkUtils.GetSlicerITKReadWriteAddress(self.labelsNode.GetName()))

            nLabels = labelStatFilter.GetNumberOfLabels()
            #print "Number of labels = ", nLabels
            self.totalScore = 0
            count = 0
            for n in range(0,nLabels):
                max = labelStatFilter.GetMaximum(n);
                size = labelStatFilter.GetCount(n)
                score = self.computeScore(max)

                if size*self.voxelVolume > self.MaximumLesionSize:
                    continue

                if size*self.voxelVolume < self.MinimumLesionSize:
                    nLabels = n+1
                    break
                
                #print "label = ", n, "  max = ", max, " score = ", score, " voxels = ", size
                self.labelScores.append(score)
                self.selectedLableList.append(0)
                self.marchingCubes.SetInputData(self.labelsNode.GetImageData())
                self.marchingCubes.SetValue(0, n)
                self.marchingCubes.Update()
                    
                self.transformPolyData.SetInputData(self.marchingCubes.GetOutput())
                mat = vtk.vtkMatrix4x4()
                self.labelsNode.GetIJKToRASMatrix(mat)
                trans = vtk.vtkTransform()
                trans.SetMatrix(mat)
                self.transformPolyData.SetTransform(trans)
                self.transformPolyData.Update()
                poly = vtk.vtkPolyData()
                poly.DeepCopy(self.transformPolyData.GetOutput())
                    
                modelNode = slicer.vtkMRMLModelNode()
                slicer.mrmlScene.AddNode(modelNode)
                dnode = slicer.vtkMRMLModelDisplayNode()
                slicer.mrmlScene.AddNode(dnode)
                modelNode.AddAndObserveDisplayNodeID(dnode.GetID())
                modelNode.SetAndObservePolyData(poly)

                ct=slicer.mrmlScene.GetNodeByID('vtkMRMLColorTableNodeLabels')
                rgb = [0,0,0]
                ct.GetLookupTable().GetColor(count+1,rgb)
                dnode.SetColor(rgb)

                self.addLabel(count, rgb, score)

                self.modelNodes.append(modelNode)
                self.selectedLables[poly] = n
                count = count+1
                #a = slicer.util.array(tn.GetID())
                #sa = sitk.GetImageFromArray(a)
            self.scoreField.setText(self.totalScore)
        else:
            print "not implemented"
예제 #21
0
    def preProcessLabel(self, labelNodeID, bbMin, bbMax):

        print('Label node ID: ' + labelNodeID)

        labelNode = slicer.util.getNode(labelNodeID)

        labelNodeAddress = sitkUtils.GetSlicerITKReadWriteAddress(
            labelNode.GetName())

        print('Label node address: ' + str(labelNodeAddress))

        labelImage = sitk.ReadImage(labelNodeAddress)

        print('Read image: ' + str(labelImage))

        crop = sitk.CropImageFilter()
        crop.SetLowerBoundaryCropSize(bbMin)
        crop.SetUpperBoundaryCropSize(bbMax)
        croppedImage = crop.Execute(labelImage)

        print('Cropped image done: ' + str(croppedImage))

        croppedLabelName = labelNode.GetName() + '-Cropped'
        sitkUtils.PushToSlicer(croppedImage, croppedLabelName, overwrite=True)
        print('Cropped volume pushed')

        croppedLabel = slicer.util.getNode(croppedLabelName)

        print('Smoothed image done')

        smoothLabelName = labelNode.GetName() + '-Smoothed'
        smoothLabel = self.createVolumeNode(smoothLabelName)

        # smooth the labels
        smoothingParameters = {
            'inputImageName': croppedLabel.GetID(),
            'outputImageName': smoothLabel.GetID()
        }
        print(str(smoothingParameters))
        cliNode = slicer.cli.run(slicer.modules.segmentationsmoothing,
                                 None,
                                 smoothingParameters,
                                 wait_for_completion=True)

        # crop the bounding box
        '''
    TODO:
     * output volume node probably not needed here
     * intermediate nodes should probably be hidden
    '''

        dt = sitk.SignedMaurerDistanceMapImageFilter()
        dt.SetSquaredDistance(False)
        distanceMapName = labelNode.GetName() + '-DistanceMap'
        print('Reading smoothed image: ' + smoothLabel.GetID())
        smoothLabelAddress = sitkUtils.GetSlicerITKReadWriteAddress(
            smoothLabel.GetName())
        smoothLabelImage = sitk.ReadImage(smoothLabelAddress)
        print(smoothLabelAddress)
        distanceImage = dt.Execute(smoothLabelImage)
        sitkUtils.PushToSlicer(distanceImage, distanceMapName, overwrite=True)

        return slicer.util.getNode(distanceMapName)
예제 #22
0
 def getStartEndWithConnectedComponents(self, volume, center):
     address = sitkUtils.GetSlicerITKReadWriteAddress(volume.GetName())
     image = sitk.ReadImage(address)
     start = self.getStartSliceUsingConnectedComponents(center, image)
     end = self.getEndSliceUsingConnectedComponents(center, image)
     return start, end
예제 #23
0
    def createModels(self):
        # Reset previous model and labels
        self.deleteModels()
        for sr in self.summary_reports:
            self.labelScores[sr] = []
        self.selectedLabelList = []

        if self.calcificationType == 0 and self.volumeNode and self.roiNode:
            slicer.vtkSlicerCropVolumeLogic().CropVoxelBased(
                self.roiNode, self.volumeNode, self.croppedNode)
            croppedImage = sitk.ReadImage(
                sitkUtils.GetSlicerITKReadWriteAddress(
                    self.croppedNode.GetName()))
            thresholdImage = sitk.BinaryThreshold(croppedImage,
                                                  self.ThresholdMin,
                                                  self.ThresholdMax, 1, 0)
            connectedCompImage = sitk.ConnectedComponent(thresholdImage, True)
            relabelImage = sitk.RelabelComponent(connectedCompImage)
            labelStatFilter = sitk.LabelStatisticsImageFilter()
            labelStatFilter.Execute(croppedImage, relabelImage)
            if relabelImage.GetPixelID() != sitk.sitkInt16:
                relabelImage = sitk.Cast(relabelImage, sitk.sitkInt16)
            sitk.WriteImage(
                relabelImage,
                sitkUtils.GetSlicerITKReadWriteAddress(
                    self.labelsNode.GetName()))

            prod_spacing = np.prod(croppedImage.GetSpacing())

            nLabels = labelStatFilter.GetNumberOfLabels()
            self.totalScore = 0
            count = 0
            for n in range(0, nLabels):
                max = labelStatFilter.GetMaximum(n)
                mean = labelStatFilter.GetMean(n)
                size = labelStatFilter.GetCount(n)
                volume = size * self.voxelVolume

                # current label is discarted if volume not meet the maximum allowed threshold
                if volume > self.MaximumLesionSize:
                    continue

                # As ordered, we stop here if the volume of the current label is less than threshold
                if volume < self.MinimumLesionSize:
                    nLabels = n + 1
                    break
                score2d, volume, mass_score = self.agatston_computation(
                    n, relabelImage, croppedImage, prod_spacing)
                # Agatston 3d:
                # -----------
                density_score = self.computeDensityScore(max)
                score3d = size * (self.sx * self.sy) * density_score
                mass_score = mean * volume

                # self.labelScores["Agatston Score"].append(score)
                self.labelScores["Agatston Score 3D"].append(score3d)
                self.labelScores["Agatston Score 2D"].append(score2d)
                self.labelScores["Mass Score"].append(mass_score)
                self.labelScores["Volume"].append(volume)
                self.selectedLabelList.append(0)

                # generate the contour
                marchingCubes = vtk.vtkDiscreteMarchingCubes()
                marchingCubes.SetInputData(self.labelsNode.GetImageData())
                marchingCubes.SetValue(0, count + 1)
                marchingCubes.Update()

                transformPolyData = vtk.vtkTransformPolyDataFilter()
                transformPolyData.SetInputData(marchingCubes.GetOutput())
                mat = vtk.vtkMatrix4x4()
                self.labelsNode.GetIJKToRASMatrix(mat)
                trans = vtk.vtkTransform()
                trans.SetMatrix(mat)
                transformPolyData.SetTransform(trans)
                transformPolyData.Update()
                poly = vtk.vtkPolyData()
                poly.DeepCopy(transformPolyData.GetOutput())

                modelNode = slicer.vtkMRMLModelNode()
                slicer.mrmlScene.AddNode(modelNode)
                dnode = slicer.vtkMRMLModelDisplayNode()
                slicer.mrmlScene.AddNode(dnode)
                modelNode.AddAndObserveDisplayNodeID(dnode.GetID())
                modelNode.SetAndObservePolyData(poly)

                ct = slicer.mrmlScene.GetNodeByID(
                    'vtkMRMLColorTableNodeLabels')
                rgb = [0, 0, 0]
                ct.GetLookupTable().GetColor(count + 1, rgb)
                dnode.SetColor(rgb)
                # Enable Slice intersection
                dnode.SetSliceDisplayMode(0)
                dnode.SetSliceIntersectionVisibility(1)

                # self.addLabel(count, rgb, [score, mass_score, volume, mean, max])
                self.addLabel(
                    count, rgb,
                    [score2d, score3d, mass_score, volume, mean, max])
                count = count + 1

                self.modelNodes.append(modelNode)
                self.selectedLabels[poly] = n

            for sr in self.summary_reports:
                self.scoreField[sr].setText(self.totalScores[sr])
예제 #24
0
    def createModels(self):
        self.deleteModels()
        for sr in self.summary_reports:
            self.labelScores[sr]=[]
        self.selectedLabelList = []
        if self.calcificationType == 0 and self.volumeNode and self.roiNode:
            #print 'in Heart Create Models'

            slicer.vtkSlicerCropVolumeLogic().CropVoxelBased(self.roiNode, self.volumeNode, self.croppedNode)
            croppedImage    = sitk.ReadImage( sitkUtils.GetSlicerITKReadWriteAddress(self.croppedNode.GetName()))
            thresholdImage  = sitk.BinaryThreshold(croppedImage,self.ThresholdMin, self.ThresholdMax, 1, 0)
            connectedCompImage  =sitk.ConnectedComponent(thresholdImage, True)
            relabelImage  =sitk.RelabelComponent(connectedCompImage)
            labelStatFilter =sitk.LabelStatisticsImageFilter()
            labelStatFilter.Execute(croppedImage, relabelImage)
            if relabelImage.GetPixelID() != sitk.sitkInt16:
                relabelImage = sitk.Cast( relabelImage, sitk.sitkInt16 )
            sitk.WriteImage( relabelImage, sitkUtils.GetSlicerITKReadWriteAddress(self.labelsNode.GetName()))

            nLabels = labelStatFilter.GetNumberOfLabels()
            #print "Number of labels = ", nLabels
            self.totalScore = 0
            count = 0
            #Computation of the score follows this paper:
            #C. H McCollough, Radiology, 243(2), 2007
            
            for n in range(0,nLabels):
                max = labelStatFilter.GetMaximum(n)
                mean = labelStatFilter.GetMean(n)
                size = labelStatFilter.GetCount(n)
                volume = size*self.voxelVolume
                if volume > self.MaximumLesionSize:
                    continue

                if volume < self.MinimumLesionSize:
                    nLabels = n+1
                    break
                
                density_score = self.computeDensityScore(max)

                #Agatston score is \sum_i area_i * density_score_i
                #For now we assume that all the plaques have the same density score
                score = size*(self.sx*self.sy)*density_score
                
                mass_score = mean*volume

                #print "label = ", n, "  max = ", max, " score = ", score, " voxels = ", size
                self.labelScores["Agatston Score"].append(score)
                self.labelScores["Mass Score"].append(mass_score)
                self.labelScores["Volume"].append(volume)
                self.selectedLabelList.append(0)
                self.marchingCubes.SetInputData(self.labelsNode.GetImageData())
                self.marchingCubes.SetValue(0, n)
                self.marchingCubes.Update()
                    
                self.transformPolyData.SetInputData(self.marchingCubes.GetOutput())
                mat = vtk.vtkMatrix4x4()
                self.labelsNode.GetIJKToRASMatrix(mat)
                trans = vtk.vtkTransform()
                trans.SetMatrix(mat)
                self.transformPolyData.SetTransform(trans)
                self.transformPolyData.Update()
                poly = vtk.vtkPolyData()
                poly.DeepCopy(self.transformPolyData.GetOutput())
                    
                modelNode = slicer.vtkMRMLModelNode()
                slicer.mrmlScene.AddNode(modelNode)
                dnode = slicer.vtkMRMLModelDisplayNode()
                slicer.mrmlScene.AddNode(dnode)
                modelNode.AddAndObserveDisplayNodeID(dnode.GetID())
                modelNode.SetAndObservePolyData(poly)

                ct=slicer.mrmlScene.GetNodeByID('vtkMRMLColorTableNodeLabels')
                rgb = [0,0,0]
                ct.GetLookupTable().GetColor(count+1,rgb)
                dnode.SetColor(rgb)
                #Enable Slice intersection
                dnode.SetSliceDisplayMode(0)
                dnode.SetSliceIntersectionVisibility(1)

                self.addLabel(count, rgb, [score,mass_score,volume,mean,max])
                count = count+1

                self.modelNodes.append(modelNode)
                self.selectedLabels[poly] = n
                #a = slicer.util.array(tn.GetID())
                #sa = sitk.GetImageFromArray(a)
            for sr in self.summary_reports:
                self.scoreField[sr].setText(self.totalScores[sr])
        else:
            print ("not implemented")
예제 #25
0
    def doit(self):

        labelLogic = self.sliceLogic.GetLabelLayer()
        labelNode = labelLogic.GetVolumeNode()
        labelNodeName = labelNode.GetName()
        labelImage = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(labelNodeName))

        bgLogic = self.sliceLogic.GetBackgroundLayer()
        bgNode = bgLogic.GetVolumeNode()
        bgNodeName = bgNode.GetName()
        bgImage = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(bgNodeName))

        # store a backup copy of the label map for undo
        # (this happens in it's own thread, so it is cheap)
        if self.undoRedo:
            self.undoRedo.saveState()

        labelID = self.editUtil.getLabel()

        l = sitk.BinaryThreshold(labelImage, labelID, labelID, 1, 0)

        filled = sitk.BinaryFillhole(l)

        d = sitk.SignedMaurerDistanceMap(filled,
                                         insideIsPositive=False,
                                         squaredDistance=False,
                                         useImageSpacing=True)
        del filled

        d = sitk.Threshold(d, -1e23, 0, 0)
        feature = d

        if (self.splitSize != 0.0):
            # the splitSize is divided by 2 to convert from a diameter size of a radius size
            level = self.splitSize * 0.5
            d = sitk.HMinima(feature, height=level, fullyConnected=False)

        markers = sitk.RegionalMinima(d,
                                      backgroundValue=0,
                                      foregroundValue=1,
                                      fullyConnected=False,
                                      flatIsMinima=True)
        del d

        markers = sitk.ConnectedComponent(markers, fullyConnected=False)

        ws = sitk.MorphologicalWatershedFromMarkers(feature,
                                                    markers,
                                                    markWatershedLine=False)
        del feature
        del markers

        ws = sitk.Mask(sitk.Cast(ws, labelImage.GetPixelIDValue()), l)
        del l

        sitk.WriteImage(ws,
                        sitkUtils.GetSlicerITKReadWriteAddress(labelNodeName))
        labelNode.GetImageData().Modified()
        labelNode.Modified()
    def refineLandmark(self, state):
        """Refine the specified landmark"""
        # Refine landmark, or if none, do nothing
        #     Crop images around the fiducial
        #     Affine registration of the cropped images
        #     Transform the fiducial using the transformation
        #
        # No need to take into account the current transformation because landmarks are in World RAS
        timing = False
        if self.VerboseMode == "Verbose":
            timing = True

        if state.fixed == None or state.moving == None or state.fixedFiducials == None or state.movingFiducials == None or state.currentLandmarkName == None:
            print "Cannot refine landmarks. Images or landmarks not selected."
            return

        print("Refining landmark " +
              state.currentLandmarkName) + " using " + self.name

        start = time.time()
        if timing: loadStart = start

        volumes = (state.fixed, state.moving)
        (fixedVolume, movingVolume) = volumes

        fixedImage = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(fixedVolume.GetName()))
        movingImage = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(movingVolume.GetName()))

        if timing:
            print 'Time for loading was ' + str(time.time() -
                                                loadStart) + ' seconds'

        landmarks = state.logic.landmarksForVolumes(volumes)

        (fixedFiducial, movingFiducial) = landmarks[state.currentLandmarkName]

        (fixedList, fixedIndex) = fixedFiducial
        (movingList, movingIndex) = movingFiducial

        fixedPoint = [
            0,
        ] * 3
        movingPoint = [
            0,
        ] * 3

        fixedList.GetNthFiducialPosition(fixedIndex, fixedPoint)
        movingList.GetNthFiducialPosition(movingIndex, movingPoint)

        # HACK transform from RAS to LPS
        fixedPoint = [-fixedPoint[0], -fixedPoint[1], fixedPoint[2]]
        movingPoint = [-movingPoint[0], -movingPoint[1], movingPoint[2]]

        # NOTE: SimpleITK index always starts at 0

        # define an roi for the fixed
        if timing: roiStart = time.time()
        fixedRadius = 30
        fixedROISize = [
            0,
        ] * 3
        fixedROIIndex = [
            0,
        ] * 3
        fixedROIIndex = list(
            fixedImage.TransformPhysicalPointToIndex(fixedPoint))
        for i in range(3):
            if fixedROIIndex[i] < 0 or fixedROIIndex[i] > fixedImage.GetSize(
            )[i] - 1:
                import sys
                sys.stderr.write(
                    "Fixed landmark {0} in not with in fixed image!\n".format(
                        landmarkName))
                return
            radius = min(fixedRadius, fixedROIIndex[i],
                         fixedImage.GetSize()[i] - fixedROIIndex[i] - 1)
            fixedROISize[i] = radius * 2 + 1
            fixedROIIndex[i] -= radius
        if self.VerboseMode == "Full Verbose":
            print "Fixed ROI: ", fixedROIIndex, fixedROISize
        if timing: roiEnd = time.time()

        # crop the fixed
        if timing: cropStart = time.time()
        croppedFixedImage = sitk.RegionOfInterest(fixedImage, fixedROISize,
                                                  fixedROIIndex)
        croppedFixedImage = sitk.Cast(croppedFixedImage, sitk.sitkFloat32)
        if timing: cropEnd = time.time()

        # define an roi for the moving
        if timing: roi2Start = time.time()
        if self.LocalSimpleITKMode == "Small":
            movingRadius = 45
        else:
            movingRadius = 60
        movingROISize = [
            0,
        ] * 3
        movingROIIndex = [
            0,
        ] * 3
        movingROIIndex = list(
            movingImage.TransformPhysicalPointToIndex(movingPoint))
        for i in range(3):
            if movingROIIndex[i] < 0 or movingROIIndex[
                    i] > movingImage.GetSize()[i] - 1:
                import sys
                sys.stderr.write(
                    "Moving landmark {0} in not with in moving image!\n".
                    format(landmarkName))
                return
            radius = min(movingRadius, movingROIIndex[i],
                         movingImage.GetSize()[i] - movingROIIndex[i] - 1)
            movingROISize[i] = radius * 2 + 1
            movingROIIndex[i] -= radius
        if self.VerboseMode == "Full Verbose":
            print "Moving ROI: ", movingROIIndex, movingROISize
        if timing: roi2End = time.time()

        if timing: crop2Start = time.time()
        croppedMovingImage = sitk.RegionOfInterest(movingImage, movingROISize,
                                                   movingROIIndex)
        croppedMovingImage = sitk.Cast(croppedMovingImage, sitk.sitkFloat32)
        if timing: crop2End = time.time()

        if timing:
            print 'Time to set up fixed ROI was ' + str(roiEnd -
                                                        roiStart) + ' seconds'
        if timing:
            print 'Time to set up moving ROI was ' + str(
                roi2End - roi2Start) + ' seconds'
        if timing:
            print 'Time to crop fixed volume ' + str(cropEnd -
                                                     cropStart) + ' seconds'
        if timing:
            print 'Time to crop moving volume ' + str(crop2End -
                                                      crop2Start) + ' seconds'

        # initialize the registration
        if timing: initTransformStart = time.time()
        tx = sitk.CenteredTransformInitializer(
            croppedFixedImage, croppedMovingImage,
            sitk.VersorRigid3DTransform(),
            sitk.CenteredTransformInitializerFilter.GEOMETRY)
        if timing: initTransformEnd = time.time()
        if timing:
            print 'Time to initialize transformation was ' + str(
                initTransformEnd - initTransformStart) + ' seconds'

        # define the registration
        R = sitk.ImageRegistrationMethod()
        R.SetMetricAsMattesMutualInformation(numberOfHistogramBins=50)
        R.SetMetricSamplingPercentage(0.2)
        R.SetMetricSamplingStrategy(sitk.ImageRegistrationMethod.RANDOM)
        R.SetOptimizerAsRegularStepGradientDescent(learningRate=1,
                                                   minStep=0.1,
                                                   relaxationFactor=0.5,
                                                   numberOfIterations=250)
        R.SetOptimizerScalesFromJacobian(
        )  # Use this for versor based transforms
        R.SetShrinkFactorsPerLevel([1])
        R.SetSmoothingSigmasPerLevel([1])
        R.SetInitialTransform(tx)
        R.SetInterpolator(sitk.sitkLinear)

        #R.SetNumberOfThreads(1)

        # setup an observer
        def command_iteration(method):
            print("{0:3} = {1:10.5f} : {2}".format(
                method.GetOptimizerIteration(), method.GetMetricValue(),
                method.GetOptimizerPosition()))

        if self.VerboseMode == "Full Verbose":
            R.AddCommand(sitk.sitkIterationEvent, lambda: command_iteration(R))

        # run the registration
        if timing: regStart = time.time()

        outTx = R.Execute(croppedFixedImage, croppedMovingImage)

        if self.VerboseMode == "Full Verbose":
            print("-------")
            print(outTx)
            print("Optimizer stop condition: {0}".format(
                R.GetOptimizerStopConditionDescription()))
            print(" Iteration: {0}".format(R.GetOptimizerIteration()))
            print(" Metric value: {0}".format(R.GetMetricValue()))

        if timing: regEnd = time.time()
        if timing:
            print 'Time for local registration was ' + str(
                regEnd - regStart) + ' seconds'

        # apply the local transform to the landmark
        #print transform

        if timing: resultStart = time.time()
        #outTx.SetInverse()
        updatedPoint = outTx.TransformPoint(fixedPoint)

        # HACK transform from LPS to RAS
        updatedPoint = [-updatedPoint[0], -updatedPoint[1], updatedPoint[2]]
        movingList.SetNthFiducialPosition(movingIndex, updatedPoint[0],
                                          updatedPoint[1], updatedPoint[2])
        if timing: resultEnd = time.time()
        if timing:
            print 'Time for transforming landmark was ' + str(
                resultEnd - resultStart) + ' seconds'

        end = time.time()
        print 'Refined landmark ' + state.currentLandmarkName + ' in ' + str(
            end - start) + ' seconds'
예제 #27
0
 def run(self, dockerPath, dockerVolumePath, inputVolume):
     """
 Run the actual algorithm
 """
     qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor)
     if not self.isValidInputOutputData(inputVolume):
         slicer.util.errorDisplay(
             'Input volume is the same as output vessel model. Choose a different output vessel model.'
         )
         return False
     slicer.app.processEvents()
     fileList = os.listdir(dockerVolumePath)
     for fileName in fileList:
         os.remove(os.path.join(dockerVolumePath, fileName))
     oriVolumeDim = inputVolume.GetImageData().GetDimensions()
     inputVolumeSpacing = inputVolume.GetSpacing()
     spacing = (inputVolumeSpacing[0] * oriVolumeDim[0] / self.DOCKERVOLUMEDIMENSION[0], \
                inputVolumeSpacing[1] * oriVolumeDim[1] / self.DOCKERVOLUMEDIMENSION[1], \
               inputVolumeSpacing[2] * oriVolumeDim[2] / self.DOCKERVOLUMEDIMENSION[2])
     self.resampledVolume = self.ResampleVolume(inputVolume, spacing,
                                                self.resampledVolume)
     img = sitk.ReadImage(
         sitkUtils.GetSlicerITKReadWriteAddress(
             self.resampledVolume.GetName()))
     fileName = "quarterVolume.nii.gz"
     sitk.WriteImage(img, str(os.path.join(dockerVolumePath, fileName)))
     #-----------------------------------
     logging.info('Processing started')
     cmd = list()
     cmd.append(dockerPath)
     cmd.extend(('run', '-t', '-v'))
     cmd.append(str(dockerVolumePath) + ':' + "/workspace/data/Case1")
     cmd.append(
         'li3igtlab/brain-vessel-seg@sha256:2095141606837f364a857ec90a19efe49f8879918881a24a4cf0e72c74a2c2d2'
     )
     cmd.extend(('python3', '/workspace/NiftyNet/net_run.py', 'inference'))
     cmd.extend(('-a', 'brainVesselSegApp.brainVesselSegApp', '-c',
                 '/workspace/data/vesselSeg.ini'))
     p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
     print cmd
     progress = 0
     while True:
         progress += 0.15
         slicer.app.processEvents()
         line = p.stdout.readline()
         if not line:
             print "no line"
             break
         print(line)
     slicer.app.processEvents()
     successful, probabilityMap = slicer.util.loadVolume(os.path.join(
         dockerVolumePath, "Case1__niftynet_out.nii.gz"),
                                                         returnNode=True)
     if successful and probabilityMap:
         inputVolumeSpacing = probabilityMap.GetSpacing()
         spacing = (inputVolumeSpacing[0] * self.DOCKERVOLUMEDIMENSION[0] / oriVolumeDim[0] , \
                    inputVolumeSpacing[1] * self.DOCKERVOLUMEDIMENSION[1] / oriVolumeDim[1] , \
                    inputVolumeSpacing[2] * self.DOCKERVOLUMEDIMENSION[2] / oriVolumeDim[2] )
         probabilityMap_resampled = self.ResampleVolume(
             probabilityMap, spacing, resampledVolume=None)
         probabilityMap_resampled.SetName("ProbabilityMap_Resampled")
         slicer.mrmlScene.AddNode(probabilityMap_resampled)
         inputVolume.SetAttribute(self.REL_PROBABLITYMAP,
                                  probabilityMap_resampled.GetID())
     logging.info('Processing completed')
     qt.QApplication.restoreOverrideCursor()
     return True
    def run(self, leftVol, rightVol, enableScreenshots=0):
        """
    Run the actual algorithm
    """
        logging.info('Processing started')

        nodeName = "BlankVolume"
        imageSize = [390, 466, 318]
        voxelType = vtk.VTK_UNSIGNED_CHAR
        imageOrigin = [98, 98, -72]
        imageSpacing = [0.5, 0.5, 0.5]
        imageDirections = [[-1, 0, 0], [0, -1, 0], [0, 0, 1]]
        fillVoxelValue = 255
        # Create an empty image volume, filled with fillVoxelValue
        imageData = vtk.vtkImageData()
        imageData.SetDimensions(imageSize)
        imageData.AllocateScalars(voxelType, 1)
        thresholder = vtk.vtkImageThreshold()
        thresholder.SetInputData(imageData)
        thresholder.SetInValue(fillVoxelValue)
        thresholder.SetOutValue(fillVoxelValue)
        thresholder.Update()
        # Create volume node
        blankVolumeNode = slicer.mrmlScene.AddNewNodeByClass(
            "vtkMRMLScalarVolumeNode", nodeName)
        blankVolumeNode.SetOrigin(imageOrigin)
        blankVolumeNode.SetSpacing(imageSpacing)
        blankVolumeNode.SetIJKToRASDirections(imageDirections)
        blankVolumeNode.SetAndObserveImageData(thresholder.GetOutput())
        blankVolumeNode.CreateDefaultDisplayNodes()
        blankVolumeNode.CreateDefaultStorageNode()
        logging.info('Created empty volume Blank Volume')

        # left right front back bottom top
        leftData = leftVol.GetPolyData().GetPoints().GetBounds()
        rightData = rightVol.GetPolyData().GetPoints().GetBounds()
        leftBound = leftData[0]
        rightBound = rightData[1]
        topBound = max(leftData[5], rightData[5])
        frontBound = min(leftData[2], rightData[2])
        backBound = max(leftData[3], rightData[3])
        midline = (leftBound + rightBound) / 2
        halfway = -(backBound + frontBound) / 1.7
        print(leftBound, rightBound)
        print("Midline:", midline)
        print(frontBound, backBound)
        print("Halfway:", halfway)
        print("Top:", topBound)

        # handleNode.SetAndObservePolyData(handle.GetOutput())
        # handleNode.CreateDefaultDisplayNodes()
        def makeHandle():
            fn = vtk.vtkParametricTorus()
            fn.SetRingRadius((rightBound - leftBound) / 5)
            fn.SetCrossSectionRadius((rightBound - leftBound) / 15)
            #vtk.FlipNormalsOn()
            source = vtk.vtkParametricFunctionSource()
            source.SetParametricFunction(fn)
            source.Update()

            trans = vtk.vtkTransform()
            trans.RotateX(90)
            trans.Translate(midline, topBound + 5, halfway)
            # vtk generate normals
            # communicate with SLACK
            rotate = vtk.vtkTransformPolyDataFilter()
            rotate.SetTransform(trans)
            rotate.SetInputConnection(source.GetOutputPort())
            rotate.Update()

            return rotate.GetOutput()

        handleVol = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelNode',
                                                       "handle")
        handle = makeHandle()
        handleVol.SetAndObservePolyData(handle)
        handleVol.CreateDefaultDisplayNodes()
        handleVol.CreateDefaultStorageNode()

        leftBLM = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLLabelMapVolumeNode', "leftBLM")
        # leftBLM.CreateDefaultDisplayNodes()
        # leftBLM.CreateDefaultStorageNode()

        rightBLM = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLLabelMapVolumeNode', "rightBLM")
        # rightBLM.CreateDefaultDisplayNodes()
        # rightBLM.CreateDefaultStorageNode()

        handleBLM = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLLabelMapVolumeNode', "handleBLM")
        # handleBLM.CreateDefaultDisplayNodes()
        # handleBLM.CreateDefaultStorageNode()

        leftParams = {
            'sampleDistance': 0.1,
            'InputVolume': blankVolumeNode.GetID(),
            'surface': leftVol.GetID(),
            'OutputVolume': leftBLM.GetID()
        }
        process = slicer.cli.run(slicer.modules.modeltolabelmap,
                                 None,
                                 leftParams,
                                 wait_for_completion=True)

        rightParams = {
            'sampleDistance': 0.1,
            'InputVolume': blankVolumeNode.GetID(),
            'surface': rightVol.GetID(),
            'OutputVolume': rightBLM.GetID()
        }
        process = slicer.cli.run(slicer.modules.modeltolabelmap,
                                 None,
                                 rightParams,
                                 wait_for_completion=True)

        # we have leftBLM, rightBLM, and handleBLM; all are binary label maps
        brainBLM = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLLabelMapVolumeNode', "brainBLM")
        # brainBLM.CreateDefaultDisplayNodes()
        # brainBLM.CreateDefaultStorageNode()

        path = slicer.util.tempDirectory("saves")
        leftPath = path + "/left.nrrd"
        rightPath = path + "/right.nrrd"

        slicer.util.saveNode(leftBLM, leftPath)
        slicer.util.saveNode(rightBLM, rightPath)

        left = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(leftBLM.GetName()))
        right = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(rightBLM.GetName()))

        orFilter = sitk.OrImageFilter()
        brain = orFilter.Execute(right, left)

        dilateFilter = sitk.BinaryDilateImageFilter()
        rad = round((rightBound - leftBound) / 30)
        dilateFilter.SetKernelRadius(rad)
        dilateFilter.SetBackgroundValue(0)
        dilateFilter.SetForegroundValue(255)
        print(dilateFilter.GetKernelType(), dilateFilter.GetKernelRadius())

        brain_dilated = dilateFilter.Execute(brain)

        holesFilter = sitk.BinaryFillholeImageFilter()
        brain_dilated_fixed = holesFilter.Execute(brain_dilated, True, 255)
        #output = orFilter.Execute(intermediate, handle)

        sitkUtils.PushToSlicer(brain_dilated_fixed,
                               "combined sides",
                               compositeView=0,
                               overwrite=False)
        slicer.mrmlScene.RemoveNode(leftBLM)
        slicer.mrmlScene.RemoveNode(rightBLM)
        slicer.mrmlScene.RemoveNode(handleBLM)
        slicer.mrmlScene.RemoveNode(brainBLM)
        slicer.mrmlScene.RemoveNode(blankVolumeNode)

        # Capture screenshot
        if enableScreenshots:
            self.takeScreenshot('MySlicerExtensionTest-Start', 'MyScreenshot',
                                -1)

        logging.info('Processing completed')

        return True
예제 #29
0
    def run(self, leftVol, rightVol, enableScreenshots=0):
        """
    Run the actual algorithm
    """
        logging.info('Processing started')

        nodeName = "BlankVolume"
        imageSize = [390, 466, 318]
        voxelType = vtk.VTK_UNSIGNED_CHAR
        imageOrigin = [98, 98, -72]
        imageSpacing = [0.5, 0.5, 0.5]
        imageDirections = [[-1, 0, 0], [0, -1, 0], [0, 0, 1]]
        fillVoxelValue = 255
        # Create an empty image volume, filled with fillVoxelValue
        imageData = vtk.vtkImageData()
        imageData.SetDimensions(imageSize)
        imageData.AllocateScalars(voxelType, 1)
        thresholder = vtk.vtkImageThreshold()
        thresholder.SetInputData(imageData)
        thresholder.SetInValue(fillVoxelValue)
        thresholder.SetOutValue(fillVoxelValue)
        thresholder.Update()
        # Create volume node
        blankVolumeNode = slicer.mrmlScene.AddNewNodeByClass(
            "vtkMRMLScalarVolumeNode", nodeName)
        blankVolumeNode.SetOrigin(imageOrigin)
        blankVolumeNode.SetSpacing(imageSpacing)
        blankVolumeNode.SetIJKToRASDirections(imageDirections)
        blankVolumeNode.SetAndObserveImageData(thresholder.GetOutput())
        blankVolumeNode.CreateDefaultDisplayNodes()
        blankVolumeNode.CreateDefaultStorageNode()
        logging.info('Created empty volume Blank Volume')

        # left right front back bottom top
        leftData = leftVol.GetPolyData().GetPoints().GetBounds()
        rightData = rightVol.GetPolyData().GetPoints().GetBounds()
        leftBound = leftData[0]
        rightBound = rightData[1]
        topBound = max(leftData[5], rightData[5])
        frontBound = min(leftData[2], rightData[2])
        backBound = max(leftData[3], rightData[3])
        midline = (leftBound + rightBound) / 2
        halfway = -(backBound + frontBound) / 1.7
        print(leftBound, rightBound)
        # medial could be constant zero but why not account for lateral brain asymmetry
        print("Medial:", midline)
        print("Coronal:", halfway)
        print("Top Bound:", topBound)

        # function for creating solid taurus and positioning using coronal/medial/top bound measurements
        def makeHandle():
            fn = vtk.vtkParametricTorus()
            # scale radius by a factor of the brain width
            fn.SetRingRadius((rightBound - leftBound) / 5)
            fn.SetCrossSectionRadius((rightBound - leftBound) / 15)

            source = vtk.vtkParametricFunctionSource()
            source.SetParametricFunction(fn)
            source.Update()

            trans = vtk.vtkTransform()
            trans.RotateX(90)
            # add a bit extra to top bound so it sticks out
            trans.Translate(midline, topBound + 5, halfway)

            rotate = vtk.vtkTransformPolyDataFilter()
            rotate.SetTransform(trans)
            rotate.SetInputConnection(source.GetOutputPort())
            rotate.Update()

            return rotate.GetOutput()

        handleVol = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelNode',
                                                       "handle")
        handle = makeHandle()
        handleVol.SetAndObservePolyData(handle)
        handleVol.CreateDefaultDisplayNodes()
        handleVol.CreateDefaultStorageNode()

        # add nodes to scene
        leftBLM = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLLabelMapVolumeNode', "leftBLM")
        rightBLM = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLLabelMapVolumeNode', "rightBLM")
        handleBLM = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLLabelMapVolumeNode', "handleBLM")

        # manually create parameters for the left and right maps for ModelToLabelMap module
        leftParams = {
            'sampleDistance': 0.1,
            'InputVolume': blankVolumeNode.GetID(),
            'surface': leftVol.GetID(),
            'OutputVolume': leftBLM.GetID()
        }
        process = slicer.cli.run(slicer.modules.modeltolabelmap,
                                 None,
                                 leftParams,
                                 wait_for_completion=True)

        rightParams = {
            'sampleDistance': 0.1,
            'InputVolume': blankVolumeNode.GetID(),
            'surface': rightVol.GetID(),
            'OutputVolume': rightBLM.GetID()
        }
        process = slicer.cli.run(slicer.modules.modeltolabelmap,
                                 None,
                                 rightParams,
                                 wait_for_completion=True)

        # we have leftBLM, rightBLM, and handleBLM; all are binary label maps
        brainBLM = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLLabelMapVolumeNode', "brainBLM")

        path = slicer.util.tempDirectory("saves")
        leftPath = path + "/left.nrrd"
        rightPath = path + "/right.nrrd"

        slicer.util.saveNode(leftBLM, leftPath)
        slicer.util.saveNode(rightBLM, rightPath)

        # move to simple itk in order to Or function the binary label maps
        # look into doing this manually by looping thru voxels and bitwise oring them maybe?
        left = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(leftBLM.GetName()))
        right = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(rightBLM.GetName()))

        orFilter = sitk.OrImageFilter()
        brain = orFilter.Execute(right, left)

        # dilate the image to increase structural integrity of the 3D printed Model and make it more aesthetic
        dilateFilter = sitk.BinaryDilateImageFilter()
        rad = round((rightBound - leftBound) / 30)
        dilateFilter.SetKernelRadius(rad)
        dilateFilter.SetBackgroundValue(0)
        dilateFilter.SetForegroundValue(255)
        print(dilateFilter.GetKernelType(), dilateFilter.GetKernelRadius())

        brain_dilated = dilateFilter.Execute(brain)

        holesFilter = sitk.BinaryFillholeImageFilter()
        brain_dilated_fixed = holesFilter.Execute(brain_dilated, True, 255)

        # push SimpleITK back to Slicer and clean up the extra nodes
        sitkUtils.PushToSlicer(brain_dilated_fixed,
                               "combined sides",
                               compositeView=0,
                               overwrite=False)
        slicer.mrmlScene.RemoveNode(leftBLM)
        slicer.mrmlScene.RemoveNode(rightBLM)
        slicer.mrmlScene.RemoveNode(handleBLM)
        slicer.mrmlScene.RemoveNode(brainBLM)
        slicer.mrmlScene.RemoveNode(blankVolumeNode)

        # TODO: convert to a different type so that it's ready to go with 3D printing, makes it easier when running on a batch of .nrrd files

        # Capture screenshot
        if enableScreenshots:
            self.takeScreenshot('MySlicerExtensionTest-Start', 'MyScreenshot',
                                -1)

        logging.info('Processing completed')

        return True