Ejemplo n.º 1
0
 def selectParameterNode(self):
   # Select parameter set node if one is found in the scene, and create one otherwise
   segmentEditorSingletonTag = "SegmentEditor"
   segmentEditorNode = slicer.mrmlScene.GetSingletonNode(segmentEditorSingletonTag, "vtkMRMLSegmentEditorNode")
   if segmentEditorNode is None:
     segmentEditorNode = slicer.vtkMRMLSegmentEditorNode()
     segmentEditorNode.SetSingletonTag(segmentEditorSingletonTag)
     segmentEditorNode = slicer.mrmlScene.AddNode(segmentEditorNode)
   if self.parameterSetNode == segmentEditorNode:
     # nothing changed
     return
   self.parameterSetNode = segmentEditorNode
   self.editor.setMRMLSegmentEditorNode(self.parameterSetNode)
  def test_ScriptedSegmentEditorEffectModuleTemplate1(self):
    """
    Basic automated test of the segmentation method:
    - Create segmentation by placing sphere-shaped seeds
    - Run segmentation
    - Verify results using segment statistics
    The test can be executed from SelfTests module (test name: SegmentEditorScriptedSegmentEditorEffectModuleTemplate)
    """

    self.delayDisplay("Starting test_ScriptedSegmentEditorEffectModuleTemplate1")

    import vtkSegmentationCorePython as vtkSegmentationCore
    import vtkSlicerSegmentationsModuleLogicPython as vtkSlicerSegmentationsModuleLogic
    import SampleData
    from SegmentStatistics import SegmentStatisticsLogic

    ##################################
    self.delayDisplay("Load master volume")

    import SampleData
    sampleDataLogic = SampleData.SampleDataLogic()
    masterVolumeNode = sampleDataLogic.downloadMRBrainTumor1()

    ##################################
    self.delayDisplay("Create segmentation containing a few spheres")

    segmentationNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLSegmentationNode")
    segmentationNode.CreateDefaultDisplayNodes()
    segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(masterVolumeNode)

    # Segments are defined by a list of: name and a list of sphere [radius, posX, posY, posZ]
    segmentGeometries = [
      ['Tumor', [[10, -6,30,28]]],
      ['Background', [[10, 0,65,22], [15, 1, -14, 30], [12, 0, 28, -7], [5, 0,30,54], [12, 31, 33, 27], [17, -42, 30, 27], [6, -2,-17,71]]],
      ['Air', [[10, 76,73,0], [15, -70,74,0]]] ]
    for segmentGeometry in segmentGeometries:
      segmentName = segmentGeometry[0]
      appender = vtk.vtkAppendPolyData()
      for sphere in segmentGeometry[1]:
        sphereSource = vtk.vtkSphereSource()
        sphereSource.SetRadius(sphere[0])
        sphereSource.SetCenter(sphere[1], sphere[2], sphere[3])
        appender.AddInputConnection(sphereSource.GetOutputPort())
      segment = vtkSegmentationCore.vtkSegment()
      segment.SetName(segmentationNode.GetSegmentation().GenerateUniqueSegmentID(segmentName))
      appender.Update()
      segment.AddRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName(), appender.GetOutput())
      segmentationNode.GetSegmentation().AddSegment(segment)

    ##################################
    self.delayDisplay("Create segment editor")

    segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
    segmentEditorWidget.show()
    segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
    segmentEditorNode = slicer.vtkMRMLSegmentEditorNode()
    slicer.mrmlScene.AddNode(segmentEditorNode)
    segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
    segmentEditorWidget.setSegmentationNode(segmentationNode)
    segmentEditorWidget.setMasterVolumeNode(masterVolumeNode)

    ##################################
    self.delayDisplay("Run segmentation")
    segmentEditorWidget.setActiveEffectByName("ScriptedSegmentEditorEffectModuleTemplate")
    effect = segmentEditorWidget.activeEffect()
    effect.setParameter("ObjectScaleMm", 3.0)
    effect.self().onApply()

    ##################################
    self.delayDisplay("Make segmentation results nicely visible in 3D")
    segmentationDisplayNode = segmentationNode.GetDisplayNode()
    segmentationDisplayNode.SetSegmentVisibility("Air", False)
    segmentationDisplayNode.SetSegmentOpacity3D("Background",0.5)

    ##################################
    self.delayDisplay("Compute statistics")

    segStatLogic = SegmentStatisticsLogic()
    segStatLogic.computeStatistics(segmentationNode, masterVolumeNode)

    # Export results to table (just to see all results)
    resultsTableNode = slicer.vtkMRMLTableNode()
    slicer.mrmlScene.AddNode(resultsTableNode)
    segStatLogic.exportToTable(resultsTableNode)
    segStatLogic.showTable(resultsTableNode)

    self.delayDisplay("Check a few numerical results")
    self.assertEqual( round(segStatLogic.statistics["Tumor","LM volume cc"]), 16)
    self.assertEqual( round(segStatLogic.statistics["Background","LM volume cc"]), 3010)

    self.delayDisplay('test_ScriptedSegmentEditorEffectModuleTemplate1 passed')
    def test_SurfaceCut1(self):
        """
    Basic automated test of the segmentation method:
    - Create segmentation by placing sphere-shaped seeds
    - Run segmentation
    - Verify results using segment statistics
    The test can be executed from SelfTests module (test name: SegmentEditorSurfaceCut)
    """

        self.delayDisplay("Starting test_SurfaceCut1")

        import vtkSegmentationCorePython as vtkSegmentationCore
        import vtkSlicerSegmentationsModuleLogicPython as vtkSlicerSegmentationsModuleLogic
        import SampleData
        from SegmentStatistics import SegmentStatisticsLogic

        ##################################
        self.delayDisplay("Load master volume")

        import SampleData
        sampleDataLogic = SampleData.SampleDataLogic()
        masterVolumeNode = sampleDataLogic.downloadMRBrainTumor1()

        ##################################
        self.delayDisplay("Create segmentation containing a few spheres")

        segmentationNode = slicer.vtkMRMLSegmentationNode()
        slicer.mrmlScene.AddNode(segmentationNode)
        segmentationNode.CreateDefaultDisplayNodes()
        segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(
            masterVolumeNode)

        # Segments are defined by a list of: name and a list of sphere [radius, posX, posY, posZ]
        segmentGeometries = [['Tumor', [[10, -6, 30, 28]]],
                             [
                                 'Background',
                                 [[10, 0, 65, 22], [15, 1, -14, 30],
                                  [12, 0, 28, -7], [5, 0, 30, 54],
                                  [12, 31, 33, 27], [17, -42, 30, 27],
                                  [6, -2, -17, 71]]
                             ], ['Air', [[10, 76, 73, 0], [15, -70, 74, 0]]]]
        for segmentGeometry in segmentGeometries:
            segmentName = segmentGeometry[0]
            appender = vtk.vtkAppendPolyData()
            for sphere in segmentGeometry[1]:
                sphereSource = vtk.vtkSphereSource()
                sphereSource.SetRadius(sphere[0])
                sphereSource.SetCenter(sphere[1], sphere[2], sphere[3])
                appender.AddInputConnection(sphereSource.GetOutputPort())
            segment = vtkSegmentationCore.vtkSegment()
            segment.SetName(
                segmentationNode.GetSegmentation().GenerateUniqueSegmentID(
                    segmentName))
            appender.Update()
            segment.AddRepresentation(
                vtkSegmentationCore.vtkSegmentationConverter.
                GetSegmentationClosedSurfaceRepresentationName(),
                appender.GetOutput())
            segmentationNode.GetSegmentation().AddSegment(segment)

        ##################################
        self.delayDisplay("Create segment editor")

        segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
        segmentEditorWidget.show()
        segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
        segmentEditorNode = slicer.vtkMRMLSegmentEditorNode()
        slicer.mrmlScene.AddNode(segmentEditorNode)
        segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
        segmentEditorWidget.setSegmentationNode(segmentationNode)
        segmentEditorWidget.setMasterVolumeNode(masterVolumeNode)

        ##################################
        self.delayDisplay("Run segmentation")
        segmentEditorWidget.setActiveEffectByName("SurfaceCut")
        effect = segmentEditorWidget.activeEffect()
        effect.setParameter("ObjectScaleMm", 3.0)
        effect.self().onApply()

        ##################################
        self.delayDisplay("Make segmentation results nicely visible in 3D")
        segmentationDisplayNode = segmentationNode.GetDisplayNode()
        segmentationDisplayNode.SetSegmentVisibility("Air", False)
        segmentationDisplayNode.SetSegmentOpacity3D("Background", 0.5)

        ##################################
        self.delayDisplay("Compute statistics")

        segStatLogic = SegmentStatisticsLogic()
        segStatLogic.computeStatistics(segmentationNode, masterVolumeNode)

        # Export results to table (just to see all results)
        resultsTableNode = slicer.vtkMRMLTableNode()
        slicer.mrmlScene.AddNode(resultsTableNode)
        segStatLogic.exportToTable(resultsTableNode)
        segStatLogic.showTable(resultsTableNode)

        self.delayDisplay("Check a few numerical results")
        self.assertEqual(
            round(segStatLogic.statistics["Tumor", "LM volume cc"]), 16)
        self.assertEqual(
            round(segStatLogic.statistics["Background", "LM volume cc"]), 3010)

        self.delayDisplay('test_SurfaceCut1 passed')
Ejemplo n.º 4
0
    def run(self, inputVolume, outputSegmentation, smoothingKernelSize=3.0):
        """
    Run the processing algorithm.
    Can be used without GUI widget.
    :param inputVolume: volume to be segmented
    :param outputSegmentation: segmentation to sore the result in
    :param smoothingKernelSize: this is used for closing small holes in the segmentation
    """

        if not inputVolume or not outputSegmentation:
            raise ValueError("Input volume or output segmentation is invalid")

        logging.info('Processing started')

        # Compute bone threshold value automatically
        import vtkITK
        thresholdCalculator = vtkITK.vtkITKImageThresholdCalculator()
        thresholdCalculator.SetInputData(inputVolume.GetImageData())
        thresholdCalculator.SetMethodToOtsu()
        thresholdCalculator.Update()
        boneThresholdValue = thresholdCalculator.GetThreshold()
        volumeScalarRange = inputVolume.GetImageData().GetScalarRange()
        logging.debug(
            "Volume minimum = {0}, maximum = {1}, bone threshold = {2}".format(
                volumeScalarRange[0], volumeScalarRange[1],
                boneThresholdValue))

        # Set up segmentation
        outputSegmentation.CreateDefaultDisplayNodes()
        outputSegmentation.SetReferenceImageGeometryParameterFromVolumeNode(
            inputVolume)

        # Create segment editor to get access to effects
        segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
        # To show segment editor widget (useful for debugging): segmentEditorWidget.show()
        segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
        if not segmentEditorWidget.effectByName("Wrap Solidify"):
            raise NotImplementedError(
                "SurfaceWrapSolidify extension is required")

        segmentEditorNode = slicer.vtkMRMLSegmentEditorNode()
        slicer.mrmlScene.AddNode(segmentEditorNode)
        segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
        segmentEditorWidget.setSegmentationNode(outputSegmentation)
        segmentEditorWidget.setMasterVolumeNode(inputVolume)

        # Create bone segment by thresholding
        boneSegmentID = outputSegmentation.GetSegmentation().AddEmptySegment(
            "bone")
        segmentEditorNode.SetSelectedSegmentID(boneSegmentID)
        segmentEditorWidget.setActiveEffectByName("Threshold")
        effect = segmentEditorWidget.activeEffect()
        effect.setParameter("MinimumThreshold", str(boneThresholdValue))
        effect.setParameter("MaximumThreshold", str(volumeScalarRange[1]))
        effect.self().onApply()

        # Smooth bone segment (just to reduce solidification computation time)
        segmentEditorWidget.setActiveEffectByName("Smoothing")
        effect = segmentEditorWidget.activeEffect()
        effect.setParameter("SmoothingMethod", "MORPHOLOGICAL_CLOSING")
        effect.setParameter("KernelSizeMm", str(smoothingKernelSize))
        effect.self().onApply()

        # Solidify bone
        segmentEditorWidget.setActiveEffectByName("Wrap Solidify")
        effect = segmentEditorWidget.activeEffect()
        effect.self().onApply()

        # Create segment for cavity within bone region using thresholding
        segmentEditorNode.SetOverwriteMode(
            slicer.vtkMRMLSegmentEditorNode.OverwriteNone)
        segmentEditorNode.SetMaskMode(
            slicer.vtkMRMLSegmentEditorNode.PaintAllowedInsideAllSegments)
        cavitySegmentID = outputSegmentation.GetSegmentation().AddEmptySegment(
            "cavity")
        segmentEditorNode.SetSelectedSegmentID(cavitySegmentID)
        segmentEditorWidget.setActiveEffectByName("Threshold")
        effect = segmentEditorWidget.activeEffect()
        effect.setParameter("MinimumThreshold", str(volumeScalarRange[0]))
        effect.setParameter("MaximumThreshold", str(boneThresholdValue))
        effect.self().onApply()

        # Cavity shrink
        segmentEditorWidget.setActiveEffectByName("Margin")
        effect = segmentEditorWidget.activeEffect()
        effect.setParameter("MarginSizeMm", str(-smoothingKernelSize))
        effect.self().onApply()

        # Find largest cavity
        segmentEditorWidget.setActiveEffectByName("Islands")
        effect = segmentEditorWidget.activeEffect()
        effect.setParameterDefault("Operation", "KEEP_LARGEST_ISLAND")
        effect.self().onApply()

        # Cavity restore
        segmentEditorNode.SetMaskMode(
            slicer.vtkMRMLSegmentEditorNode.PaintAllowedInsideAllSegments
        )  # ensure we don't leak into bone
        segmentEditorWidget.setActiveEffectByName("Margin")
        effect = segmentEditorWidget.activeEffect()
        effect.setParameter("MarginSizeMm", str(smoothingKernelSize))
        effect.self().onApply()

        # Clean up
        slicer.mrmlScene.RemoveNode(segmentEditorNode)
        outputSegmentation.RemoveSegment(boneSegmentID)
        segmentEditorWidget = None

        logging.info('Processing completed')
    def test_WrapSolidify1(self):
        """
    Basic automated test of the segmentation method:
    - Create segmentation by placing sphere-shaped seeds
    - Run segmentation
    - Verify results using segment statistics
    The test can be executed from SelfTests module (test name: SegmentEditorWrapSolidify)
    """

        self.delayDisplay("Starting test_WrapSolidify1")

        import vtkSegmentationCorePython as vtkSegmentationCore
        import vtkSlicerSegmentationsModuleLogicPython as vtkSlicerSegmentationsModuleLogic
        import SampleData
        from SegmentStatistics import SegmentStatisticsLogic

        ##################################
        self.delayDisplay("Load master volume")

        masterVolumeNode = SampleData.downloadSample('MRBrainTumor1')

        ##################################
        self.delayDisplay("Create segmentation containing a two spheres")

        segmentationNode = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLSegmentationNode')
        segmentationNode.CreateDefaultDisplayNodes()
        segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(
            masterVolumeNode)

        features = ["none", "carveCavities", "createShell", "both"]
        spheres = [[20, 5, 5, 5], [20, -5, -5, -5]]
        appender = vtk.vtkAppendPolyData()
        for sphere in spheres:
            sphereSource = vtk.vtkSphereSource()
            sphereSource.SetRadius(sphere[0])
            sphereSource.SetCenter(sphere[1], sphere[2], sphere[3])
            appender.AddInputConnection(sphereSource.GetOutputPort())

        for m in features:
            segmentName = str(m)
            segment = vtkSegmentationCore.vtkSegment()
            segment.SetName(
                segmentationNode.GetSegmentation().GenerateUniqueSegmentID(
                    segmentName))
            appender.Update()
            segment.AddRepresentation(
                vtkSegmentationCore.vtkSegmentationConverter.
                GetSegmentationClosedSurfaceRepresentationName(),
                appender.GetOutput())
            segmentationNode.GetSegmentation().AddSegment(segment)

        ##################################
        self.delayDisplay("Create segment editor")

        segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
        segmentEditorWidget.show()
        segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
        segmentEditorNode = slicer.vtkMRMLSegmentEditorNode()
        slicer.mrmlScene.AddNode(segmentEditorNode)
        segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
        segmentEditorWidget.setSegmentationNode(segmentationNode)
        segmentEditorWidget.setMasterVolumeNode(masterVolumeNode)

        ##################################
        self.delayDisplay("Run WrapSolidify Effect")
        segmentEditorWidget.setActiveEffectByName("Wrap Solidify")
        effect = segmentEditorWidget.activeEffect()

        for t in ["SEGMENTATION", "MODEL"]:
            effect.setParameter("outputType", t)

            self.delayDisplay(
                "Creating Output Type %s, activated feature none" % (t))
            segmentEditorWidget.setCurrentSegmentID(
                segmentationNode.GetSegmentation().GetSegmentIdBySegmentName(
                    'none'))
            effect.setParameter("carveCavities", False)
            effect.setParameter("createShell", False)
            effect.self().onApply()

            self.delayDisplay(
                "Creating Output Type %s, activated feature carveCavities" %
                (t))
            effect.setParameter("carveCavities", True)
            effect.setParameter("createShell", False)
            segmentEditorWidget.setCurrentSegmentID(
                segmentationNode.GetSegmentation().GetSegmentIdBySegmentName(
                    'carveCavities'))
            effect.self().onApply()

            self.delayDisplay(
                "Creating Output Type %s, activated feature createShell" % (t))
            effect.setParameter("carveCavities", False)
            effect.setParameter("createShell", True)
            segmentEditorWidget.setCurrentSegmentID(
                segmentationNode.GetSegmentation().GetSegmentIdBySegmentName(
                    'createShell'))
            effect.self().onApply()

            self.delayDisplay(
                "Creating Output Type %s, activated feature both" % (t))
            effect.setParameter("carveCavities", True)
            effect.setParameter("createShell", True)
            segmentEditorWidget.setCurrentSegmentID(
                segmentationNode.GetSegmentation().GetSegmentIdBySegmentName(
                    'both'))
            effect.self().onApply()

        ##################################
        self.delayDisplay("Creating Segments from Models")
        for m in features:
            model = slicer.util.getNode(m)
            segmentName = "MODEL_%s" % m
            segment = vtkSegmentationCore.vtkSegment()
            segment.SetName(
                segmentationNode.GetSegmentation().GenerateUniqueSegmentID(
                    segmentName))
            segment.SetColor(model.GetDisplayNode().GetColor())
            segment.AddRepresentation(
                vtkSegmentationCore.vtkSegmentationConverter.
                GetSegmentationClosedSurfaceRepresentationName(),
                model.GetPolyData())
            segmentationNode.GetSegmentation().AddSegment(segment)

        ##################################
        self.delayDisplay("Compute statistics")
        segStatLogic = SegmentStatisticsLogic()
        segStatLogic.getParameterNode().SetParameter("Segmentation",
                                                     segmentationNode.GetID())
        segStatLogic.getParameterNode().SetParameter("ScalarVolume",
                                                     masterVolumeNode.GetID())
        segStatLogic.computeStatistics()
        statistics = segStatLogic.getStatistics()

        ##################################
        self.delayDisplay("Check a few numerical results")

        # logging.info(round(statistics["none",'ScalarVolumeSegmentStatisticsPlugin.volume_mm3']))
        # logging.info(round(statistics["MODEL_none",'ScalarVolumeSegmentStatisticsPlugin.volume_mm3']))
        # logging.info(round(statistics["carveCavities",'ScalarVolumeSegmentStatisticsPlugin.volume_mm3']))
        # logging.info(round(statistics["MODEL_carveCavities",'ScalarVolumeSegmentStatisticsPlugin.volume_mm3']))
        # logging.info(round(statistics["createShell",'ScalarVolumeSegmentStatisticsPlugin.volume_mm3']))
        # logging.info(round(statistics["MODEL_createShell",'ScalarVolumeSegmentStatisticsPlugin.volume_mm3']))
        # logging.info(round(statistics["both",'ScalarVolumeSegmentStatisticsPlugin.volume_mm3']))
        # logging.info(round(statistics["MODEL_both",'ScalarVolumeSegmentStatisticsPlugin.volume_mm3']))

        self.assertEqual(
            round(
                statistics["none",
                           'ScalarVolumeSegmentStatisticsPlugin.volume_mm3']),
            46605)
        self.assertEqual(
            round(
                statistics["MODEL_none",
                           'ScalarVolumeSegmentStatisticsPlugin.volume_mm3']),
            46320)

        self.assertEqual(
            round(
                statistics["carveCavities",
                           'ScalarVolumeSegmentStatisticsPlugin.volume_mm3']),
            46605)
        self.assertEqual(
            round(
                statistics["MODEL_carveCavities",
                           'ScalarVolumeSegmentStatisticsPlugin.volume_mm3']),
            46321)

        self.assertEqual(
            round(
                statistics["createShell",
                           'ScalarVolumeSegmentStatisticsPlugin.volume_mm3']),
            9257)
        self.assertEqual(
            round(
                statistics["MODEL_createShell",
                           'ScalarVolumeSegmentStatisticsPlugin.volume_mm3']),
            9230)

        self.assertEqual(
            round(
                statistics["both",
                           'ScalarVolumeSegmentStatisticsPlugin.volume_mm3']),
            9254)
        self.assertEqual(
            round(
                statistics["MODEL_both",
                           'ScalarVolumeSegmentStatisticsPlugin.volume_mm3']),
            9245)

        self.delayDisplay('test_WrapSolidify1 passed')
  def test_SurfaceCut1(self):
    """
    Basic automated test of the segmentation method:
    - Create segmentation by placing fiducials around tumor
    - Apply
    - Verify results using segment statistics
    The test can be executed from SelfTests module (test name: SegmentEditorSurfaceCut)
    """

    self.delayDisplay("Starting test_SurfaceCut1")


    ##################################
    self.delayDisplay("Load master volume")

    import SampleData
    sampleDataLogic = SampleData.SampleDataLogic()
    masterVolumeNode = sampleDataLogic.downloadMRBrainTumor1()

    ##################################
    self.delayDisplay("Create tumor segmentation")

    segmentationNode = slicer.vtkMRMLSegmentationNode()
    slicer.mrmlScene.AddNode(segmentationNode)
    segmentationNode.CreateDefaultDisplayNodes()
    segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(masterVolumeNode)

    segmentName = "Tumor"
    import vtkSegmentationCorePython as vtkSegmentationCore

    segment = vtkSegmentationCore.vtkSegment()
    segment.SetName(segmentationNode.GetSegmentation().GenerateUniqueSegmentID(segmentName))
    segmentationNode.GetSegmentation().AddSegment(segment)

    ##################################
    self.delayDisplay("Create segment editor")

    segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
    segmentEditorWidget.show()
    segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
    segmentEditorNode = slicer.vtkMRMLSegmentEditorNode()
    slicer.mrmlScene.AddNode(segmentEditorNode)
    segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
    segmentEditorWidget.setSegmentationNode(segmentationNode)
    segmentEditorWidget.setMasterVolumeNode(masterVolumeNode)

    ##################################
    self.delayDisplay("Run segmentation")

    segmentEditorWidget.setActiveEffectByName("Surface cut")
    effect = segmentEditorWidget.activeEffect()

    effect.self().fiducialPlacementToggle.placeButton().click()

    points =[[2.589283578714074, 44.60536690073953, 27.299999999999997], [8.515228351086698, 35.22262101114956, 27.299999999999997],
             [13.700430026912741, 25.099132025013006, 27.299999999999997], [5.799170330415919, 19.17318725264039, 27.299999999999997],
             [2.589283578714074, 9.296612632019361, 27.299999999999997], [-10.250263428093263, 12.25958501820567, 27.299999999999997],
             [-16.17620820046588, 18.185529790578286, 27.299999999999997], [-20.373752414229813, 27.568275680168263, 27.299999999999997],
             [-15.929293834950343, 38.679422128366916, 27.299999999999997], [-11.484835255670887, 44.11153816970849, 27.299999999999997],
             [6.539913426962492, 33.49422045254088, 31.499999999999993], [1.354711751136449, 42.383137611099805, 31.499999999999993],
             [-8.768777235000101, 44.35845253522401, 31.499999999999993], [-14.200893276341674, 36.70410720424271, 31.499999999999993],
             [-18.398437490105607, 27.07444694913721, 31.499999999999993], [-12.719407083248512, 16.704043597485132, 31.499999999999993],
             [-7.534205407422476, 11.765756287174618, 31.499999999999993], [0.12013992355882408, 12.25958501820567, 31.499999999999993],
             [5.799170330415919, 16.21021486645408, 31.499999999999993], [8.268313985571176, 21.642330907795646, 31.499999999999993],
             [13.947344392428263, 26.827532583621682, 31.499999999999993], [-3.0897468281430065, 32.50656299047878, 45.49999999999998],
             [2.589283578714074, 27.32136131465274, 45.49999999999998], [-5.3119761177827485, 21.642330907795646, 45.49999999999998],
             [-8.02803413845352, 27.32136131465274, 45.49999999999998], [-14.694722007372718, 30.778162431870093, 38.499999999999986],
             [-8.02803413845352, 12.01267065269014, 38.499999999999986], [-3.583575559174065, 39.66707959042902, 11.900000000000007],
             [3.576941040776184, 31.765819893932196, 11.900000000000007], [0.12013992355882408, 20.901587811249065, 11.900000000000007],
             [-9.26260596603116, 28.555933142230366, 11.900000000000007], [6.046084695931441, 38.432507762851394, 17.500000000000007],
             [-17.163865662527982, 33.7411348180564, 17.500000000000007], [-14.200893276341674, 21.889245273311168, 17.500000000000007]]

    for p in points:
      effect.self().segmentMarkupNode.AddFiducialFromArray(p)

    effect.self().onApply()

    ##################################
    self.delayDisplay("Make segmentation results nicely visible in 3D")
    segmentationDisplayNode = segmentationNode.GetDisplayNode()
    segmentationDisplayNode.SetSegmentVisibility(segmentName, True)
    slicer.util.findChild(segmentEditorWidget, "Show3DButton").checked = True
    segmentationDisplayNode.SetSegmentOpacity3D("Background",0.5)

    ##################################
    self.delayDisplay("Compute statistics")

    from SegmentStatistics import SegmentStatisticsLogic

    segStatLogic = SegmentStatisticsLogic()

    segStatLogic.getParameterNode().SetParameter("Segmentation", segmentationNode.GetID())
    segStatLogic.getParameterNode().SetParameter("ScalarVolume", masterVolumeNode.GetID())
    segStatLogic.getParameterNode().SetParameter("visibleSegmentsOnly", "False")

    segStatLogic.computeStatistics()

    # Export results to table (just to see all results)
    resultsTableNode = slicer.vtkMRMLTableNode()
    slicer.mrmlScene.AddNode(resultsTableNode)
    segStatLogic.exportToTable(resultsTableNode)
    segStatLogic.showTable(resultsTableNode)

    self.delayDisplay("Check a few numerical results")

    stats = segStatLogic.getStatistics()
    self.assertEqual( round(stats['Tumor', 'LabelmapSegmentStatisticsPlugin.volume_mm3']), 19498.0)

    self.delayDisplay('test_SurfaceCut1 passed')
Ejemplo n.º 7
0
    def test_TDIO1(self):
        """
        Basic automated test of the segmentation method:
        - Create segmentation by placing sphere-shaped seeds
        - Run segmentation
        - Verify results using segment statistics
        The test can be executed from SelfTests module (test name: SegmentEditorTDIO)
        """
        self.delayDisplay('Starting test_TDIO1')
        import vtkSegmentationCorePython as vtkSegmentationCore, vtkSlicerSegmentationsModuleLogicPython as vtkSlicerSegmentationsModuleLogic, SampleData
        from SegmentStatistics import SegmentStatisticsLogic
        self.delayDisplay('Load master volume')
        masterVolumeNode = SampleData.downloadSample('MRBrainTumor1')
        self.delayDisplay('Create segmentation containing a few spheres')
        segmentationNode = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLSegmentationNode')
        segmentationNode.CreateDefaultDisplayNodes()
        segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(
            masterVolumeNode)
        segmentGeometries = [['Tumor', [[10, -6, 30, 28]]],
                             [
                                 'Background',
                                 [[10, 0, 65, 22], [15, 1, -14, 30],
                                  [12, 0, 28, -7], [5, 0, 30, 54],
                                  [12, 31, 33, 27], [17, -42, 30, 27],
                                  [6, -2, -17, 71]]
                             ], ['Air', [[10, 76, 73, 0], [15, -70, 74, 0]]]]
        for segmentGeometry in segmentGeometries:
            segmentName = segmentGeometry[0]
            appender = vtk.vtkAppendPolyData()
            for sphere in segmentGeometry[1]:
                sphereSource = vtk.vtkSphereSource()
                sphereSource.SetRadius(sphere[0])
                sphereSource.SetCenter(sphere[1], sphere[2], sphere[3])
                appender.AddInputConnection(sphereSource.GetOutputPort())

            segment = vtkSegmentationCore.vtkSegment()
            segment.SetName(
                segmentationNode.GetSegmentation().GenerateUniqueSegmentID(
                    segmentName))
            appender.Update()
            segment.AddRepresentation(
                vtkSegmentationCore.vtkSegmentationConverter.
                GetSegmentationClosedSurfaceRepresentationName(),
                appender.GetOutput())
            segmentationNode.GetSegmentation().AddSegment(segment)

        self.delayDisplay('Create segment editor')
        segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
        segmentEditorWidget.show()
        segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
        segmentEditorNode = slicer.vtkMRMLSegmentEditorNode()
        slicer.mrmlScene.AddNode(segmentEditorNode)
        segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
        segmentEditorWidget.setSegmentationNode(segmentationNode)
        segmentEditorWidget.setMasterVolumeNode(masterVolumeNode)
        self.delayDisplay('Run segmentation')
        segmentEditorWidget.setActiveEffectByName('TDIO')
        effect = segmentEditorWidget.activeEffect()
        effect.setParameter('ObjectScaleMm', 3.0)
        effect.self().onApply()
        self.delayDisplay('Make segmentation results nicely visible in 3D')
        segmentationDisplayNode = segmentationNode.GetDisplayNode()
        segmentationDisplayNode.SetSegmentVisibility('Air', False)
        segmentationDisplayNode.SetSegmentOpacity3D('Background', 0.5)
        self.delayDisplay('Compute statistics')
        segStatLogic = SegmentStatisticsLogic()
        segStatLogic.computeStatistics(segmentationNode, masterVolumeNode)
        resultsTableNode = slicer.vtkMRMLTableNode()
        slicer.mrmlScene.AddNode(resultsTableNode)
        segStatLogic.exportToTable(resultsTableNode)
        segStatLogic.showTable(resultsTableNode)
        self.delayDisplay('Check a few numerical results')
        self.assertEqual(
            round(segStatLogic.statistics[('Tumor', 'LM volume cc')]), 16)
        self.assertEqual(
            round(segStatLogic.statistics[('Background', 'LM volume cc')]),
            3010)
        self.delayDisplay('test_TDIO1 passed')
Ejemplo n.º 8
0
    def run(self,
            inputVolume,
            outputSegmentation,
            smoothingKernelSize=3.0,
            splitCavitiesDiameter=15.0):
        """
    Run the processing algorithm.
    Can be used without GUI widget.
    :param inputVolume: volume to be segmented
    :param outputSegmentation: segmentation to sore the result in
    :param smoothingKernelSize: this is used for closing small holes in the segmentation
    :param splitCavitiesDiameter: plugs in holes smaller than splitCavitiesDiamater.
    """

        if not inputVolume or not outputSegmentation:
            raise ValueError("Input volume or output segmentation is invalid")

        logging.info('Processing started')

        # Compute bone threshold value automatically
        import vtkITK
        thresholdCalculator = vtkITK.vtkITKImageThresholdCalculator()
        thresholdCalculator.SetInputData(inputVolume.GetImageData())
        # thresholdCalculator.SetMethodToOtsu()  - this does not always work (see for example CTHead example data set)
        thresholdCalculator.SetMethodToMaximumEntropy()
        thresholdCalculator.Update()
        boneThresholdValue = thresholdCalculator.GetThreshold()
        volumeScalarRange = inputVolume.GetImageData().GetScalarRange()
        logging.debug(
            f"Volume minimum = {volumeScalarRange[0]}, maximum = {volumeScalarRange[1]}, bone threshold = {boneThresholdValue}"
        )

        # Set up segmentation
        outputSegmentation.CreateDefaultDisplayNodes()
        outputSegmentation.SetReferenceImageGeometryParameterFromVolumeNode(
            inputVolume)

        # Create segment editor to get access to effects
        segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
        # To show segment editor widget (useful for debugging): segmentEditorWidget.show()
        segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
        if not segmentEditorWidget.effectByName("Wrap Solidify"):
            raise NotImplementedError(
                "SurfaceWrapSolidify extension is required")

        segmentEditorNode = slicer.vtkMRMLSegmentEditorNode()
        slicer.mrmlScene.AddNode(segmentEditorNode)
        segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
        segmentEditorWidget.setSegmentationNode(outputSegmentation)
        segmentEditorWidget.setMasterVolumeNode(inputVolume)

        # Create bone segment by thresholding
        boneSegmentID = outputSegmentation.GetSegmentation().AddEmptySegment(
            "bone")
        segmentEditorNode.SetSelectedSegmentID(boneSegmentID)
        segmentEditorWidget.setActiveEffectByName("Threshold")
        effect = segmentEditorWidget.activeEffect()
        effect.setParameter("MinimumThreshold", str(boneThresholdValue))
        effect.setParameter("MaximumThreshold", str(volumeScalarRange[1]))
        effect.self().onApply()

        # Smooth bone segment (just to reduce solidification computation time)
        segmentEditorWidget.setActiveEffectByName("Smoothing")
        effect = segmentEditorWidget.activeEffect()
        effect.setParameter("SmoothingMethod", "MORPHOLOGICAL_CLOSING")
        effect.setParameter("KernelSizeMm", str(smoothingKernelSize))
        effect.self().onApply()

        # Solidify bone
        segmentEditorWidget.setActiveEffectByName("Wrap Solidify")
        effect = segmentEditorWidget.activeEffect()
        effect.setParameter("region", "largestCavity")
        effect.setParameter("splitCavities",
                            "True" if splitCavitiesDiameter > 0 else "False")
        effect.setParameter("splitCavitiesDiameter",
                            str(splitCavitiesDiameter))  # in mm
        effect.setParameter("outputType", "newSegment")  # in mm
        effect.self().onApply()

        # Clean up
        #slicer.mrmlScene.RemoveNode(segmentEditorNode)
        #outputSegmentation.RemoveSegment(boneSegmentID)
        #segmentEditorWidget = None

        logging.info('Processing completed')
Ejemplo n.º 9
0
            2
        )  # small sphere for small features. Change depending on size of objects in your phantom
        featSeed.Update()
        appendFeat.AddInputData(featSeed.GetOutput())

    appendFeat.Update()

    # add feature segmentation seeds to the segmentationNode. Change the name or colour based on preference.
    segmentationNode.AddSegmentFromClosedSurfaceRepresentation(
        appendFeat.GetOutput(), "Feature", [0.0, 0.0, 1.0])

    # segmentEditorWidget.show() # this is for debugging if you need to!

    slicer.app.processEvents()
    segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
    segmentEditorNode = slicer.vtkMRMLSegmentEditorNode()
    slicer.mrmlScene.AddNode(segmentEditorNode)
    segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
    segmentEditorWidget.setSegmentationNode(segmentationNode)
    segmentEditorWidget.setMasterVolumeNode(masterVolumeNode)

    # grow from seeds
    segmentEditorWidget.setActiveEffectByName("Grow from seeds")
    effect = segmentEditorWidget.activeEffect()
    effect.self().onPreview()

    # for troubleshooting / editing the seed growth, stop before the onApply() function
    effect.self().onApply()

    # grow the background further into the phantom volume segmentation
    # i needed this as my images had a noisy edge to the phantom volume, so it picked up to much noise as phantom volume