def removeIslands(self): # # change the label values based on the parameter node # if not self.sliceLogic: self.sliceLogic = self.editUtil.getSliceLogic() parameterNode = self.editUtil.getParameterNode() minimumSize = int(parameterNode.GetParameter("IslandEffect,minimumSize")) fullyConnected = bool(parameterNode.GetParameter("IslandEffect,fullyConnected")) label = self.editUtil.getLabel() # first, create an inverse binary version of the image # so that islands inside segemented object will be detected, along # with a big island of the background preThresh = vtk.vtkImageThreshold() preThresh.SetInValue( 0 ) preThresh.SetOutValue( 1 ) preThresh.ReplaceInOn() preThresh.ReplaceOutOn() preThresh.ThresholdBetween( label,label ) preThresh.SetInput( self.getScopedLabelInput() ) preThresh.SetOutputScalarTypeToUnsignedLong() # now identify the islands in the inverted volume # and find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() islandMath.SetInput( preThresh.GetOutput() ) islandMath.SetFullyConnected( fullyConnected ) islandMath.SetMinimumSize( minimumSize ) # TODO: $this setProgressFilter $islandMath "Calculating Islands..." islandMath.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount print( "%d islands created (%d ignored)" % (islandCount, ignoredIslands) ) # now rethreshold so that everything which is not background becomes the label postThresh = vtk.vtkImageThreshold() postThresh.SetInValue( label ) postThresh.SetOutValue( 0 ) postThresh.ReplaceInOn() postThresh.ReplaceOutOn() postThresh.ThresholdBetween( 0, 0 ) postThresh.SetOutputScalarTypeToShort() postThresh.SetInput( islandMath.GetOutput() ) postThresh.SetOutput( self.getScopedLabelOutput() ) # TODO $this setProgressFilter $postThresh "Applying to Label Map..." postThresh.Update() self.applyScopedLabel()
def preview(self, color=None, checked = True): """previewsing the result of thresholding""" if not self.editUtil.getBackgroundImage() or not self.editUtil.getLabelImage(): return if not checked: self.cursorActor.VisibilityOff() self.sliceView.scheduleRender() return # # make a lookup table where inside the threshold is opaque and colored # by the label color, while the background is transparent (black) # - apply the threshold operation to the currently visible background # (output of the layer logic's vtkImageReslice instance) # if not color: color = self.getPaintColor if not self.lut: self.lut = vtk.vtkLookupTable() self.lut.SetRampToLinear() self.lut.SetNumberOfTableValues( 2 ) self.lut.SetTableRange( 0, 1 ) self.lut.SetTableValue( 0, 0, 0, 0, 0 ) r,g,b,a = color self.lut.SetTableValue( 1, r, g, b, a ) if not self.map: self.map = vtk.vtkImageMapToRGBA() self.map.SetOutputFormatToRGBA() self.map.SetLookupTable( self.lut ) if not self.thresh: self.thresh = vtk.vtkImageThreshold() sliceLogic = self.sliceWidget.sliceLogic() backgroundLogic = sliceLogic.GetBackgroundLayer() if vtk.VTK_MAJOR_VERSION <= 5: self.thresh.SetInput( backgroundLogic.GetReslice().GetOutput() ) else: self.thresh.SetInputConnection( backgroundLogic.GetReslice().GetOutputPort() ) self.thresh.ThresholdBetween( self.min, self.max ) self.thresh.SetInValue( 1 ) self.thresh.SetOutValue( 0 ) self.thresh.SetOutputScalarTypeToUnsignedChar() if vtk.VTK_MAJOR_VERSION <= 5: self.map.SetInput( self.thresh.GetOutput() ) self.map.Update() self.cursorMapper.SetInput( self.map.GetOutput() ) else: self.map.SetInputConnection( self.thresh.GetOutputPort() ) self.cursorMapper.SetInputConnection( self.map.GetOutputPort() ) self.cursorActor.VisibilityOn() self.sliceView.scheduleRender()
def initializeNewLabel(newLabel, sourceVolume): displayNode = slicer.mrmlScene.AddNode( slicer.vtkMRMLLabelMapVolumeDisplayNode()) threshold = vtk.vtkImageThreshold() threshold.ReplaceInOn() threshold.ReplaceOutOn() threshold.SetInValue(0) threshold.SetOutValue(0) threshold.SetOutputScalarTypeToUnsignedShort() threshold.SetInput(sourceVolume.GetImageData()) threshold.Update() labelImage = vtk.vtkImageData() labelImage.DeepCopy(threshold.GetOutput()) newLabel.SetAndObserveStorageNodeID(None) newLabel.SetLabelMap(1) newLabel.CopyOrientation(sourceVolume) ras2ijk = vtk.vtkMatrix4x4() sourceVolume.GetRASToIJKMatrix(ras2ijk) newLabel.SetRASToIJKMatrix(ras2ijk) newLabel.SetAttribute('AssociatedNodeID', sourceVolume.GetID()) newLabel.SetAndObserveDisplayNodeID(displayNode.GetID()) newLabel.SetAndObserveImageData(labelImage)
def CreateNewVolume(self, trial_num, numSamp, labelType): imageSize=[64, 64, 64] imageSpacing=[1.0, 1.0, 1.0] voxelType=vtk.VTK_UNSIGNED_CHAR # Create an empty image volume imageData=vtk.vtkImageData() imageData.SetDimensions(imageSize) imageData.AllocateScalars(voxelType, 1) thresholder=vtk.vtkImageThreshold() thresholder.SetInputData(imageData) thresholder.SetInValue(0) thresholder.SetOutValue(0) # Create volume node volumeNode=slicer.vtkMRMLScalarVolumeNode() volumeNode.SetSpacing(imageSpacing) volumeNode.SetImageDataConnection(thresholder.GetOutputPort()) # Add volume to scene slicer.mrmlScene.AddNode(volumeNode) displayNode=slicer.vtkMRMLScalarVolumeDisplayNode() slicer.mrmlScene.AddNode(displayNode) colorNode = slicer.util.getNode('Grey') displayNode.SetAndObserveColorNodeID(colorNode.GetID()) volumeNode.SetAndObserveDisplayNodeID(displayNode.GetID()) volumeNode.CreateDefaultStorageNode() # name volume volume_name = str(labelType)+'_trial_'+str(trial_num)+'_nsamp_'+str(numSamp) volumeNode.SetName(volume_name) return volumeNode
def setupScene(self): logging.info("UltraSound.setupScene") # live ultrasound liveUltrasoundNodeName = self.guideletParent.parameterNode.GetParameter("LiveUltrasoundNodeName") self.liveUltrasoundNode_Reference = slicer.util.getNode(liveUltrasoundNodeName) if not self.liveUltrasoundNode_Reference: imageSpacing = [0.2, 0.2, 0.2] # Create an empty image volume imageData = vtk.vtkImageData() imageData.SetDimensions(self.DEFAULT_IMAGE_SIZE) imageData.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) thresholder = vtk.vtkImageThreshold() thresholder.SetInputData(imageData) thresholder.SetInValue(0) thresholder.SetOutValue(0) # Create volume node self.liveUltrasoundNode_Reference = slicer.vtkMRMLScalarVolumeNode() self.liveUltrasoundNode_Reference.SetName(liveUltrasoundNodeName) self.liveUltrasoundNode_Reference.SetSpacing(imageSpacing) self.liveUltrasoundNode_Reference.SetImageDataConnection(thresholder.GetOutputPort()) # Add volume to scene slicer.mrmlScene.AddNode(self.liveUltrasoundNode_Reference) displayNode = slicer.vtkMRMLScalarVolumeDisplayNode() slicer.mrmlScene.AddNode(displayNode) colorNode = slicer.util.getNode("Grey") displayNode.SetAndObserveColorNodeID(colorNode.GetID()) self.liveUltrasoundNode_Reference.SetAndObserveDisplayNodeID(displayNode.GetID()) # self.liveUltrasoundNode_Reference.CreateDefaultStorageNode() self.setupResliceDriver()
def Extract_Surface(self, imgReader, label): # Extract a vtk surface from a vtk image treshold_filter = vtk.vtkImageThreshold() treshold_filter.ThresholdBetween(label, label) try: treshold_filter.SetInputConnection(imgReader.GetOutputPort()) except: treshold_filter.SetInputData(imgReader) treshold_filter.ReplaceInOn() treshold_filter.SetInValue( 255 ) # Replace the bone label = label to 255 (threshold again using contour filter) treshold_filter.Update() boneExtractor = vtk.vtkDiscreteMarchingCubes() try: boneExtractor.SetInputData(treshold_filter.GetOutput()) except: boneExtractor.SetInputConnection(treshold_filter.GetOutputPort()) # The bone label(s) of interest were set to 255 above using the image threshold filter boneExtractor.SetValue(0, 255) boneExtractor.Update() output_polydata = self.Smooth_Surface(boneExtractor.GetOutput()) return output_polydata
def initializeNewLabel(newLabel, sourceVolume): displayNode = slicer.mrmlScene.AddNode(slicer.vtkMRMLLabelMapVolumeDisplayNode()) threshold = vtk.vtkImageThreshold() threshold.ReplaceInOn() threshold.ReplaceOutOn() threshold.SetInValue(0) threshold.SetOutValue(0) threshold.SetOutputScalarTypeToUnsignedShort() threshold.SetInput(sourceVolume.GetImageData()) threshold.Update() labelImage = vtk.vtkImageData() labelImage.DeepCopy(threshold.GetOutput()) newLabel.SetAndObserveStorageNodeID(None) newLabel.SetLabelMap(1) newLabel.CopyOrientation(sourceVolume) ras2ijk = vtk.vtkMatrix4x4() sourceVolume.GetRASToIJKMatrix(ras2ijk) newLabel.SetRASToIJKMatrix(ras2ijk) newLabel.SetAttribute('ReportingReportNodeID', sourceVolume.GetAttribute('ReportingReportNodeID')) newLabel.SetAttribute('AssociatedNodeID', sourceVolume.GetID()) newLabel.SetAndObserveDisplayNodeID(displayNode.GetID()) newLabel.SetAndObserveImageData(labelImage)
def setupScene(self): logging.info("UltraSound.setupScene") ''' ReferenceToRas transform is used in almost all IGT applications. Reference is the coordinate system of a tool fixed to the patient. Tools are tracked relative to Reference, to compensate for patient motion. ReferenceToRas makes sure that everything is displayed in an anatomical coordinate system, i.e. R, A, and S (Right, Anterior, and Superior) directions in Slicer are correct relative to any images or tracked tools displayed. ReferenceToRas is needed for initialization, so we need to set it up before calling Guidelet.setupScene(). ''' if self.referenceToRas is None or (self.referenceToRas and slicer.mrmlScene.GetNodeByID(self.referenceToRas.GetID()) is None): self.referenceToRas = slicer.mrmlScene.GetFirstNodeByName('ReferenceToRas') if self.referenceToRas is None: self.referenceToRas = slicer.vtkMRMLLinearTransformNode() self.referenceToRas.SetName("ReferenceToRas") m = self.guideletParent.logic.readTransformFromSettings('ReferenceToRas', self.guideletParent.configurationName) if m is None: m = self.guideletParent.logic.createMatrixFromString('1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1') self.referenceToRas.SetMatrixTransformToParent(m) slicer.mrmlScene.AddNode(self.referenceToRas) # live ultrasound liveUltrasoundNodeName = self.guideletParent.parameterNode.GetParameter('LiveUltrasoundNodeName') self.liveUltrasoundNode_Reference = slicer.mrmlScene.GetFirstNodeByName(liveUltrasoundNodeName) if not self.liveUltrasoundNode_Reference: imageSpacing=[0.2, 0.2, 0.2] # Create an empty image volume imageData=vtk.vtkImageData() imageData.SetDimensions(self.DEFAULT_IMAGE_SIZE) imageData.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) thresholder=vtk.vtkImageThreshold() thresholder.SetInputData(imageData) thresholder.SetInValue(0) thresholder.SetOutValue(0) # Create volume node self.liveUltrasoundNode_Reference=slicer.vtkMRMLScalarVolumeNode() self.liveUltrasoundNode_Reference.SetName(liveUltrasoundNodeName) self.liveUltrasoundNode_Reference.SetSpacing(imageSpacing) self.liveUltrasoundNode_Reference.SetImageDataConnection(thresholder.GetOutputPort()) # Add volume to scene slicer.mrmlScene.AddNode(self.liveUltrasoundNode_Reference) displayNode=slicer.vtkMRMLScalarVolumeDisplayNode() slicer.mrmlScene.AddNode(displayNode) colorNode = slicer.mrmlScene.GetFirstNodeByName('Grey') displayNode.SetAndObserveColorNodeID(colorNode.GetID()) self.liveUltrasoundNode_Reference.SetAndObserveDisplayNodeID(displayNode.GetID()) self.plusRemoteNode = slicer.mrmlScene.GetFirstNodeByClass('vtkMRMLPlusRemoteNode') if self.plusRemoteNode is None: self.plusRemoteNode = slicer.vtkMRMLPlusRemoteNode() self.plusRemoteNode.SetName("PlusRemoteNode") slicer.mrmlScene.AddNode(self.plusRemoteNode) self.plusRemoteNode.AddObserver(slicer.vtkMRMLPlusRemoteNode.RecordingStartedEvent, self.recordingCommandCompleted) self.plusRemoteNode.AddObserver(slicer.vtkMRMLPlusRemoteNode.RecordingCompletedEvent, self.recordingCommandCompleted) self.plusRemoteNode.SetAndObserveOpenIGTLinkConnectorNode(self.guideletParent.connectorNode) self.setupResliceDriver()
def setupScene(self): logging.info("UltraSound.setupScene") ''' ReferenceToRas transform is used in almost all IGT applications. Reference is the coordinate system of a tool fixed to the patient. Tools are tracked relative to Reference, to compensate for patient motion. ReferenceToRas makes sure that everything is displayed in an anatomical coordinate system, i.e. R, A, and S (Right, Anterior, and Superior) directions in Slicer are correct relative to any images or tracked tools displayed. ReferenceToRas is needed for initialization, so we need to set it up before calling Guidelet.setupScene(). ''' if self.referenceToRas is None or ( self.referenceToRas and slicer.mrmlScene.GetNodeByID( self.referenceToRas.GetID()) is None): self.referenceToRas = slicer.mrmlScene.GetFirstNodeByName( 'ReferenceToRas') if self.referenceToRas is None: self.referenceToRas = slicer.vtkMRMLLinearTransformNode() self.referenceToRas.SetName("ReferenceToRas") m = self.guideletParent.logic.readTransformFromSettings( 'ReferenceToRas', self.guideletParent.configurationName) if m is None: m = self.guideletParent.logic.createMatrixFromString( '1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1') self.referenceToRas.SetMatrixTransformToParent(m) slicer.mrmlScene.AddNode(self.referenceToRas) # live ultrasound liveUltrasoundNodeName = self.guideletParent.parameterNode.GetParameter( 'LiveUltrasoundNodeName') self.liveUltrasoundNode_Reference = slicer.mrmlScene.GetFirstNodeByName( liveUltrasoundNodeName) if not self.liveUltrasoundNode_Reference: imageSpacing = [0.2, 0.2, 0.2] # Create an empty image volume imageData = vtk.vtkImageData() imageData.SetDimensions(self.DEFAULT_IMAGE_SIZE) imageData.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) thresholder = vtk.vtkImageThreshold() thresholder.SetInputData(imageData) thresholder.SetInValue(0) thresholder.SetOutValue(0) # Create volume node self.liveUltrasoundNode_Reference = slicer.vtkMRMLScalarVolumeNode( ) self.liveUltrasoundNode_Reference.SetName(liveUltrasoundNodeName) self.liveUltrasoundNode_Reference.SetSpacing(imageSpacing) self.liveUltrasoundNode_Reference.SetImageDataConnection( thresholder.GetOutputPort()) # Add volume to scene slicer.mrmlScene.AddNode(self.liveUltrasoundNode_Reference) displayNode = slicer.vtkMRMLScalarVolumeDisplayNode() slicer.mrmlScene.AddNode(displayNode) colorNode = slicer.mrmlScene.GetFirstNodeByName('Grey') displayNode.SetAndObserveColorNodeID(colorNode.GetID()) self.liveUltrasoundNode_Reference.SetAndObserveDisplayNodeID( displayNode.GetID()) self.setupResliceDriver()
def growCut(self): growCutFilter = vtkITK.vtkITKGrowCutSegmentationImageFilter() background = self.getScopedBackground() gestureInput = self.getScopedLabelInput() growCutOutput = self.getScopedLabelOutput() if not self.areInputsValid(): logging.warning(self.getInvalidInputsMessage()) # set the make a zero-valued volume for the output # TODO: maybe this should be done in numpy as a one-liner thresh = vtk.vtkImageThreshold() thresh.ReplaceInOn() thresh.ReplaceOutOn() thresh.SetInValue(0) thresh.SetOutValue(0) thresh.SetOutputScalarType(vtk.VTK_SHORT) if vtk.VTK_MAJOR_VERSION <= 5: thresh.SetInput(gestureInput) else: thresh.SetInputData(gestureInput) thresh.SetOutput(growCutOutput) thresh.Update() growCutOutput.DeepCopy(gestureInput) if vtk.VTK_MAJOR_VERSION <= 5: growCutFilter.SetInput(0, background) growCutFilter.SetInput(1, gestureInput) growCutFilter.SetInput(2, growCutOutput) else: growCutFilter.SetInputData(0, background) growCutFilter.SetInputData(1, gestureInput) growCutFilter.SetInputConnection(2, thresh.GetOutputPort()) objectSize = 5. # TODO: this is a magic number contrastNoiseRatio = 0.8 # TODO: this is a magic number priorStrength = 0.003 # TODO: this is a magic number segmented = 2 # TODO: this is a magic number conversion = 1000 # TODO: this is a magic number spacing = gestureInput.GetSpacing() voxelVolume = reduce(lambda x, y: x * y, spacing) voxelAmount = objectSize / voxelVolume voxelNumber = round(voxelAmount) * conversion cubeRoot = 1. / 3. oSize = int(round(pow(voxelNumber, cubeRoot))) growCutFilter.SetObjectSize(oSize) growCutFilter.SetContrastNoiseRatio(contrastNoiseRatio) growCutFilter.SetPriorSegmentConfidence(priorStrength) growCutFilter.Update() growCutOutput.DeepCopy(growCutFilter.GetOutput()) self.applyScopedLabel()
def growCut(self): growCutFilter = vtkITK.vtkITKGrowCutSegmentationImageFilter() background = self.getScopedBackground() gestureInput = self.getScopedLabelInput() growCutOutput = self.getScopedLabelOutput() if not self.areInputsValid(): logging.warning(self.getInvalidInputsMessage()) # set the make a zero-valued volume for the output # TODO: maybe this should be done in numpy as a one-liner thresh = vtk.vtkImageThreshold() thresh.ReplaceInOn() thresh.ReplaceOutOn() thresh.SetInValue(0) thresh.SetOutValue(0) thresh.SetOutputScalarType( vtk.VTK_SHORT ) if vtk.VTK_MAJOR_VERSION <= 5: thresh.SetInput( gestureInput ) else: thresh.SetInputData( gestureInput ) thresh.SetOutput( growCutOutput ) thresh.Update() growCutOutput.DeepCopy( gestureInput ) if vtk.VTK_MAJOR_VERSION <= 5: growCutFilter.SetInput( 0, background ) growCutFilter.SetInput( 1, gestureInput ) growCutFilter.SetInput( 2, growCutOutput ) else: growCutFilter.SetInputData( 0, background ) growCutFilter.SetInputData( 1, gestureInput ) growCutFilter.SetInputConnection( 2, thresh.GetOutputPort() ) objectSize = 5. # TODO: this is a magic number contrastNoiseRatio = 0.8 # TODO: this is a magic number priorStrength = 0.003 # TODO: this is a magic number segmented = 2 # TODO: this is a magic number conversion = 1000 # TODO: this is a magic number spacing = gestureInput.GetSpacing() voxelVolume = reduce(lambda x,y: x*y, spacing) voxelAmount = objectSize / voxelVolume voxelNumber = round(voxelAmount) * conversion cubeRoot = 1./3. oSize = int(round(pow(voxelNumber,cubeRoot))) growCutFilter.SetObjectSize( oSize ) growCutFilter.SetContrastNoiseRatio( contrastNoiseRatio ) growCutFilter.SetPriorSegmentConfidence( priorStrength ) growCutFilter.Update() growCutOutput.DeepCopy( growCutFilter.GetOutput() ) self.applyScopedLabel()
def preview(self, color=None): if not self.editUtil.getBackgroundImage( ) or not self.editUtil.getLabelImage(): return # # make a lookup table where inside the threshold is opaque and colored # by the label color, while the background is transparent (black) # - apply the threshold operation to the currently visible background # (output of the layer logic's vtkImageReslice instance) # if not color: color = self.getPaintColor if not self.lut: self.lut = vtk.vtkLookupTable() self.lut.SetRampToLinear() self.lut.SetNumberOfTableValues(2) self.lut.SetTableRange(0, 1) self.lut.SetTableValue(0, 0, 0, 0, 0) r, g, b, a = color self.lut.SetTableValue(1, r, g, b, a) if not self.map: self.map = vtk.vtkImageMapToRGBA() self.map.SetOutputFormatToRGBA() self.map.SetLookupTable(self.lut) if not self.thresh: self.thresh = vtk.vtkImageThreshold() sliceLogic = self.sliceWidget.sliceLogic() backgroundLogic = sliceLogic.GetBackgroundLayer() if vtk.VTK_MAJOR_VERSION <= 5: self.thresh.SetInput(backgroundLogic.GetReslice().GetOutput()) else: self.thresh.SetInputConnection( backgroundLogic.GetReslice().GetOutputPort()) self.thresh.ThresholdBetween(self.min, self.max) self.thresh.SetInValue(1) self.thresh.SetOutValue(0) self.thresh.SetOutputScalarTypeToUnsignedChar() if vtk.VTK_MAJOR_VERSION <= 5: self.map.SetInput(self.thresh.GetOutput()) self.map.Update() self.cursorMapper.SetInput(self.map.GetOutput()) else: self.map.SetInputConnection(self.thresh.GetOutputPort()) self.cursorMapper.SetInputConnection(self.map.GetOutputPort()) self.cursorActor.VisibilityOn() self.sliceView.scheduleRender()
def __init__(self, grayscaleNode, labelNode, fileName=None): volumeName = grayscaleNode.GetName() self.keys = ("Volume", "Curve Type", "Voxel Count", "Volume mm^3", "Volume cc", "Minimum Intensity", "Maximum Intensity", "Mean Intensity", "Standard Deviation") cubicMMPerVoxel = reduce(lambda x,y: x*y, labelNode.GetSpacing()) ccPerCubicMM = 0.001 self.labelStats = {} self.labelStats['Labels'] = [] stataccum = vtk.vtkImageAccumulate() stataccum.SetInput(labelNode.GetImageData()) stataccum.Update() lo = int(stataccum.GetMin()[0]) hi = int(stataccum.GetMax()[0]) for i in xrange(lo,hi+1): thresholder = vtk.vtkImageThreshold() thresholder.SetInput(labelNode.GetImageData()) thresholder.SetInValue(1) thresholder.SetOutValue(0) thresholder.ReplaceOutOn() thresholder.ThresholdBetween(i,i) thresholder.SetOutputScalarType(grayscaleNode.GetImageData().GetScalarType()) thresholder.Update() stencil = vtk.vtkImageToImageStencil() stencil.SetInput(thresholder.GetOutput()) stencil.ThresholdBetween(1, 1) stat1 = vtk.vtkImageAccumulate() stat1.SetInput(grayscaleNode.GetImageData()) stat1.SetStencil(stencil.GetOutput()) stat1.Update() curveType = 'Curve Type' if i == 32: curveType = 'Washout Curve' elif i == 306: curveType = 'Persistent Curve' elif i == 291: curveType = 'Plateau Curve' elif i == 0: curveType = 'Unsegmented Region' if stat1.GetVoxelCount() > 0: # add an entry to the LabelStats list self.labelStats["Labels"].append(i) self.labelStats[i,"Volume"] = volumeName self.labelStats[i,"Curve Type"] = curveType self.labelStats[i,"Voxel Count"] = stat1.GetVoxelCount() self.labelStats[i,"Volume mm^3"] = self.labelStats[i,"Voxel Count"] * cubicMMPerVoxel self.labelStats[i,"Volume cc"] = self.labelStats[i,"Volume mm^3"] * ccPerCubicMM self.labelStats[i,"Minimum Intensity"] = stat1.GetMin()[0] self.labelStats[i,"Maximum Intensity"] = stat1.GetMax()[0] self.labelStats[i,"Mean Intensity"] = stat1.GetMean()[0] self.labelStats[i,"Standard Deviation"] = stat1.GetStandardDeviation()[0]
def setupScene(self): layoutManager = slicer.app.layoutManager() # live ultrasound liveUltrasoundNodeName = self.guideletParent.parameterNode.GetParameter('LiveUltrasoundNodeName') self.liveUltrasoundNode_Reference = slicer.util.getNode(liveUltrasoundNodeName) if not self.liveUltrasoundNode_Reference: imageSize=[800, 600, 1] imageSpacing=[0.2, 0.2, 0.2] # Create an empty image volume imageData=vtk.vtkImageData() imageData.SetDimensions(imageSize) imageData.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) thresholder=vtk.vtkImageThreshold() thresholder.SetInputData(imageData) thresholder.SetInValue(0) thresholder.SetOutValue(0) # Create volume node self.liveUltrasoundNode_Reference=slicer.vtkMRMLScalarVolumeNode() self.liveUltrasoundNode_Reference.SetName(liveUltrasoundNodeName) self.liveUltrasoundNode_Reference.SetSpacing(imageSpacing) self.liveUltrasoundNode_Reference.SetImageDataConnection(thresholder.GetOutputPort()) # Add volume to scene slicer.mrmlScene.AddNode(self.liveUltrasoundNode_Reference) displayNode=slicer.vtkMRMLScalarVolumeDisplayNode() slicer.mrmlScene.AddNode(displayNode) colorNode = slicer.util.getNode('Grey') displayNode.SetAndObserveColorNodeID(colorNode.GetID()) self.liveUltrasoundNode_Reference.SetAndObserveDisplayNodeID(displayNode.GetID()) #self.liveUltrasoundNode_Reference.CreateDefaultStorageNode() # Show ultrasound in red view. redSlice = layoutManager.sliceWidget('Red') redSliceLogic = redSlice.sliceLogic() redSliceLogic.GetSliceCompositeNode().SetBackgroundVolumeID(self.liveUltrasoundNode_Reference.GetID()) # Set up volume reslice driver. resliceLogic = slicer.modules.volumereslicedriver.logic() if resliceLogic: redNode = slicer.util.getNode('vtkMRMLSliceNodeRed') # Typically the image is zoomed in, therefore it is faster if the original resolution is used # on the 3D slice (and also we can show the full image and not the shape and size of the 2D view) redNode.SetSliceResolutionMode(slicer.vtkMRMLSliceNode.SliceResolutionMatchVolumes) resliceLogic.SetDriverForSlice(self.liveUltrasoundNode_Reference.GetID(), redNode) resliceLogic.SetModeForSlice(6, redNode) # Transverse mode, default for PLUS ultrasound. resliceLogic.SetFlipForSlice(False, redNode) resliceLogic.SetRotationForSlice(180, redNode) redSliceLogic.FitSliceToAll() else: logging.warning('Logic not found for Volume Reslice Driver') self.liveUltrasoundNode_Reference.SetAndObserveTransformNodeID(self.guideletParent.ReferenceToRas.GetID())
def preview(self,color=None): if not self.editUtil.getBackgroundImage() or not self.editUtil.getLabelImage(): return # # make a lookup table where inside the threshold is opaque and colored # by the label color, while the background is transparent (black) # - apply the threshold operation to the currently visible background # (output of the layer logic's vtkImageReslice instance) # if not color: color = self.getPaintColor if not self.lut: self.lut = vtk.vtkLookupTable() self.lut.SetRampToLinear() self.lut.SetNumberOfTableValues( 3 ) self.lut.SetTableRange( 0, 2 ) self.lut.SetTableValue( 0, 0, 0, 0, 0 ) r,g,b,a = color self.lut.SetTableValue( 1, r, g, b, a ) #self.lut.SetTableValue( 2, r, g, b, a ) if not self.map: self.map = vtk.vtkImageMapToRGBA() self.map.SetOutputFormatToRGBA() self.map.SetLookupTable( self.lut ) if not self.thresh: self.thresh = vtk.vtkImageThreshold() sliceLogic = self.sliceWidget.sliceLogic() backgroundLogic = sliceLogic.GetBackgroundLayer() # backgroundNodeName = backgroundNode.GetName() # backgroundImage = sitk.ReadImage( sitkUtils.GetSlicerITKReadWriteAddress( backgroundNodeName ) ) self.thresh.SetInput( backgroundLogic.GetReslice().GetOutput() ) self.thresh.ThresholdBetween( self.min, self.max ) self.thresh.SetInValue( 1 ) self.thresh.SetOutValue( 0 ) self.thresh.SetOutputScalarTypeToUnsignedChar() self.map.SetInput( self.thresh.GetOutput() ) self.map.Update() self.cursorMapper.SetInput( self.map.GetOutput() ) self.cursorActor.VisibilityOn() self.sliceView.scheduleRender()
def split(self): """split the merge volume into individual structures""" self.statusText("Splitting...") merge = self.mergeVolume() if not merge: return colorNode = merge.GetDisplayNode().GetColorNode() accum = vtk.vtkImageAccumulate() if vtk.VTK_MAJOR_VERSION <= 5: accum.SetInput(merge.GetImageData()) else: accum.SetInputConnection(merge.GetImageDataConnection()) accum.Update() lo = int(accum.GetMin()[0]) hi = int(accum.GetMax()[0]) # TODO: pending resolution of bug 1822, run the thresholding # in single threaded mode to avoid data corruption observed on mac release # builds thresholder = vtk.vtkImageThreshold() thresholder.SetNumberOfThreads(1) for i in xrange(lo, hi + 1): self.statusText("Splitting label %d..." % i) if vtk.VTK_MAJOR_VERSION <= 5: thresholder.SetInput(merge.GetImageData()) else: thresholder.SetInputConnection(merge.GetImageDataConnection()) thresholder.SetInValue(i) thresholder.SetOutValue(0) thresholder.ReplaceInOn() thresholder.ReplaceOutOn() thresholder.ThresholdBetween(i, i) thresholder.SetOutputScalarType( merge.GetImageData().GetScalarType()) thresholder.Update() if thresholder.GetOutput().GetScalarRange() != (0.0, 0.0): labelName = colorNode.GetColorName(i) self.statusText("Creating structure volume %s..." % labelName) structureVolume = self.structureVolume(labelName) if not structureVolume: self.addStructure(i, "noEdit") structureVolume = self.structureVolume(labelName) structureVolume.GetImageData().DeepCopy( thresholder.GetOutput()) self.editUtil.markVolumeNodeAsModified(structureVolume) self.statusText("Finished splitting.")
def buildSimpleLabelMap( self, image, inValue, outValue ): threshold = vtk.vtkImageThreshold() threshold.SetInputData( image ) threshold.ThresholdByLower( 0 ) threshold.ReplaceInOn() threshold.ReplaceOutOn() threshold.SetOutValue( outValue ) threshold.SetInValue( inValue ) threshold.Update() outVolumeData = vtk.vtkImageData() outVolumeData.DeepCopy( threshold.GetOutput() ) return outVolumeData
def buildSimpleLabelMap(self, image, inValue, outValue): threshold = vtk.vtkImageThreshold() threshold.SetInputData(image) threshold.ThresholdByLower(0) threshold.ReplaceInOn() threshold.ReplaceOutOn() threshold.SetOutValue(outValue) threshold.SetInValue(inValue) threshold.Update() outVolumeData = vtk.vtkImageData() outVolumeData.DeepCopy(threshold.GetOutput()) return outVolumeData
def split(self): """split the merge volume into individual structures""" self.statusText( "Splitting..." ) merge = self.mergeVolume() if not merge: return colorNode = merge.GetDisplayNode().GetColorNode() accum = vtk.vtkImageAccumulate() if vtk.VTK_MAJOR_VERSION <= 5: accum.SetInput(merge.GetImageData()) else: accum.SetInputConnection(merge.GetImageDataConnection()) accum.Update() lo = int(accum.GetMin()[0]) hi = int(accum.GetMax()[0]) # TODO: pending resolution of bug 1822, run the thresholding # in single threaded mode to avoid data corruption observed on mac release # builds thresholder = vtk.vtkImageThreshold() thresholder.SetNumberOfThreads(1) for i in xrange(lo,hi+1): self.statusText( "Splitting label %d..."%i ) if vtk.VTK_MAJOR_VERSION <= 5: thresholder.SetInput( merge.GetImageData() ) else: thresholder.SetInputConnection( merge.GetImageDataConnection() ) thresholder.SetInValue( i ) thresholder.SetOutValue( 0 ) thresholder.ReplaceInOn() thresholder.ReplaceOutOn() thresholder.ThresholdBetween( i, i ) thresholder.SetOutputScalarType( merge.GetImageData().GetScalarType() ) thresholder.Update() if thresholder.GetOutput().GetScalarRange() != (0.0, 0.0): labelName = colorNode.GetColorName(i) self.statusText( "Creating structure volume %s..."%labelName ) structureVolume = self.structureVolume( labelName ) if not structureVolume: self.addStructure( i, "noEdit" ) structureVolume = self.structureVolume( labelName ) structureVolume.GetImageData().DeepCopy( thresholder.GetOutput() ) self.editUtil.markVolumeNodeAsModified(structureVolume) self.statusText( "Finished splitting." )
def growCut(background,gestureInput,growCutOutput): growCutFilter = vtkITK.vtkITKGrowCutSegmentationImageFilter() # set the make a zero-valued volume for the output # TODO: maybe this should be done in numpy as a one-liner thresh = vtk.vtkImageThreshold() thresh.ReplaceInOn() thresh.ReplaceOutOn() thresh.SetInValue(0) thresh.SetOutValue(0) thresh.SetOutputScalarType( vtk.VTK_SHORT ) thresh.SetInputData( gestureInput ) thresh.SetOutput( growCutOutput ) thresh.Update() growCutOutput.DeepCopy( gestureInput ) growCutFilter.SetInputData( 0, background ) growCutFilter.SetInputData( 1, gestureInput ) growCutFilter.SetInputConnection( 2, thresh.GetOutputPort() ) objectSize = 10. # TODO: this is a magic number contrastNoiseRatio = 0.8 # TODO: this is a magic number priorStrength = 0.003 # TODO: this is a magic number segmented = 2 # TODO: this is a magic number conversion = 1000 # TODO: this is a magic number spacing = gestureInput.GetSpacing() voxelVolume = reduce(lambda x,y: x*y, spacing) voxelAmount = objectSize / voxelVolume voxelNumber = round(voxelAmount) * conversion cubeRoot = 1./3. oSize = int(round(pow(voxelNumber,cubeRoot))) growCutFilter.SetObjectSize( oSize ) growCutFilter.SetContrastNoiseRatio( contrastNoiseRatio ) growCutFilter.SetPriorSegmentConfidence( priorStrength ) growCutFilter.Update() growCutOutput.DeepCopy( growCutFilter.GetOutput() ) return growCutOutput
def growCut(background, gestureInput, growCutOutput): growCutFilter = vtkITK.vtkITKGrowCutSegmentationImageFilter() # set the make a zero-valued volume for the output # TODO: maybe this should be done in numpy as a one-liner thresh = vtk.vtkImageThreshold() thresh.ReplaceInOn() thresh.ReplaceOutOn() thresh.SetInValue(0) thresh.SetOutValue(0) thresh.SetOutputScalarType(vtk.VTK_SHORT) thresh.SetInputData(gestureInput) thresh.SetOutput(growCutOutput) thresh.Update() growCutOutput.DeepCopy(gestureInput) growCutFilter.SetInputData(0, background) growCutFilter.SetInputData(1, gestureInput) growCutFilter.SetInputConnection(2, thresh.GetOutputPort()) objectSize = 10. # TODO: this is a magic number contrastNoiseRatio = 0.8 # TODO: this is a magic number priorStrength = 0.003 # TODO: this is a magic number segmented = 2 # TODO: this is a magic number conversion = 1000 # TODO: this is a magic number spacing = gestureInput.GetSpacing() voxelVolume = reduce(lambda x, y: x * y, spacing) voxelAmount = objectSize / voxelVolume voxelNumber = round(voxelAmount) * conversion cubeRoot = 1. / 3. oSize = int(round(pow(voxelNumber, cubeRoot))) growCutFilter.SetObjectSize(oSize) growCutFilter.SetContrastNoiseRatio(contrastNoiseRatio) growCutFilter.SetPriorSegmentConfidence(priorStrength) growCutFilter.Update() growCutOutput.DeepCopy(growCutFilter.GetOutput()) return growCutOutput
def apply(self): if not self.editUtil.getBackgroundImage() or not self.editUtil.getLabelImage(): return node = self.editUtil.getParameterNode() self.undoRedo.saveState() thresh = vtk.vtkImageThreshold() thresh.SetInput( self.editUtil.getBackgroundImage() ) thresh.ThresholdBetween(self.min, self.max) thresh.SetInValue( self.editUtil.getLabel() ) thresh.SetOutValue( 0 ) thresh.SetOutputScalarType( self.editUtil.getLabelImage().GetScalarType() ) # $this setProgressFilter $thresh "Threshold" thresh.Update() self.editUtil.getLabelImage().DeepCopy( thresh.GetOutput() ) self.editUtil.markVolumeNodeAsModified(self.editUtil.getLabelVolume())
def split(self): """split the merge volume into individual structures""" self.statusText("Splitting...") merge = self.mergeVolume() if not merge: return colorNode = merge.GetDisplayNode().GetColorNode() accum = vtk.vtkImageAccumulate() accum.SetInput(merge.GetImageData()) accum.Update() lo = int(accum.GetMin()[0]) hi = int(accum.GetMax()[0]) thresholder = vtk.vtkImageThreshold() for i in xrange(lo, hi + 1): self.statusText("Splitting label %d..." % i) thresholder.SetInput(merge.GetImageData()) thresholder.SetInValue(i) thresholder.SetOutValue(0) thresholder.ReplaceInOn() thresholder.ReplaceOutOn() thresholder.ThresholdBetween(i, i) thresholder.SetOutputScalarType( merge.GetImageData().GetScalarType()) thresholder.Update() if thresholder.GetOutput().GetScalarRange() != (0.0, 0.0): labelName = colorNode.GetColorName(i) self.statusText("Creating structure volume %s..." % labelName) structureVolume = self.structureVolume(labelName) if not structureVolume: self.addStructure(i, "noEdit") structureVolume = self.structureVolume(labelName) structureVolume.GetImageData().DeepCopy( thresholder.GetOutput()) structureVolume.Modified() self.statusText("Finished splitting.")
def identIslands(self): inputImage=self.volume.GetImageData() labelImage=self.label.GetImageData() #labelImage.SetSpacing(self.label.GetSpacing()) IJKToRAS = vtk.vtkMatrix4x4() self.volume.GetIJKToRASMatrix(IJKToRAS) self.label.SetIJKToRASMatrix(IJKToRAS) eV=slicer.vtkFillVOIImageFilter() eV.SetfillValue(0) eV.SetInputData(inputImage) if self.sliceidx>0: VOIpre=[0,inputImage.GetDimensions()[0],0,inputImage.GetDimensions()[1],0,self.sliceidx-1] eV.AddVOI(VOIpre) if self.sliceidx<inputImage.GetDimensions()[2]: VOIpost=[0,inputImage.GetDimensions()[0],0,inputImage.GetDimensions()[1],self.sliceidx+1,inputImage.GetDimensions()[2]] eV.AddVOI(VOIpost) eV.Update() slice=eV.GetOutput() thresh = vtk.vtkImageThreshold() thresh.SetInputData(slice) thresh.ThresholdBetween(self.thrRange[0],self.thrRange[1]) thresh.SetInValue(1) thresh.SetOutValue(0) thresh.SetOutputScalarType(vtk.VTK_SHORT) thresh.Modified() thresh.Update() islandM=vtkITK.vtkITKIslandMath() islandM.SetInputData(thresh.GetOutput()) islandM.Update() labelImage.DeepCopy(islandM.GetOutput())
def split(self): """split the merge volume into individual structures""" self.statusText( "Splitting..." ) merge = self.mergeVolume() if not merge: return colorNode = merge.GetDisplayNode().GetColorNode() accum = vtk.vtkImageAccumulate() accum.SetInput(merge.GetImageData()) accum.Update() lo = int(accum.GetMin()[0]) hi = int(accum.GetMax()[0]) thresholder = vtk.vtkImageThreshold() for i in xrange(lo,hi+1): self.statusText( "Splitting label %d..."%i ) thresholder.SetInput( merge.GetImageData() ) thresholder.SetInValue( i ) thresholder.SetOutValue( 0 ) thresholder.ReplaceInOn() thresholder.ReplaceOutOn() thresholder.ThresholdBetween( i, i ) thresholder.SetOutputScalarType( merge.GetImageData().GetScalarType() ) thresholder.Update() if thresholder.GetOutput().GetScalarRange() != (0.0, 0.0): labelName = colorNode.GetColorName(i) self.statusText( "Creating structure volume %s..."%labelName ) structureVolume = self.structureVolume( labelName ) if not structureVolume: self.addStructure( i, "noEdit" ) structureVolume = self.structureVolume( labelName ) structureVolume.GetImageData().DeepCopy( thresholder.GetOutput() ) structureVolume.Modified() self.statusText( "Finished splitting." )
def getVolumeIm(self,im,minValue=1): thresh = vtk.vtkImageThreshold() thresh.SetInputData(im) max = im.GetScalarRange()[1] thresh.ThresholdBetween(minValue, max) thresh.SetInValue(1) thresh.SetOutValue(0) thresh.SetOutputScalarType(im.GetScalarType()) thresh.Modified() thresh.Update() stencil = vtk.vtkImageToImageStencil() stencil.SetInputData(thresh.GetOutput()) stencil.ThresholdBetween(1, 1) stencil.Update() stat1 = vtk.vtkImageAccumulate() stat1.SetInputData(im) stat1.SetStencilData(stencil.GetOutput()) stat1.Update() return stat1.GetVoxelCount()
def apply(self, LayoutName): """applying the threshold to the label image""" self.sliceLogic = self.editUtil.getSliceLogic(LayoutName) BackgroundImage = self.editUtil.getBackgroundImage(LayoutName) if not BackgroundImage or not self.editUtil.getLabelImage(LayoutName): return node = self.editUtil.getParameterNode() self.undoRedo.saveState(LayoutName) thresh = vtk.vtkImageThreshold() if vtk.VTK_MAJOR_VERSION <= 5: thresh.SetInput( self.editUtil.getBackgroundImage() ) else: thresh.SetInputData( self.editUtil.getBackgroundImage() ) thresh.ThresholdBetween(self.min, self.max) thresh.SetInValue( self.editUtil.getLabel() ) thresh.SetOutValue( 0 ) thresh.SetOutputScalarType( self.editUtil.getLabelImage(LayoutName).GetScalarType() ) # $this setProgressFilter $thresh "Threshold" thresh.Update() self.editUtil.getLabelImage(LayoutName).DeepCopy( thresh.GetOutput() ) self.editUtil.markVolumeNodeAsModified(self.editUtil.getLabelVolume(LayoutName))
def setupScene(self): logging.info("UltraSound.setupScene") # live ultrasound liveUltrasoundNodeName = self.guideletParent.parameterNode.GetParameter( 'LiveUltrasoundNodeName') self.liveUltrasoundNode_Reference = slicer.util.getNode( liveUltrasoundNodeName) if not self.liveUltrasoundNode_Reference: imageSpacing = [0.2, 0.2, 0.2] # Create an empty image volume imageData = vtk.vtkImageData() imageData.SetDimensions(self.DEFAULT_IMAGE_SIZE) imageData.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) thresholder = vtk.vtkImageThreshold() thresholder.SetInputData(imageData) thresholder.SetInValue(0) thresholder.SetOutValue(0) # Create volume node self.liveUltrasoundNode_Reference = slicer.vtkMRMLScalarVolumeNode( ) self.liveUltrasoundNode_Reference.SetName(liveUltrasoundNodeName) self.liveUltrasoundNode_Reference.SetSpacing(imageSpacing) self.liveUltrasoundNode_Reference.SetImageDataConnection( thresholder.GetOutputPort()) # Add volume to scene slicer.mrmlScene.AddNode(self.liveUltrasoundNode_Reference) displayNode = slicer.vtkMRMLScalarVolumeDisplayNode() slicer.mrmlScene.AddNode(displayNode) colorNode = slicer.util.getNode('Grey') displayNode.SetAndObserveColorNodeID(colorNode.GetID()) self.liveUltrasoundNode_Reference.SetAndObserveDisplayNodeID( displayNode.GetID()) #self.liveUltrasoundNode_Reference.CreateDefaultStorageNode() self.setupResliceDriver()
def setupScene(self): logging.debug('setupScene') logging.debug('Create transforms') self.ReferenceToRas = slicer.util.getNode('ReferenceToRas') if not self.ReferenceToRas: self.ReferenceToRas=slicer.vtkMRMLLinearTransformNode() self.ReferenceToRas.SetName("ReferenceToRas") m = vtk.vtkMatrix4x4() m.SetElement( 0, 0, 0 ) m.SetElement( 0, 2, -1 ) m.SetElement( 1, 1, 0 ) m.SetElement( 1, 1, -1 ) m.SetElement( 2, 2, 0 ) m.SetElement( 2, 0, -1 ) self.ReferenceToRas.SetMatrixTransformToParent(m) slicer.mrmlScene.AddNode(self.ReferenceToRas) self.needleTipToNeedle = slicer.util.getNode('NeedleTipToNeedle') if not self.needleTipToNeedle: self.needleTipToNeedle=slicer.vtkMRMLLinearTransformNode() self.needleTipToNeedle.SetName("NeedleTipToNeedle") m = self.readTransformFromSettings('NeedleTipToNeedle') if m: self.needleTipToNeedle.SetMatrixTransformToParent(m) slicer.mrmlScene.AddNode(self.needleTipToNeedle) self.needleModelToNeedleTip = slicer.util.getNode('NeedleModelToNeedleTip') if not self.needleModelToNeedleTip: self.needleModelToNeedleTip=slicer.vtkMRMLLinearTransformNode() self.needleModelToNeedleTip.SetName("NeedleModelToNeedleTip") m = vtk.vtkMatrix4x4() m.SetElement( 0, 0, 0 ) m.SetElement( 1, 1, 0 ) m.SetElement( 2, 2, 0 ) m.SetElement( 0, 1, 1 ) m.SetElement( 1, 2, 1 ) m.SetElement( 2, 0, 1 ) self.needleModelToNeedleTip.SetMatrixTransformToParent(m) slicer.mrmlScene.AddNode(self.needleModelToNeedleTip) # Create transforms that will be updated through OpenIGTLink self.needleToReference = slicer.util.getNode('NeedleToReference') if not self.needleToReference: self.needleToReference=slicer.vtkMRMLLinearTransformNode() self.needleToReference.SetName("NeedleToReference") slicer.mrmlScene.AddNode(self.needleToReference) # Models logging.debug('Create models') self.needleModel_NeedleTip = slicer.util.getNode('NeedleModel') if not self.needleModel_NeedleTip: slicer.modules.createmodels.logic().CreateNeedle(80,1.0,2.5,0) self.needleModel_NeedleTip=slicer.util.getNode(pattern="NeedleModel") self.needleModel_NeedleTip.GetDisplayNode().SetColor(0.333333, 1.0, 1.0) self.needleModel_NeedleTip.SetName("NeedleModel") self.needleModel_NeedleTip.GetDisplayNode().SliceIntersectionVisibilityOn() liveUltrasoundNodeName = self.parameterNode.GetParameter('LiveUltrasoundNodeName') self.liveUltrasoundNode_Reference = slicer.util.getNode(liveUltrasoundNodeName) if not self.liveUltrasoundNode_Reference: imageSize=[800, 600, 1] imageSpacing=[0.2, 0.2, 0.2] # Create an empty image volume imageData=vtk.vtkImageData() imageData.SetDimensions(imageSize) imageData.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) thresholder=vtk.vtkImageThreshold() thresholder.SetInputData(imageData) thresholder.SetInValue(0) thresholder.SetOutValue(0) # Create volume node self.liveUltrasoundNode_Reference=slicer.vtkMRMLScalarVolumeNode() self.liveUltrasoundNode_Reference.SetName(liveUltrasoundNodeName) self.liveUltrasoundNode_Reference.SetSpacing(imageSpacing) self.liveUltrasoundNode_Reference.SetImageDataConnection(thresholder.GetOutputPort()) # Add volume to scene slicer.mrmlScene.AddNode(self.liveUltrasoundNode_Reference) displayNode=slicer.vtkMRMLScalarVolumeDisplayNode() slicer.mrmlScene.AddNode(displayNode) colorNode = slicer.util.getNode('Grey') displayNode.SetAndObserveColorNodeID(colorNode.GetID()) self.liveUltrasoundNode_Reference.SetAndObserveDisplayNodeID(displayNode.GetID()) #self.liveUltrasoundNode_Reference.CreateDefaultStorageNode() # Show ultrasound in red view. layoutManager = self.layoutManager redSlice = layoutManager.sliceWidget('Red') redSliceLogic = redSlice.sliceLogic() redSliceLogic.GetSliceCompositeNode().SetBackgroundVolumeID(self.liveUltrasoundNode_Reference.GetID()) # Set up volume reslice driver. resliceLogic = slicer.modules.volumereslicedriver.logic() if resliceLogic: redNode = slicer.util.getNode('vtkMRMLSliceNodeRed') # Typically the image is zoomed in, therefore it is faster if the original resolution is used # on the 3D slice (and also we can show the full image and not the shape and size of the 2D view) redNode.SetSliceResolutionMode(slicer.vtkMRMLSliceNode.SliceResolutionMatchVolumes) resliceLogic.SetDriverForSlice(self.liveUltrasoundNode_Reference.GetID(), redNode) resliceLogic.SetModeForSlice(6, redNode) # Transverse mode, default for PLUS ultrasound. resliceLogic.SetFlipForSlice(False, redNode) resliceLogic.SetRotationForSlice(180, redNode) redSliceLogic.FitSliceToAll() else: logging.warning('Logic not found for Volume Reslice Driver') # Build transform tree logging.debug('Set up transform tree') self.needleModel_NeedleTip.SetAndObserveTransformNodeID(self.needleModelToNeedleTip.GetID()) self.needleModelToNeedleTip.SetAndObserveTransformNodeID(self.needleTipToNeedle.GetID()) self.needleTipToNeedle.SetAndObserveTransformNodeID(self.needleToReference.GetID()) self.liveUltrasoundNode_Reference.SetAndObserveTransformNodeID(self.ReferenceToRas.GetID()) # Hide slice view annotations (patient name, scale, color bar, etc.) as they # decrease reslicing performance by 20%-100% logging.debug('Hide slice view annotations') import DataProbe dataProbeUtil=DataProbe.DataProbeLib.DataProbeUtil() dataProbeParameterNode=dataProbeUtil.getParameterNode() dataProbeParameterNode.SetParameter('showSliceViewAnnotations', '0')
def removeIslandsMorphologyDecruft(self,image,foregroundLabel,backgroundLabel,iterations=1): # # make binary mask foregroundLabel->1, backgroundLabel->0 # binThresh = vtk.vtkImageThreshold() if vtk.VTK_MAJOR_VERSION <= 5: binThresh.SetInput( image ) else: binThresh.SetInputData( image ) binThresh.ThresholdBetween(foregroundLabel,foregroundLabel) binThresh.SetInValue( 1 ) binThresh.SetOutValue( 0 ) binThresh.Update() # # first, erode iterations number of times # eroder = slicer.vtkImageErode() eroderImage = vtk.vtkImageData() eroderImage.DeepCopy(binThresh.GetOutput()) if vtk.VTK_MAJOR_VERSION <= 5: eroder.SetInput(eroderImage) else: eroder.SetInputData(eroderImage) for iteration in range(iterations): eroder.SetForeground( 1 ) eroder.SetBackground( 0 ) eroder.SetNeighborTo8() eroder.Update() eroderImage.DeepCopy(eroder.GetOutput()) # # now save only islands bigger than a specified size # # note that island operation happens in unsigned long space # but the slicer editor works in Short castIn = vtk.vtkImageCast() if vtk.VTK_MAJOR_VERSION <= 5: castIn.SetInput( eroderImage ) else: castIn.SetInputConnection( eroder.GetInputConnection(0,0) ) castIn.SetOutputScalarTypeToUnsignedLong() # now identify the islands in the inverted volume # and find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() if vtk.VTK_MAJOR_VERSION <= 5: islandMath.SetInput( castIn.GetOutput() ) else: islandMath.SetInputConnection( castIn.GetOutputPort() ) islandMath.SetFullyConnected( self.fullyConnected ) islandMath.SetMinimumSize( self.minimumSize ) # note that island operation happens in unsigned long space # but the slicer editor works in Short castOut = vtk.vtkImageCast() if vtk.VTK_MAJOR_VERSION <= 5: castOut.SetInput( islandMath.GetOutput() ) else: castOut.SetInputConnection( islandMath.GetOutputPort() ) castOut.SetOutputScalarTypeToShort() castOut.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount print( "%d islands created (%d ignored)" % (islandCount, ignoredIslands) ) # # now map everything back to 0 and 1 # thresh = vtk.vtkImageThreshold() if vtk.VTK_MAJOR_VERSION <= 5: thresh.SetInput( castOut.GetOutput() ) else: thresh.SetInputConnection( castOut.GetOutputPort() ) thresh.ThresholdByUpper(1) thresh.SetInValue( 1 ) thresh.SetOutValue( 0 ) thresh.Update() # # now, dilate back (erode background) iterations_plus_one number of times # dilater = slicer.vtkImageErode() dilaterImage = vtk.vtkImageData() dilaterImage.DeepCopy(thresh.GetOutput()) if vtk.VTK_MAJOR_VERSION <= 5: dilater.SetInput(dilaterImage) else: dilater.SetInputData(dilaterImage) for iteration in range(1+iterations): dilater.SetForeground( 0 ) dilater.SetBackground( 1 ) dilater.SetNeighborTo8() dilater.Update() dilaterImage.DeepCopy(dilater.GetOutput()) # # only keep pixels in both original and dilated result # logic = vtk.vtkImageLogic() if vtk.VTK_MAJOR_VERSION <= 5: logic.SetInput1(dilaterImage) logic.SetInput2(binThresh.GetOutput()) else: logic.SetInputConnection(0, dilater.GetInputConnection(0,0)) logic.SetInputConnection(1, binThresh.GetOutputPort()) #if foregroundLabel == 0: # logic.SetOperationToNand() #else: logic.SetOperationToAnd() logic.SetOutputTrueValue(1) logic.Update() # # convert from binary mask to 1->foregroundLabel, 0->backgroundLabel # unbinThresh = vtk.vtkImageThreshold() if vtk.VTK_MAJOR_VERSION <= 5: unbinThresh.SetInput( logic.GetOutput() ) else: unbinThresh.SetInputConnection( logic.GetOutputPort() ) unbinThresh.ThresholdBetween( 1,1 ) unbinThresh.SetInValue( foregroundLabel ) unbinThresh.SetOutValue( backgroundLabel ) unbinThresh.Update() image.DeepCopy(unbinThresh.GetOutput())
def performInitialization(self, image, lowerThreshold, upperThreshold, sourceSeedIds, targetSeedIds, ignoreSideBranches=0): ''' ''' # import the vmtk libraries try: import vtkvmtkSegmentationPython as vtkvmtkSegmentation except ImportError: logging.error("Unable to import the SlicerVmtk libraries") cast = vtk.vtkImageCast() cast.SetInputData(image) cast.SetOutputScalarTypeToFloat() cast.Update() image = cast.GetOutput() scalarRange = image.GetScalarRange() imageDimensions = image.GetDimensions() maxImageDimensions = max(imageDimensions) threshold = vtk.vtkImageThreshold() threshold.SetInputData(image) threshold.ThresholdBetween(lowerThreshold, upperThreshold) threshold.ReplaceInOff() threshold.ReplaceOutOn() threshold.SetOutValue(scalarRange[0] - scalarRange[1]) threshold.Update() thresholdedImage = threshold.GetOutput() scalarRange = thresholdedImage.GetScalarRange() shiftScale = vtk.vtkImageShiftScale() shiftScale.SetInputData(thresholdedImage) shiftScale.SetShift(-scalarRange[0]) shiftScale.SetScale(1.0 / (scalarRange[1] - scalarRange[0])) shiftScale.Update() speedImage = shiftScale.GetOutput() if ignoreSideBranches: # ignore sidebranches, use colliding fronts fastMarching = vtkvmtkSegmentation.vtkvmtkCollidingFrontsImageFilter( ) fastMarching.SetInputData(speedImage) fastMarching.SetSeeds1(sourceSeedIds) fastMarching.SetSeeds2(targetSeedIds) fastMarching.ApplyConnectivityOn() fastMarching.StopOnTargetsOn() fastMarching.Update() subtract = vtk.vtkImageMathematics() subtract.SetInputData(fastMarching.GetOutput()) subtract.SetOperationToAddConstant() subtract.SetConstantC(-10 * fastMarching.GetNegativeEpsilon()) subtract.Update() else: fastMarching = vtkvmtkSegmentation.vtkvmtkFastMarchingUpwindGradientImageFilter( ) fastMarching.SetInputData(speedImage) fastMarching.SetSeeds(sourceSeedIds) fastMarching.GenerateGradientImageOn() fastMarching.SetTargetOffset(0.0) fastMarching.SetTargets(targetSeedIds) if targetSeedIds.GetNumberOfIds() > 0: fastMarching.SetTargetReachedModeToOneTarget() else: fastMarching.SetTargetReachedModeToNoTargets() fastMarching.Update() if targetSeedIds.GetNumberOfIds() > 0: subtract = vtk.vtkImageMathematics() subtract.SetInputData(fastMarching.GetOutput()) subtract.SetOperationToAddConstant() subtract.SetConstantC(-fastMarching.GetTargetValue()) subtract.Update() else: subtract = vtk.vtkImageThreshold() subtract.SetInputData(fastMarching.GetOutput()) subtract.ThresholdByLower(2000) # TODO find robuste value subtract.ReplaceInOff() subtract.ReplaceOutOn() subtract.SetOutValue(-1) subtract.Update() outImageData = vtk.vtkImageData() outImageData.DeepCopy(subtract.GetOutput()) return outImageData
def getSmallestSegment(self): import numpy self.keys = ("Index", "Count", "Volume mm^3", "Volume cc", "Min", "Max", "Mean", "StdDev") cubicMMPerVoxel = reduce(lambda x, y: x * y, self.labelNode.GetSpacing()) ccPerCubicMM = 0.001 #geting a set of labels from a label map labels = self.getLabelsFromLabelMap(self.labelNode) print "NON - ZERO LABELS-----------------------------" print labels # TODO: progress and status updates # this->InvokeEvent(vtkLabelStatisticsLogic::StartLabelStats, (void*)"start label stats") self.labelStats = {} self.labelStats['Labels'] = [] stataccum = vtk.vtkImageAccumulate() stataccum.SetInput(self.labelNode.GetImageData()) stataccum.Update() lo = int(stataccum.GetMin()[0]) hi = int(stataccum.GetMax()[0]) aux1 = 999999999999999999999999999999999 aux2 = 999999999999999999999999999999999 smallestLabel = 0 segmentCount = 0 #This loop finds the most pathological segment(the smallest one) for i in xrange(lo, hi + 1): print i thresholder = vtk.vtkImageThreshold() thresholder.SetInput(self.labelNode.GetImageData()) thresholder.SetInValue(1) thresholder.SetOutValue(0) thresholder.ReplaceOutOn() thresholder.ThresholdBetween(i, i) thresholder.SetOutputScalarType( self.grayscaleNode.GetImageData().GetScalarType()) thresholder.Update() # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.25"); # use vtk's statistics class with the binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() stencil.SetInput(thresholder.GetOutput()) stencil.ThresholdBetween(1, 1) # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.5") self.stat = vtk.vtkImageAccumulate() stat1 = vtk.vtkImageAccumulate() stat1.SetInput(self.grayscaleNode.GetImageData()) stat1.SetStencil(stencil.GetOutput()) stat1.Update() # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.75") if stat1.GetVoxelCount() > 0: # add an entry to the LabelStats list self.labelStats["Labels"].append(i) self.labelStats[i, "Index"] = i self.labelStats[i, "Count"] = stat1.GetVoxelCount() print stat1.GetVoxelCount() self.labelStats[i, "Volume mm^3"] = self.labelStats[ i, "Count"] * cubicMMPerVoxel self.labelStats[i, "Volume cc"] = self.labelStats[ i, "Volume mm^3"] * ccPerCubicMM self.labelStats[i, "Min"] = stat1.GetMin()[0] self.labelStats[i, "Max"] = stat1.GetMax()[0] self.labelStats[i, "Mean"] = stat1.GetMean()[0] self.labelStats[i, "StdDev"] = stat1.GetStandardDeviation()[0] aux1 = stat1.GetVoxelCount() segmentCount = i self.segmentCount = i if aux1 < aux2: aux2 = aux1 smallestLabel = i print "el menor" print aux2 print smallestLabel print "numero total de segmentos" print segmentCount # Looking for the segment next to the most pathological one ar = slicer.util.array('*label') w = numpy.transpose(numpy.where(ar == smallestLabel)) self.smallestSegmentMatrix = w lenght = len(w) - 1 self.sSegmentIJK = w[0] sSegmentTopSlice = w[lenght][0] sSegmentBottomSlice = w[0][0] self.sSegmentTopSlice = w[lenght][0] self.sSegmentBottomSlice = w[0][0] print sSegmentTopSlice print sSegmentBottomSlice closeSegmentBot = 0 csbMatrix = 0 closeSegmentTop = 0 cstMatrix = 0 for c in xrange(2, segmentCount): w = numpy.transpose(numpy.where(ar == c)) m1 = sSegmentBottomSlice - 2 m2 = sSegmentTopSlice + 2 laux = len(w) - 1 if (w[0][0] == m2): print "segmento cercano inferior" print c print w closeSegmentBot = c csbMatrix = w if (w[laux][0] == m1): print "segmento cercano superior" print c closeSegmentTop = c cstMatrix = w self.closeSegmentBottomMatrix = csbMatrix self.closeSegmentTopMatrix = cstMatrix
def removeIslands(self): # # change the label values based on the parameter node # if not self.sliceLogic: self.sliceLogic = self.editUtil.getSliceLogic() parameterNode = self.editUtil.getParameterNode() minimumSize = int(parameterNode.GetParameter("IslandEffect,minimumSize")) fullyConnected = bool(parameterNode.GetParameter("IslandEffect,fullyConnected")) label = self.editUtil.getLabel() # first, create an inverse binary version of the image # so that islands inside segemented object will be detected, along # with a big island of the background preThresh = vtk.vtkImageThreshold() preThresh.SetInValue( 0 ) preThresh.SetOutValue( 1 ) preThresh.ReplaceInOn() preThresh.ReplaceOutOn() preThresh.ThresholdBetween( label,label ) preThresh.SetInput( self.getScopedLabelInput() ) preThresh.SetOutputScalarTypeToUnsignedLong() # now identify the islands in the inverted volume # and find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() islandMath.SetInput( preThresh.GetOutput() ) islandMath.SetFullyConnected( fullyConnected ) islandMath.SetMinimumSize( minimumSize ) # TODO: $this setProgressFilter $islandMath "Calculating Islands..." islandMath.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount print( "%d islands created (%d ignored)" % (islandCount, ignoredIslands) ) if islandCount == 0: return bgPixel = self.findNonZeroBorderPixel(islandMath.GetOutput()) # now rethreshold so that everything which is not background becomes the label postThresh = vtk.vtkImageThreshold() postThresh.SetInValue( 0 ) postThresh.SetOutValue( label ) postThresh.ReplaceInOn() postThresh.ReplaceOutOn() postThresh.ThresholdBetween( bgPixel, bgPixel ) postThresh.SetOutputScalarTypeToShort() postThresh.SetInput( islandMath.GetOutput() ) postThresh.SetOutput( self.getScopedLabelOutput() ) # TODO $this setProgressFilter $postThresh "Applying to Label Map..." postThresh.Update() self.applyScopedLabel() if False: # some code for debugging - leave it in layerLogic = self.sliceLogic.GetLabelLayer() labelNode = layerLogic.GetVolumeNode() volumesLogic = slicer.modules.volumes.logic() thresh1 = volumesLogic.CloneVolume(slicer.mrmlScene, labelNode, 'thres1') islands = volumesLogic.CloneVolume(slicer.mrmlScene, labelNode, 'islands') thresh2 = volumesLogic.CloneVolume(slicer.mrmlScene, labelNode, 'thres2') cast = vtk.vtkImageCast() cast.SetOutputScalarTypeToShort() cast.SetInput(preThresh.GetOutput()) cast.Update() thresh1.SetAndObserveImageData(cast.GetOutput()) cast2 = vtk.vtkImageCast() cast2.SetOutputScalarTypeToShort() cast2.SetInput(islandMath.GetOutput()) cast2.Update() islands.SetAndObserveImageData(cast2.GetOutput()) thresh2.SetAndObserveImageData(postThresh.GetOutput())
def __init__(self, grayscaleNode, labelNode, fileName=None): import numpy self.keys = ("Index", "Count", "Volume", "Min", "Max", "Mean", "StdDev") cubicMMPerVoxel = reduce(lambda x,y: x*y, labelNode.GetSpacing()) # TODO: progress and status updates # this->InvokeEvent(vtkLabelStatisticsLogic::StartLabelStats, (void*)"start label stats") self.labelStats = {} self.labelStats['Labels'] = [] stataccum = vtk.vtkImageAccumulate() stataccum.SetInput(labelNode.GetImageData()) stataccum.Update() lo = int(stataccum.GetMin()[0]) hi = int(stataccum.GetMax()[0]) for i in xrange(lo,hi+1): # this->SetProgress((float)i/hi); # std::string event_message = "Label "; std::stringstream s; s << i; event_message.append(s.str()); # this->InvokeEvent(vtkLabelStatisticsLogic::LabelStatsOuterLoop, (void*)event_message.c_str()); # logic copied from slicer3 LabelStatistics # to create the binary volume of the label # //logic copied from slicer2 LabelStatistics MaskStat # // create the binary volume of the label thresholder = vtk.vtkImageThreshold() thresholder.SetInput(labelNode.GetImageData()) thresholder.SetInValue(1) thresholder.SetOutValue(0) thresholder.ReplaceOutOn() thresholder.ThresholdBetween(i,i) thresholder.SetOutputScalarType(grayscaleNode.GetImageData().GetScalarType()) thresholder.Update() # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.25"); # use vtk's statistics class with the binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() stencil.SetInput(thresholder.GetOutput()) stencil.ThresholdBetween(1, 1) # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.5") stat1 = vtk.vtkImageAccumulate() stat1.SetInput(grayscaleNode.GetImageData()) stat1.SetStencil(stencil.GetOutput()) stat1.Update() # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.75") if stat1.GetVoxelCount() > 0: # add an entry to the LabelStats list self.labelStats["Labels"].append(i) self.labelStats[i,"Index"] = i self.labelStats[i,"Count"] = stat1.GetVoxelCount() self.labelStats[i,"Volume"] = self.labelStats[i,"Count"] * cubicMMPerVoxel self.labelStats[i,"Min"] = stat1.GetMin()[0] self.labelStats[i,"Max"] = stat1.GetMax()[0] self.labelStats[i,"Mean"] = stat1.GetMean()[0] self.labelStats[i,"StdDev"] = stat1.GetStandardDeviation()[0]
def __init__(self, grayscaleNode, labelNode, KEV120, KEV80, fileName=None): #import numpy self.keys = ("Index", "Label Name", "Agatston Score", "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'] = [] stataccum = vtk.vtkImageAccumulate() if vtk.VTK_MAJOR_VERSION <= 5: stataccum.SetInput(labelNode.GetImageData()) else: stataccum.SetInputConnection(labelNode.GetImageDataConnection()) stataccum.Update() lo = int(stataccum.GetMin()[0]) hi = int(stataccum.GetMax()[0]) displayNode = labelNode.GetDisplayNode() colorNode = displayNode.GetColorNode() self.labelNode = labelNode self.grayscaleNode = grayscaleNode self.KEV80 = KEV80 self.KEV120 = KEV120 self.calculateAgatstonScores() for i in xrange(lo,7): # skip indices 0 (background) and 1 (default threshold pixels) # because these are not calcium and do not have an Agatston score if i == 0 or i == 1: continue # this->SetProgress((float)i/hi); # std::string event_message = "Label "; std::stringstream s; s << i; event_message.append(s.str()); # this->InvokeEvent(vtkLabelStatisticsLogic::LabelStatsOuterLoop, (void*)event_message.c_str()); # logic copied from slicer3 LabelStatistics # to create the binary volume of the label # //logic copied from slicer2 LabelStatistics MaskStat # // create the binary volume of the label thresholder = vtk.vtkImageThreshold() if vtk.VTK_MAJOR_VERSION <= 5: thresholder.SetInput(labelNode.GetImageData()) else: thresholder.SetInputConnection(labelNode.GetImageDataConnection()) thresholder.SetInValue(1) thresholder.SetOutValue(0) thresholder.ReplaceOutOn() if i != 6: thresholder.ThresholdBetween(i,i) else: # label 6 is the total calcium pixels in labels 2, 3, 4 and 5 thresholder.ThresholdBetween(2,5) thresholder.SetOutputScalarType(grayscaleNode.GetImageData().GetScalarType()) thresholder.Update() # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.25"); # use vtk's statistics class with the binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() if vtk.VTK_MAJOR_VERSION <= 5: stencil.SetInput(thresholder.GetOutput()) else: stencil.SetInputConnection(thresholder.GetOutputPort()) stencil.ThresholdBetween(1, 1) # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.5") stat1 = vtk.vtkImageAccumulate() if vtk.VTK_MAJOR_VERSION <= 5: stat1.SetInput(grayscaleNode.GetImageData()) stat1.SetStencil(stencil.GetOutput()) else: stat1.SetInputConnection(grayscaleNode.GetImageDataConnection()) stencil.Update() stat1.SetStencilData(stencil.GetOutput()) stat1.Update() # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.75") if stat1.GetVoxelCount() > 0: # add an entry to the LabelStats list self.labelStats["Labels"].append(i) self.labelStats[i,"Index"] = i self.labelStats[i,"Label Name"] = colorNode.GetColorName(i) self.labelStats[i,"Agatston Score"] = self.AgatstonScoresPerLabel[i] self.labelStats[i,"Count"] = stat1.GetVoxelCount() self.labelStats[i,"Volume mm^3"] = self.labelStats[i,"Count"] * cubicMMPerVoxel self.labelStats[i,"Volume cc"] = self.labelStats[i,"Volume mm^3"] * ccPerCubicMM self.labelStats[i,"Min"] = stat1.GetMin()[0] self.labelStats[i,"Max"] = stat1.GetMax()[0] self.labelStats[i,"Mean"] = stat1.GetMean()[0] self.labelStats[i,"StdDev"] = stat1.GetStandardDeviation()[0]
def removeIslandsMorphologyDecruft(self, image, foregroundLabel, backgroundLabel, iterations=1): # # make binary mask foregroundLabel->1, backgroundLabel->0 # binThresh = vtk.vtkImageThreshold() if vtk.VTK_MAJOR_VERSION <= 5: binThresh.SetInput(image) else: binThresh.SetInputData(image) binThresh.ThresholdBetween(foregroundLabel, foregroundLabel) binThresh.SetInValue(1) binThresh.SetOutValue(0) binThresh.Update() # # first, erode iterations number of times # eroder = slicer.vtkImageErode() eroderImage = vtk.vtkImageData() eroderImage.DeepCopy(binThresh.GetOutput()) if vtk.VTK_MAJOR_VERSION <= 5: eroder.SetInput(eroderImage) else: eroder.SetInputData(eroderImage) for iteration in range(iterations): eroder.SetForeground(1) eroder.SetBackground(0) eroder.SetNeighborTo8() eroder.Update() eroderImage.DeepCopy(eroder.GetOutput()) # # now save only islands bigger than a specified size # # note that island operation happens in unsigned long space # but the slicer editor works in Short castIn = vtk.vtkImageCast() if vtk.VTK_MAJOR_VERSION <= 5: castIn.SetInput(eroderImage) else: castIn.SetInputConnection(eroder.GetInputConnection(0, 0)) castIn.SetOutputScalarTypeToUnsignedLong() # now identify the islands in the inverted volume # and find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() if vtk.VTK_MAJOR_VERSION <= 5: islandMath.SetInput(castIn.GetOutput()) else: islandMath.SetInputConnection(castIn.GetOutputPort()) islandMath.SetFullyConnected(self.fullyConnected) islandMath.SetMinimumSize(self.minimumSize) # note that island operation happens in unsigned long space # but the slicer editor works in Short castOut = vtk.vtkImageCast() if vtk.VTK_MAJOR_VERSION <= 5: castOut.SetInput(islandMath.GetOutput()) else: castOut.SetInputConnection(islandMath.GetOutputPort()) castOut.SetOutputScalarTypeToShort() castOut.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount print("%d islands created (%d ignored)" % (islandCount, ignoredIslands)) # # now map everything back to 0 and 1 # thresh = vtk.vtkImageThreshold() if vtk.VTK_MAJOR_VERSION <= 5: thresh.SetInput(castOut.GetOutput()) else: thresh.SetInputConnection(castOut.GetOutputPort()) thresh.ThresholdByUpper(1) thresh.SetInValue(1) thresh.SetOutValue(0) thresh.Update() # # now, dilate back (erode background) iterations_plus_one number of times # dilater = slicer.vtkImageErode() dilaterImage = vtk.vtkImageData() dilaterImage.DeepCopy(thresh.GetOutput()) if vtk.VTK_MAJOR_VERSION <= 5: dilater.SetInput(dilaterImage) else: dilater.SetInputData(dilaterImage) for iteration in range(1 + iterations): dilater.SetForeground(0) dilater.SetBackground(1) dilater.SetNeighborTo8() dilater.Update() dilaterImage.DeepCopy(dilater.GetOutput()) # # only keep pixels in both original and dilated result # logic = vtk.vtkImageLogic() if vtk.VTK_MAJOR_VERSION <= 5: logic.SetInput1(dilaterImage) logic.SetInput2(binThresh.GetOutput()) else: logic.SetInputConnection(0, dilater.GetInputConnection(0, 0)) logic.SetInputConnection(1, binThresh.GetOutputPort()) # if foregroundLabel == 0: # logic.SetOperationToNand() # else: logic.SetOperationToAnd() logic.SetOutputTrueValue(1) logic.Update() # # convert from binary mask to 1->foregroundLabel, 0->backgroundLabel # unbinThresh = vtk.vtkImageThreshold() if vtk.VTK_MAJOR_VERSION <= 5: unbinThresh.SetInput(logic.GetOutput()) else: unbinThresh.SetInputConnection(logic.GetOutputPort()) unbinThresh.ThresholdBetween(1, 1) unbinThresh.SetInValue(foregroundLabel) unbinThresh.SetOutValue(backgroundLabel) unbinThresh.Update() image.DeepCopy(unbinThresh.GetOutput())
def __init__(self, grayscaleNode, labelNode, fileName=None): #import numpy self.keys = ("Type", "Percentage", "Volume liters", "Mean", "StdDev", "Min", "Max", ) self.types = ("Normal", "PS", "PL", "CL1", "CL2", "CL3") cubicMMPerVoxel = reduce(lambda x,y: x*y, labelNode.GetSpacing()) litersPerCubicMM = 0.000001 # TODO: progress and status updates # this->InvokeEvent(vtkEmphysemaSubtypesLogic::StartLabelStats, (void*)"start label stats") self.labelStats = {} self.labelStats['Labels'] = [] stataccum = vtk.vtkImageAccumulate() stataccum.SetInput(labelNode.GetImageData()) stataccum.Update() lo = 1 hi = 6 for i in xrange(lo,hi+1): # this->SetProgress((float)i/hi); # std::string event_message = "Label "; std::stringstream s; s << i; event_message.append(s.str()); # this->InvokeEvent(vtkEmphysemaSubtypesLogic::LabelStatsOuterLoop, (void*)event_message.c_str()); # logic copied from slicer3 EmphysemaSubtypes # to create the binary volume of the label # //logic copied from slicer2 EmphysemaSubtypes MaskStat # // create the binary volume of the label thresholder = vtk.vtkImageThreshold() thresholder.SetInput(labelNode.GetImageData()) thresholder.SetInValue(1) thresholder.SetOutValue(0) thresholder.ReplaceOutOn() thresholder.ThresholdBetween(i,i) thresholder.SetOutputScalarType(grayscaleNode.GetImageData().GetScalarType()) thresholder.Update() # this.InvokeEvent(vtkEmphysemaSubtypesLogic::LabelStatsInnerLoop, (void*)"0.25"); # use vtk's statistics class with the binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() stencil.SetInput(thresholder.GetOutput()) stencil.ThresholdBetween(1, 1) # this.InvokeEvent(vtkEmphysemaSubtypesLogic::LabelStatsInnerLoop, (void*)"0.5") stat1 = vtk.vtkImageAccumulate() stat1.SetInput(grayscaleNode.GetImageData()) stat1.SetStencil(stencil.GetOutput()) stat1.Update() # this.InvokeEvent(vtkEmphysemaSubtypesLogic::LabelStatsInnerLoop, (void*)"0.75") if stat1.GetVoxelCount() > 0: # add an entry to the LabelStats list self.labelStats["Labels"].append(i) self.labelStats[i,"Type"] = self.types[i-1] self.labelStats[i,"Percentage"] = float(stat1.GetVoxelCount()) self.labelStats[i,"Volume liters"] = float(stat1.GetVoxelCount() * cubicMMPerVoxel * litersPerCubicMM) self.labelStats[i,"Min"] = float(stat1.GetMin()[0]) self.labelStats[i,"Max"] = float(stat1.GetMax()[0]) self.labelStats[i,"Mean"] = float(stat1.GetMean()[0]) self.labelStats[i,"StdDev"] = float(stat1.GetStandardDeviation()[0]) # this.InvokeEvent(vtkEmphysemaSubtypesLogic::LabelStatsInnerLoop, (void*)"1") # this.InvokeEvent(vtkEmphysemaSubtypesLogic::EndLabelStats, (void*)"end label stats") total=0 for i in xrange(lo,hi+1): total = total + self.labelStats[i,"Percentage"] for i in xrange(lo,hi+1): self.labelStats[i,"Percentage"] = float(100.0 * self.labelStats[i,"Percentage"]/total)
def onHelloWorldButtonClicked(self): scene = slicer.mrmlScene inputModel = self.inputSelector.currentNode() bounds = [0, 0, 0, 0, 0, 0] inputModel.GetBounds(bounds) print('Model Name is:') print(inputModel.GetName()) X = bounds[1] - bounds[0] Y = bounds[3] - bounds[2] Z = bounds[5] - bounds[4] mid = (bounds[0] + X / 2, bounds[2] + Y / 2, bounds[4] + Z / 2) X_thick = .1 #TODO resolution input Y_thick = .1 #TODO resolution input Z_thick = .1 #TODO resolution input z_slices = int(math.ceil(Z / Z_thick)) y_slices = int(math.ceil(Y / Y_thick)) x_slices = int(math.ceil(X / X_thick)) x_thick = X / x_slices y_thick = Y / y_slices z_thick = Z / z_slices print('number of slices') print((x_slices, y_slices, z_slices)) print('midpoint') print(mid) #TODO Bounding box calculation imageSize = [x_slices, y_slices, z_slices] imageSpacing = [x_thick, y_thick, z_thick] voxelType = vtk.VTK_UNSIGNED_CHAR imageData = vtk.vtkImageData() imageData.SetDimensions(imageSize) imageData.AllocateScalars(voxelType, 1) thresholder = vtk.vtkImageThreshold() thresholder.SetInputData(imageData) thresholder.SetInValue(1) thresholder.SetOutValue(1) # Create volume node volumeNode = slicer.vtkMRMLScalarVolumeNode() volumeNode.SetSpacing(imageSpacing) volumeNode.SetImageDataConnection(thresholder.GetOutputPort()) # Add volume to scene slicer.mrmlScene.AddNode(volumeNode) displayNode = slicer.vtkMRMLScalarVolumeDisplayNode() slicer.mrmlScene.AddNode(displayNode) colorNode = slicer.util.getNode('Grey') displayNode.SetAndObserveColorNodeID(colorNode.GetID()) volumeNode.SetAndObserveDisplayNodeID(displayNode.GetID()) volumeNode.CreateDefaultStorageNode() #Transform the Volume to Fit Around the Model transform = slicer.vtkMRMLLinearTransformNode() scene.AddNode(transform) volumeNode.SetAndObserveTransformNodeID(transform.GetID()) vTransform = vtk.vtkTransform() vTransform.Translate( (-X / 2 + mid[0], -Y / 2 + mid[1], -Z / 2 + mid[2])) transform.SetAndObserveMatrixTransformToParent(vTransform.GetMatrix()) #Create a segmentation Node segmentationNode = slicer.vtkMRMLSegmentationNode() slicer.mrmlScene.AddNode(segmentationNode) segmentationNode.CreateDefaultDisplayNodes() segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode( volumeNode) #Add the model as a segmentation #sphereSource = vtk.vtkSphereSource() #sphereSource.SetRadius(10) #sphereSource.SetCenter(6,30,28) #sphereSource.Update() #segmentationNode.AddSegmentFromClosedSurfaceRepresentation(sphereSource.GetOutput(), "Test") segmentID = segmentationNode.GetSegmentation().GenerateUniqueSegmentID( "Test") segmentationNode.AddSegmentFromClosedSurfaceRepresentation( inputModel.GetPolyData(), segmentID) #TODO, Unique ID segmentationNode.SetMasterRepresentationToBinaryLabelmap() modelLabelMap = segmentationNode.GetBinaryLabelmapRepresentation( segmentID) #TODO Unique ID segmentationNode.SetMasterRepresentationToBinaryLabelmap() shape = list(modelLabelMap.GetDimensions()) shape.reverse() #why reverse? labelArray = vtk.util.numpy_support.vtk_to_numpy( modelLabelMap.GetPointData().GetScalars()).reshape(shape) for n in range(1, shape[0] - 1): labelArray[n, :, :] = numpy.maximum(labelArray[n, :, :], labelArray[n - 1, :, :]) outputPolyData = vtk.vtkPolyData() slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentClosedSurfaceRepresentation( segmentationNode, segmentID, outputPolyData) # Create model node model = slicer.vtkMRMLModelNode() model.SetScene(scene) model.SetName(scene.GenerateUniqueName("Model_Undercuts_Removed")) model.SetAndObservePolyData(outputPolyData) # Create display node modelDisplay = slicer.vtkMRMLModelDisplayNode() modelDisplay.SetColor(1, 1, 0) # yellow modelDisplay.SetBackfaceCulling(0) modelDisplay.SetScene(scene) scene.AddNode(modelDisplay) model.SetAndObserveDisplayNodeID(modelDisplay.GetID()) # Add to scene scene.AddNode(model)
def createROIslow(self): labelim=vtk.vtkImageData() inputImage=self.volume.GetImageData() labelImage=self.label.GetImageData() IJKToRAS = vtk.vtkMatrix4x4() self.volume.GetIJKToRASMatrix(IJKToRAS) thresh = vtk.vtkImageThreshold() thresh.SetInputData(inputImage) lo, hi = inputImage.GetScalarRange() minimum=lo + 0.25 * (hi-lo) maximum=hi thresh.ThresholdBetween(minimum, maximum) thresh.SetInValue(1) thresh.SetOutValue(0) thresh.SetOutputScalarType(vtk.VTK_SHORT) thresh.Modified() thresh.Update() node=slicer.vtkMRMLScalarVolumeNode() node.SetIJKToRASMatrix(IJKToRAS) node.SetAndObserveImageData(thresh.GetOutput()) slicer.mrmlScene.AddNode(node) node.SetName('tmp') qu=QCLib.QCUtil() rect=qu.minRectangle(node) slicer.mrmlScene.RemoveNode(node) dim1=inputImage.GetDimensions()[0] dim2=inputImage.GetDimensions()[1] dim3=inputImage.GetDimensions()[2] # coln.SetColor(0,'bg',0,0,0) # coln.SetColor(1,'n',1,0,0) # coln.SetColor(2,'ne',0,1,0) # coln.SetColor(3,'nw',0,0,1) # coln.SetColor(4,'e',1,1,0) # coln.SetColor(5,'w',1,0,1) # coln.SetColor(6,'s',0,1,1) # coln.SetColor(7,'se',1,1,1) # coln.SetColor(8,'sw',1,0.5,0) for x in range(dim1): for y in range(dim2): for z in range(dim3): VOIn=[rect['xmin'].values()[z],rect['xmax'].values()[z],1,rect['ymin'].values()[z]] VOIne=[rect['xmax'].values()[z],dim1-1,1,rect['ymin'].values()[z]] VOInw=[1,rect['xmin'].values()[z],1,rect['ymin'].values()[z]] VOIe=[rect['xmax'].values()[z],dim1-1,rect['ymin'].values()[z],rect['ymax'].values()[z]] VOIw=[1,rect['xmin'].values()[z],rect['ymin'].values()[z],rect['ymax'].values()[z]] VOIs=[rect['xmin'].values()[z],rect['xmax'].values()[z],rect['ymax'].values()[z],dim2-1] VOIse=[rect['xmax'].values()[z],dim1-1,rect['ymax'].values()[z],dim2-1] VOIsw=[1,rect['xmin'].values()[z],rect['ymax'].values()[z],dim2-1] if (x>=VOIn[0] and x<=VOIn[1] and y>=VOIn[2] and y<=VOIn[3]): labelImage.SetScalarComponentFromDouble(x,y,z,0,1) elif (x>=VOIne[0] and x<=VOIne[1] and y>=VOIne[2] and y<=VOIne[3]): labelImage.SetScalarComponentFromDouble(x,y,z,0,2) elif (x>=VOInw[0] and x<=VOInw[1] and y>=VOInw[2] and y<=VOInw[3]): labelImage.SetScalarComponentFromDouble(x,y,z,0,3) elif (x>=VOIe[0] and x<=VOIe[1] and y>=VOIe[2] and y<=VOIe[3]): labelImage.SetScalarComponentFromDouble(x,y,z,0,4) elif (x>=VOIw[0] and x<=VOIw[1] and y>=VOIw[2] and y<=VOIw[3]): labelImage.SetScalarComponentFromDouble(x,y,z,0,5) elif (x>=VOIs[0] and x<=VOIs[1] and y>=VOIs[2] and y<=VOIs[3]): labelImage.SetScalarComponentFromDouble(x,y,z,0,6) elif (x>=VOIse[0] and x<=VOIse[1] and y>=VOIse[2] and y<=VOIse[3]): labelImage.SetScalarComponentFromDouble(x,y,z,0,7) elif (x>=VOIsw[0] and x<=VOIsw[1] and y>=VOIsw[2] and y<=VOIsw[3]): labelImage.SetScalarComponentFromDouble(x,y,z,0,8)
def createROIvtk(self): labelim=vtk.vtkImageData() inputImage=self.volume.GetImageData() labelImage=self.label.GetImageData() IJKToRAS = vtk.vtkMatrix4x4() self.volume.GetIJKToRASMatrix(IJKToRAS) self.label.SetIJKToRASMatrix(IJKToRAS) thresh = vtk.vtkImageThreshold() thresh.SetInputData(inputImage) lo, hi = inputImage.GetScalarRange() minimum=lo + 0.25 * (hi-lo) maximum=hi thresh.ThresholdBetween(minimum, maximum) thresh.SetInValue(1) thresh.SetOutValue(0) thresh.SetOutputScalarType(vtk.VTK_SHORT) thresh.Modified() thresh.Update() node=slicer.vtkMRMLScalarVolumeNode() node.SetIJKToRASMatrix(IJKToRAS) node.SetAndObserveImageData(thresh.GetOutput()) slicer.mrmlScene.AddNode(node) node.SetName('tmp') qu=QCLib.QCUtil() rect=qu.minRectangle(node) slicer.mrmlScene.RemoveNode(node) thresh.ThresholdBetween(hi+1, hi+1) thresh.Modified() thresh.Update() labelImage.DeepCopy(thresh.GetOutput()) # coln.SetColor(0,'bg',0,0,0) # coln.SetColor(1,'n',1,0,0) # coln.SetColor(2,'ne',0,1,0) # coln.SetColor(3,'nw',0,0,1) # coln.SetColor(4,'e',1,1,0) # coln.SetColor(5,'w',1,0,1) # coln.SetColor(6,'s',0,1,1) # coln.SetColor(7,'se',1,1,1) # coln.SetColor(8,'sw',1,0.5,0) north=slicer.vtkFillVOIImageFilter() north.SetfillValue(1) north.SetInputData(labelImage) northeast=slicer.vtkFillVOIImageFilter() northeast.SetfillValue(2) northeast.SetInputData(labelImage) northwest=slicer.vtkFillVOIImageFilter() northwest.SetfillValue(3) northwest.SetInputData(labelImage) east=slicer.vtkFillVOIImageFilter() east.SetfillValue(4) east.SetInputData(labelImage) west=slicer.vtkFillVOIImageFilter() west.SetfillValue(5) west.SetInputData(labelImage) south=slicer.vtkFillVOIImageFilter() south.SetfillValue(6) south.SetInputData(labelImage) southeast=slicer.vtkFillVOIImageFilter() southeast.SetfillValue(7) southeast.SetInputData(labelImage) southwest=slicer.vtkFillVOIImageFilter() southwest.SetfillValue(8) southwest.SetInputData(labelImage) dim1=inputImage.GetDimensions()[0] dim2=inputImage.GetDimensions()[1] dim3=inputImage.GetDimensions()[2] for z in range(dim3): VOIn=[rect['xmin'].values()[z],rect['xmax'].values()[z],1,rect['ymin'].values()[z],z,z] VOIne=[rect['xmax'].values()[z],dim1-1,1,rect['ymin'].values()[z],z,z] VOInw=[1,rect['xmin'].values()[z],1,rect['ymin'].values()[z],z,z] VOIe=[rect['xmax'].values()[z],dim1-1,rect['ymin'].values()[z],rect['ymax'].values()[z],z,z] VOIw=[1,rect['xmin'].values()[z],rect['ymin'].values()[z],rect['ymax'].values()[z],z,z] VOIs=[rect['xmin'].values()[z],rect['xmax'].values()[z],rect['ymax'].values()[z],dim2-1,z,z] VOIse=[rect['xmax'].values()[z],dim1-1,rect['ymax'].values()[z],dim2-1,z,z] VOIsw=[1,rect['xmin'].values()[z],rect['ymax'].values()[z],dim2-1,z,z] north.AddVOI(VOIn) northeast.AddVOI(VOIne) northwest.AddVOI(VOInw) east.AddVOI(VOIe) west.AddVOI(VOIw) south.AddVOI(VOIs) southeast.AddVOI(VOIse) southwest.AddVOI(VOIsw) north.Update() labelImage.DeepCopy(north.GetOutput()) northeast.Update() labelImage.DeepCopy(northeast.GetOutput()) northwest.Update() labelImage.DeepCopy(northwest.GetOutput()) east.Update() labelImage.DeepCopy(east.GetOutput()) west.Update() labelImage.DeepCopy(west.GetOutput()) south.Update() labelImage.DeepCopy(south.GetOutput()) southeast.Update() labelImage.DeepCopy(southeast.GetOutput()) southwest.Update() labelImage.DeepCopy(southwest.GetOutput())
def PolyDataToImageData(self, inputPolydata_Ras, referenceVolumeNode_Ras, inVal=100, outVal=0): """ We take in an polydata and convert it to an new image data , withing the Reference Voulume node the reference volume node is cleared with a threshold because originally the volume may contain alot of noisy pixels PARAM: inputPolydata_Ras: Polydata we are looking to conver vtkPolydata() PARAM: refernceVolumeNode_Ras vtkMRMLScalarVolumeNode() RETURN : vtkImageData """ """ Transform the polydata from ras to ijk using the referenceVolumeNode """ #inputPolydataTriangulated_Ijk=polyToImage.GetOutput() transformPolydataFilter = vtk.vtkTransformPolyDataFilter() rasToIjkMatrix = vtk.vtkMatrix4x4() referenceVolumeNode_Ras.GetRASToIJKMatrix(rasToIjkMatrix) rasToIjkTransform = vtk.vtkTransform() rasToIjkTransform.SetMatrix(rasToIjkMatrix) transformPolydataFilter.SetTransform(rasToIjkTransform) transformPolydataFilter.SetInputData(inputPolydata_Ras) transformPolydataFilter.Update() inputPolydata_Ijk = transformPolydataFilter.GetOutput() normalsFunction = vtk.vtkPolyDataNormals() normalsFunction.SetInputData(inputPolydata_Ijk) normalsFunction.ConsistencyOn() trigFilter = vtk.vtkTriangleFilter() trigFilter.SetInputConnection(normalsFunction.GetOutputPort()) stripper = vtk.vtkStripper() stripper.SetInputConnection(trigFilter.GetOutputPort()) stripper.Update() inputPolydataTriangulated_Ijk = stripper.GetOutput() # Clone reference image and clear it referenceImage_Ijk = referenceVolumeNode_Ras.GetImageData() # Fill image with outVal (there is no volume Fill filter in VTK, therefore we need to use threshold filter) thresh = vtk.vtkImageThreshold() thresh.ReplaceInOn() thresh.ReplaceOutOn() thresh.SetInValue(outVal) thresh.SetOutValue(outVal) #thresh.SetOutputScalarType (vtk.VTK_UNSIGNED_CHAR) thresh.SetInputData(referenceImage_Ijk) thresh.Update() whiteImage_Ijk = thresh.GetOutput() # Convert polydata to stencil polyToImage = vtk.vtkPolyDataToImageStencil() polyToImage.SetInputData(inputPolydataTriangulated_Ijk) polyToImage.SetOutputSpacing(whiteImage_Ijk.GetSpacing()) polyToImage.SetOutputOrigin(whiteImage_Ijk.GetOrigin()) polyToImage.SetOutputWholeExtent(whiteImage_Ijk.GetExtent()) polyToImage.Update() imageStencil_Ijk = polyToImage.GetOutput() # Convert stencil to image imgstenc = vtk.vtkImageStencil() imgstenc.SetInputData(whiteImage_Ijk) imgstenc.SetStencilData(imageStencil_Ijk) imgstenc.ReverseStencilOn() imgstenc.SetBackgroundValue(inVal) imgstenc.Update() return imgstenc.GetOutput()
def test_LabelToDICOMSEGConverterRoundTrip(self): print("CTEST_FULL_OUTPUT") dir(slicer.modules) """ Load the data using DICOM module """ import os self.delayDisplay("Starting the DICOM test") # # first, get the data - a zip file of dicom data # import urllib downloads = (('http://slicer.kitware.com/midas3/download?items=10881', 'JANCT-CT.zip'), ) self.delayDisplay("Downloading") for url, name in downloads: filePath = slicer.app.temporaryPath + '/' + name if not os.path.exists(filePath) or os.stat(filePath).st_size == 0: self.delayDisplay('Requesting download %s from %s...\n' % (name, url)) urllib.urlretrieve(url, filePath) self.delayDisplay('Finished with download\n') reportingTempDir = slicer.app.temporaryPath + '/LabelToDICOMSEGConverter' qt.QDir().mkpath(reportingTempDir) dicomFilesDirectory = reportingTempDir + '/dicomFiles' self.cleanupDir(dicomFilesDirectory) qt.QDir().mkpath(dicomFilesDirectory) slicer.app.applicationLogic().Unzip(filePath, dicomFilesDirectory) try: self.delayDisplay("Switching to temp database directory") tempDatabaseDirectory = reportingTempDir + '/tempDICOMDatbase' qt.QDir().mkpath(tempDatabaseDirectory) self.cleanupDir(tempDatabaseDirectory) if slicer.dicomDatabase: self.originalDatabaseDirectory = os.path.split( slicer.dicomDatabase.databaseFilename)[0] else: self.originalDatabaseDirectory = None settings = qt.QSettings() settings.setValue('DatabaseDirectory', tempDatabaseDirectory) dicomWidget = slicer.modules.dicom.widgetRepresentation().self() dicomWidget.onDatabaseDirectoryChanged(tempDatabaseDirectory) self.delayDisplay('Importing DICOM') mainWindow = slicer.util.mainWindow() mainWindow.moduleSelector().selectModule('DICOM') self.importDICOM(slicer.dicomDatabase, dicomFilesDirectory) patient = slicer.dicomDatabase.patients()[0] studies = slicer.dicomDatabase.studiesForPatient(patient) series = [ slicer.dicomDatabase.seriesForStudy(study) for study in studies ] seriesUIDs = [uid for uidList in series for uid in uidList] dicomWidget.detailsPopup.offerLoadables(seriesUIDs, 'SeriesUIDList') dicomWidget.detailsPopup.examineForLoading() loadablesByPlugin = dicomWidget.detailsPopup.loadablesByPlugin self.delayDisplay('Loading Selection') dicomWidget.detailsPopup.loadCheckedLoadables() # initialize the module with the report and volume volumes = slicer.util.getNodes('vtkMRMLScalarVolumeNode*') self.assertTrue(len(volumes) == 1) (name, volume) = volumes.items()[0] self.delayDisplay('Loaded volume name %s' % volume.GetName()) self.delayDisplay('Configure Module') mainWindow = slicer.util.mainWindow() mainWindow.moduleSelector().selectModule( 'LabelToDICOMSEGConverter') module = slicer.modules.labeltodicomsegconverter.widgetRepresentation( ).self() # add label node volumesLogic = slicer.modules.volumes.logic() labelNode = volumesLogic.CreateAndAddLabelVolume( slicer.mrmlScene, volume, "Segmentation") labelNode.SetAttribute('AssociatedNodeID', volume.GetID()) labelDisplayNode = labelNode.GetDisplayNode() labelDisplayNode.SetAndObserveColorNodeID( 'vtkMRMLColorTableNodeFileGenericAnatomyColors.txt') image = volume.GetImageData() thresh = vtk.vtkImageThreshold() if vtk.vtkVersion().GetVTKMajorVersion() < 6: thresh.SetInput(image) else: thresh.SetInputData(image) thresh.ThresholdBetween(10, 400) thresh.SetInValue(10) thresh.SetOutValue(0) thresh.Update() labelNode.SetAndObserveImageData(thresh.GetOutput()) module.segmentationSelector.setCurrentNode(labelNode) module.volumeSelector.setCurrentNode(volume) self.delayDisplay('Input label initialized') module.outputDir = reportingTempDir + '/Output' # Save the report exportDir = reportingTempDir + '/Output' qt.QDir().mkpath(exportDir) self.cleanupDir(exportDir) module.onLabelExport() self.delayDisplay('Report saved') self.importDICOM(slicer.dicomDatabase, exportDir) slicer.mrmlScene.Clear(0) patient = slicer.dicomDatabase.patients()[0] studies = slicer.dicomDatabase.studiesForPatient(patient) series = [ slicer.dicomDatabase.seriesForStudy(study) for study in studies ] seriesUIDs = [uid for uidList in series for uid in uidList] dicomWidget.detailsPopup.offerLoadables(seriesUIDs, 'SeriesUIDList') dicomWidget.detailsPopup.examineForLoading() loadablesByPlugin = dicomWidget.detailsPopup.loadablesByPlugin self.delayDisplay('Wait', 10000) dicomWidget.detailsPopup.loadCheckedLoadables() volumes = slicer.util.getNodes('vtkMRMLLabelMapVolumeNode*') for n, v in volumes.items(): print('Label volume found: ' + v.GetID()) self.assertTrue(len(volumes) == 1) for name, volume in volumes.items(): image = volume.GetImageData() previousImage = thresh.GetOutput() diff = vtk.vtkImageDifference() if vtk.vtkVersion().GetVTKMajorVersion() < 6: diff.SetInput(thresh.GetOutput()) else: diff.SetInputData(thresh.GetOutput()) diff.SetImage(image) diff.Update() if diff.GetThresholdedError() > 1: self.delayDisplay('Reloaded image does not match') self.assertTrue(False) self.delayDisplay('Test passed') self.delayDisplay("Restoring original database directory") if self.originalDatabaseDirectory: dicomWidget.onDatabaseDirectoryChanged( self.originalDatabaseDirectory) except Exception, e: if self.originalDatabaseDirectory: dicomWidget.onDatabaseDirectoryChanged( self.originalDatabaseDirectory) import traceback traceback.print_exc() self.delayDisplay('Test caused exception!\n' + str(e)) self.assertTrue(False)
def ComputeLabelStatistics(self, grayscaleNode, inputlabelNode): """ Computes label statistics for input label node on grayscale volume (mean, std, volume, etc) """ # Print to Slicer CLI print ("Computing Label Statistics..."), start_time = time.time() # resample the label to the space of the grayscale if needed volumesLogic = slicer.modules.volumes.logic() warnings = volumesLogic.CheckForLabelVolumeValidity(grayscaleNode, inputlabelNode) if warnings != "": if "mismatch" in warnings: inputlabelNode = volumesLogic.ResampleVolumeToReferenceVolume(inputlabelNode, grayscaleNode) # Set up Stat accumulator stataccum = vtk.vtkImageAccumulate() stataccum.SetInputConnection(inputlabelNode.GetImageDataConnection()) stataccum.Update() InputLabelValue = int(stataccum.GetMax()[0]) # logic copied from slicer3 LabelStatistics thresholder = {} thresholder = vtk.vtkImageThreshold() thresholder.SetInputConnection(inputlabelNode.GetImageDataConnection()) thresholder.SetInValue(1) thresholder.SetOutValue(0) thresholder.ReplaceOutOn() thresholder.ThresholdBetween(InputLabelValue, InputLabelValue) thresholder.SetOutputScalarType(grayscaleNode.GetImageData().GetScalarType()) thresholder.Update() # use vtk's statistics class with the binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() stencil.SetInputConnection(thresholder.GetOutputPort()) stencil.ThresholdBetween(1, 1) stencil.Update() # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.5") stat1 = vtk.vtkImageAccumulate() stat1.SetInputConnection(grayscaleNode.GetImageDataConnection()) stat1.SetStencilData(stencil.GetOutput()) stat1.Update() ### List of possible label stats available ### # cubicMMPerVoxel = reduce(lambda x,y: x*y, inputlabelNode.GetSpacing()) # ccPerCubicMM = 0.001 # labelStats["Labels"].append(i) # labelStats[i,"Index"] = i # labelStats[i,"Count"] = stat1.GetVoxelCount() # labelStats[i,"Volume mm^3"] = labelStats[i,"Count"] * cubicMMPerVoxel # labelStats[i,"Volume cc"] = labelStats[i,"Volume mm^3"] * ccPerCubicMM # labelStats[i,"Min"] = stat1.GetMin()[0] # labelStats[i,"Max"] = stat1.GetMax()[0] # labelStats[i,"Mean"] = stat1.GetMean()[0] # labelStats[i,"StdDev"] = stat1.GetStandardDeviation()[0] # print to Slicer CLI end_time = time.time() print ("done (%0.2f s)") % float(end_time - start_time) # Return desired stats to variables return stat1.GetMean()[0], stat1.GetStandardDeviation()[0]
def __init__(self, grayscaleNode, labelNode, fileName=None): #import numpy numOfDataNodes = grayscaleNode.GetNumberOfDataNodes() if labelNode.IsA("vtkMRMLSequenceNode"): numOfDataNodes2 = labelNode.GetNumberOfDataNodes() if numOfDataNodes != numOfDataNodes2: sys.stderr.write( 'Number of nodes in the grayscale volume sequence does not match the number of nodes in the labelmap volume sequence' ) return self.keys = ("Index", "Count", "Volume mm^3", "Volume cc", "Min", "Max", "Mean", "StdDev") if labelNode.IsA("vtkMRMLSequenceNode"): cubicMMPerVoxel = reduce(lambda x, y: x * y, labelNode.GetNthDataNode(0).GetSpacing()) elif labelNode.IsA("vtkMRMLScalarVolumeNode"): cubicMMPerVoxel = reduce(lambda x, y: x * y, labelNode.GetSpacing()) ccPerCubicMM = 0.001 # TODO: progress and status updates # this->InvokeEvent(vtkSequenceLabelStatisticsLogic::StartLabelStats, (void*)"start label stats") self.labelStats = {} self.labelStats['Labels'] = [] stataccum = vtk.vtkImageAccumulate() isLabelmapSequence = labelNode.IsA("vtkMRMLSequenceNode") if isLabelmapSequence: stataccumInput = labelNode.GetNthDataNode(0).GetImageData() else: stataccumInput = labelNode.GetImageData() if vtk.VTK_MAJOR_VERSION <= 5: stataccum.SetInput(stataccumInput) else: stataccum.SetInputData(stataccumInput) stataccum.Update() # lo = int(stataccum.GetMin()[0]) hi = int(stataccum.GetMax()[0]) # We select the highest label index for analysis selectedLabelIndex = hi for i in xrange(numOfDataNodes): # this->SetProgress((float)i/hi); # std::string event_message = "Label "; std::stringstream s; s << i; event_message.append(s.str()); # this->InvokeEvent(vtkSequenceLabelStatisticsLogic::LabelStatsOuterLoop, (void*)event_message.c_str()); # logic copied from slicer3 SequenceLabelStatistics # to create the binary volume of the label # //logic copied from slicer2 SequenceLabelStatistics MaskStat # // create the binary volume of the label if isLabelmapSequence: stataccumInput = labelNode.GetNthDataNode(0).GetImageData() if vtk.VTK_MAJOR_VERSION <= 5: stataccum.SetInput(stataccumInput) else: stataccum.SetInputData(stataccumInput) thresholder = vtk.vtkImageThreshold() if vtk.VTK_MAJOR_VERSION <= 5: thresholder.SetInput(stataccumInput) else: thresholder.SetInputData(stataccumInput) thresholder.SetInValue(1) thresholder.SetOutValue(0) thresholder.ReplaceOutOn() thresholder.ThresholdBetween(selectedLabelIndex, selectedLabelIndex) thresholder.SetOutputScalarType( grayscaleNode.GetNthDataNode(i).GetImageData().GetScalarType()) thresholder.Update() # this.InvokeEvent(vtkSequenceLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.25"); # use vtk's statistics class with the binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() if vtk.VTK_MAJOR_VERSION <= 5: stencil.SetInput(thresholder.GetOutput()) else: stencil.SetInputData(thresholder.GetOutput()) stencil.ThresholdBetween(1, 1) # this.InvokeEvent(vtkSequenceLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.5") stat1 = vtk.vtkImageAccumulate() if vtk.VTK_MAJOR_VERSION <= 5: stat1.SetInput(grayscaleNode.GetNthDataNode(i).GetImageData()) stat1.SetStencil(stencil.GetOutput()) else: stat1.SetInputData( grayscaleNode.GetNthDataNode(i).GetImageData()) stat1.SetStencilData(stencil.GetOutput()) stat1.Update() # this.InvokeEvent(vtkSequenceLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.75") if stat1.GetVoxelCount() > 0: # add an entry to the LabelStats list self.labelStats["Labels"].append(i) self.labelStats[i, "Index"] = i self.labelStats[i, "Count"] = stat1.GetVoxelCount() self.labelStats[i, "Volume mm^3"] = self.labelStats[ i, "Count"] * cubicMMPerVoxel self.labelStats[i, "Volume cc"] = self.labelStats[ i, "Volume mm^3"] * ccPerCubicMM self.labelStats[i, "Min"] = stat1.GetMin()[0] self.labelStats[i, "Max"] = stat1.GetMax()[0] self.labelStats[i, "Mean"] = stat1.GetMean()[0] self.labelStats[i, "StdDev"] = stat1.GetStandardDeviation()[0]
def test_setSliceViewerLayers(self): self.delayDisplay('Testing slicer.util.setSliceViewerLayers') layoutManager = slicer.app.layoutManager() layoutManager.layout = slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView redSliceCompositeNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceCompositeNodeRed') self.assertIsNotNone(redSliceCompositeNode) self.assertIsNone(redSliceCompositeNode.GetBackgroundVolumeID()) self.assertIsNone(redSliceCompositeNode.GetForegroundVolumeID()) self.assertIsNone(redSliceCompositeNode.GetLabelVolumeID()) import SampleData sampleDataLogic = SampleData.SampleDataLogic() backgroundNode = sampleDataLogic.downloadMRHead() backgroundNode.SetName('Background') foregroundNode = sampleDataLogic.downloadMRHead() foregroundNode.SetName('Foreground') volumesLogic = slicer.modules.volumes.logic() labelmapNode = volumesLogic.CreateAndAddLabelVolume( slicer.mrmlScene, backgroundNode, 'Labelmap' ) thresholder = vtk.vtkImageThreshold() thresholder.SetInputData(backgroundNode.GetImageData()) thresholder.ThresholdByLower(80) thresholder.Update() labelmapNode.SetAndObserveImageData(thresholder.GetOutput()) # Try with nothing slicer.util.setSliceViewerLayers(background = None, foreground = None, label = None) self.assertIsNone(redSliceCompositeNode.GetBackgroundVolumeID()) self.assertIsNone(redSliceCompositeNode.GetForegroundVolumeID()) self.assertIsNone(redSliceCompositeNode.GetLabelVolumeID()) # Try with nodes slicer.util.setSliceViewerLayers( background = backgroundNode, foreground = foregroundNode, label = labelmapNode, foregroundOpacity = 0.5, labelOpacity = 0.1 ) self.assertEqual(redSliceCompositeNode.GetBackgroundVolumeID(), backgroundNode.GetID()) self.assertEqual(redSliceCompositeNode.GetForegroundVolumeID(), foregroundNode.GetID()) self.assertEqual(redSliceCompositeNode.GetLabelVolumeID(), labelmapNode.GetID()) self.assertEqual(redSliceCompositeNode.GetForegroundOpacity(), 0.5) self.assertEqual(redSliceCompositeNode.GetLabelOpacity(), 0.1) # Try to reset otherBackgroundNode = sampleDataLogic.downloadMRHead() otherBackgroundNode.SetName('OtherBackground') otherForegroundNode = sampleDataLogic.downloadMRHead() otherForegroundNode.SetName('OtherForeground') otherLabelmapNode = volumesLogic.CreateAndAddLabelVolume( slicer.mrmlScene, backgroundNode, 'OtherLabelmap' ) # Try with node id's slicer.util.setSliceViewerLayers( background = otherBackgroundNode.GetID(), foreground = otherForegroundNode.GetID(), label = otherLabelmapNode.GetID(), foregroundOpacity = 0.0, labelOpacity = 1.0 ) self.assertEqual(redSliceCompositeNode.GetBackgroundVolumeID(), otherBackgroundNode.GetID()) self.assertEqual(redSliceCompositeNode.GetForegroundVolumeID(), otherForegroundNode.GetID()) self.assertEqual(redSliceCompositeNode.GetLabelVolumeID(), otherLabelmapNode.GetID()) self.assertEqual(redSliceCompositeNode.GetForegroundOpacity(), 0.0) self.assertEqual(redSliceCompositeNode.GetLabelOpacity(), 1.0) self.delayDisplay('Testing slicer.util.setSliceViewerLayers passed')
def __init__(self, grayscaleNode, labelNode, fileName=None): #import numpy self.keys = ( "Type", "Percentage", "Volume liters", "Mean", "StdDev", "Min", "Max", ) self.types = ("Normal", "PS", "PL", "CL1", "CL2", "CL3") cubicMMPerVoxel = reduce(lambda x, y: x * y, labelNode.GetSpacing()) litersPerCubicMM = 0.000001 # TODO: progress and status updates # this->InvokeEvent(vtkEmphysemaSubtypesLogic::StartLabelStats, (void*)"start label stats") self.labelStats = {} self.labelStats['Labels'] = [] stataccum = vtk.vtkImageAccumulate() stataccum.SetInput(labelNode.GetImageData()) stataccum.Update() lo = 1 hi = 6 for i in xrange(lo, hi + 1): # this->SetProgress((float)i/hi); # std::string event_message = "Label "; std::stringstream s; s << i; event_message.append(s.str()); # this->InvokeEvent(vtkEmphysemaSubtypesLogic::LabelStatsOuterLoop, (void*)event_message.c_str()); # logic copied from slicer3 EmphysemaSubtypes # to create the binary volume of the label # //logic copied from slicer2 EmphysemaSubtypes MaskStat # // create the binary volume of the label thresholder = vtk.vtkImageThreshold() thresholder.SetInput(labelNode.GetImageData()) thresholder.SetInValue(1) thresholder.SetOutValue(0) thresholder.ReplaceOutOn() thresholder.ThresholdBetween(i, i) thresholder.SetOutputScalarType( grayscaleNode.GetImageData().GetScalarType()) thresholder.Update() # this.InvokeEvent(vtkEmphysemaSubtypesLogic::LabelStatsInnerLoop, (void*)"0.25"); # use vtk's statistics class with the binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() stencil.SetInput(thresholder.GetOutput()) stencil.ThresholdBetween(1, 1) # this.InvokeEvent(vtkEmphysemaSubtypesLogic::LabelStatsInnerLoop, (void*)"0.5") stat1 = vtk.vtkImageAccumulate() stat1.SetInput(grayscaleNode.GetImageData()) stat1.SetStencil(stencil.GetOutput()) stat1.Update() # this.InvokeEvent(vtkEmphysemaSubtypesLogic::LabelStatsInnerLoop, (void*)"0.75") if stat1.GetVoxelCount() > 0: # add an entry to the LabelStats list self.labelStats["Labels"].append(i) self.labelStats[i, "Type"] = self.types[i - 1] self.labelStats[i, "Percentage"] = float(stat1.GetVoxelCount()) self.labelStats[i, "Volume liters"] = float( stat1.GetVoxelCount() * cubicMMPerVoxel * litersPerCubicMM) self.labelStats[i, "Min"] = float(stat1.GetMin()[0]) self.labelStats[i, "Max"] = float(stat1.GetMax()[0]) self.labelStats[i, "Mean"] = float(stat1.GetMean()[0]) self.labelStats[i, "StdDev"] = float( stat1.GetStandardDeviation()[0]) # this.InvokeEvent(vtkEmphysemaSubtypesLogic::LabelStatsInnerLoop, (void*)"1") # this.InvokeEvent(vtkEmphysemaSubtypesLogic::EndLabelStats, (void*)"end label stats") total = 0 for i in xrange(lo, hi + 1): total = total + self.labelStats[i, "Percentage"] for i in xrange(lo, hi + 1): self.labelStats[i, "Percentage"] = float( 100.0 * self.labelStats[i, "Percentage"] / total)
def test_ReportingAIMRoundTrip(self): print("CTEST_FULL_OUTPUT") """ Load the data using DICOM module """ import os self.delayDisplay("Starting the DICOM test") # # first, get the data - a zip file of dicom data # import urllib downloads = ( ('http://slicer.kitware.com/midas3/download?items=10881', 'JANCT-CT.zip'), ) self.delayDisplay("Downloading") for url,name in downloads: filePath = slicer.app.temporaryPath + '/' + name if not os.path.exists(filePath) or os.stat(filePath).st_size == 0: self.delayDisplay('Requesting download %s from %s...\n' % (name, url)) urllib.urlretrieve(url, filePath) self.delayDisplay('Finished with download\n') reportingTempDir = slicer.app.temporaryPath+'/Reporting' print('Temporary directory location: '+reportingTempDir) qt.QDir().mkpath(reportingTempDir) dicomFilesDirectory = reportingTempDir + '/dicomFiles' self.cleanupDir(dicomFilesDirectory) qt.QDir().mkpath(dicomFilesDirectory) slicer.app.applicationLogic().Unzip(filePath, dicomFilesDirectory) try: self.delayDisplay("Switching to temp database directory") tempDatabaseDirectory = reportingTempDir + '/tempDICOMDatbase' qt.QDir().mkpath(tempDatabaseDirectory) self.cleanupDir(tempDatabaseDirectory) if slicer.dicomDatabase: self.originalDatabaseDirectory = os.path.split(slicer.dicomDatabase.databaseFilename)[0] else: self.originalDatabaseDirectory = None settings = qt.QSettings() settings.setValue('DatabaseDirectory', tempDatabaseDirectory) dicomWidget = slicer.modules.dicom.widgetRepresentation().self() dicomWidget.onDatabaseDirectoryChanged(tempDatabaseDirectory) self.delayDisplay('Importing DICOM') mainWindow = slicer.util.mainWindow() mainWindow.moduleSelector().selectModule('DICOM') #dicomWidget.dicomApp.suspendModel() indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, dicomFilesDirectory, None) indexer.waitForImportFinished() patient = slicer.dicomDatabase.patients()[0] studies = slicer.dicomDatabase.studiesForPatient(patient) series = [slicer.dicomDatabase.seriesForStudy(study) for study in studies] seriesUIDs = [uid for uidList in series for uid in uidList] dicomWidget.detailsPopup.offerLoadables(seriesUIDs, 'SeriesUIDList') dicomWidget.detailsPopup.examineForLoading() loadablesByPlugin = dicomWidget.detailsPopup.loadablesByPlugin self.delayDisplay('Loading Selection') dicomWidget.detailsPopup.loadCheckedLoadables() # initialize the module with the report and volume volumes = slicer.util.getNodes('vtkMRMLScalarVolumeNode*') self.assertTrue(len(volumes) == 1) (name,volume) = volumes.items()[0] self.delayDisplay('Loaded volume name %s' % volume.GetName()) self.delayDisplay('Configure Module') mainWindow = slicer.util.mainWindow() mainWindow.moduleSelector().selectModule('Reporting') reporting = slicer.modules.reporting.widgetRepresentation().self() report = slicer.mrmlScene.CreateNodeByClass('vtkMRMLReportingReportNode') report.SetReferenceCount(report.GetReferenceCount()-1) slicer.mrmlScene.AddNode(report) report.SetFindingLabel(7) reporting.reportSelector.setCurrentNode(report) self.delayDisplay('Setting volume to %s' % volume.GetName()) reporting.volumeSelector.setCurrentNode(volume) slicer.app.processEvents() # place some markups and add a segmentation label # add fiducial fidNode = slicer.vtkMRMLAnnotationFiducialNode() fidName = "AIM Round Trip Test Fiducial" fidNode.SetName(fidName) fidNode.SetSelected(1) fidNode.SetDisplayVisibility(1) fidNode.SetLocked(0) # TODO: ask Nicole where this is assigned in the regular workflow fidNode.SetAttribute('AssociatedNodeID',volume.GetID()) print("Calling set fid coords") startCoords = [15.8, 70.8, -126.7] fidNode.SetFiducialCoordinates(startCoords[0],startCoords[1],startCoords[2]) print("Starting fiducial coordinates: "+str(startCoords)) slicer.mrmlScene.AddNode(fidNode) # add ruler rulerNode = slicer.vtkMRMLAnnotationRulerNode() rulerNode.SetName('Test Ruler') m = vtk.vtkMatrix4x4() volume.GetIJKToRASMatrix(m) ijk0 = [0,0,1,1] ijk1 = [50,50,1,1] ras0 = m.MultiplyPoint(ijk0) ras1 = m.MultiplyPoint(ijk1) rulerNode.SetPosition1(19.386751174926758, 68.528785705566406, -127.69000244140625) rulerNode.SetPosition2(132.72709655761719, -34.349384307861328, -127.69000244140625) rulerNode.SetAttribute('AssociatedNodeID',volume.GetID()) slicer.mrmlScene.AddNode(rulerNode) slicer.app.processEvents() # add label node volumesLogic = slicer.modules.volumes.logic() labelNode = volumesLogic.CreateAndAddLabelVolume(slicer.mrmlScene, volume, "Segmentation") labelDisplayNode = labelNode.GetDisplayNode() labelDisplayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeFileGenericAnatomyColors.txt') image = volume.GetImageData() thresh = vtk.vtkImageThreshold() if vtk.vtkVersion().GetVTKMajorVersion() < 6: thresh.SetInput(image) else: thresh.SetInputData(image) thresh.ThresholdBetween(10,400) thresh.SetInValue(report.GetFindingLabel()) thresh.SetOutValue(0) thresh.Update() labelNode.SetAndObserveImageData(thresh.GetOutput()) reporting.segmentationSelector.setCurrentNode(labelNode) # Save the report exportDir = reportingTempDir+'/Output' qt.QDir().mkpath(exportDir) self.cleanupDir(exportDir) report.SetStorageDirectoryName(exportDir) reportingLogic = slicer.modules.reporting.logic() print("Before saving report") reportingLogic.SaveReportToAIM(report) self.delayDisplay('Report saved') slicer.mrmlScene.Clear(0) # parse on patient level, find segmentation object, load and make sure # it matches the input # close the scene and load the report, check consistency # try to load back the saved AIM import glob print glob.glob(exportDir+'/*') xmlFiles = glob.glob(exportDir+'/*xml') print xmlFiles self.assertTrue(len(xmlFiles) == 1) reporting.importAIMFile = xmlFiles[0] reporting.onReportImport() self.delayDisplay('Report loaded from AIM! Test passed.') self.delayDisplay("Restoring original database directory") if self.originalDatabaseDirectory: dicomWidget.onDatabaseDirectoryChanged(self.originalDatabaseDirectory) except Exception, e: if self.originalDatabaseDirectory: dicomWidget.onDatabaseDirectoryChanged(self.originalDatabaseDirectory) import traceback traceback.print_exc() self.delayDisplay('Test caused exception!\n' + str(e)) self.assertTrue(False)
def test_LabelToDICOMSEGConverterRoundTrip(self): print("CTEST_FULL_OUTPUT") dir(slicer.modules) """ Load the data using DICOM module """ import os self.delayDisplay("Starting the DICOM test") # # first, get the data - a zip file of dicom data # import urllib downloads = ( ('http://slicer.kitware.com/midas3/download?items=10881', 'JANCT-CT.zip'), ) self.delayDisplay("Downloading") for url,name in downloads: filePath = slicer.app.temporaryPath + '/' + name if not os.path.exists(filePath) or os.stat(filePath).st_size == 0: self.delayDisplay('Requesting download %s from %s...\n' % (name, url)) urllib.urlretrieve(url, filePath) self.delayDisplay('Finished with download\n') reportingTempDir = slicer.app.temporaryPath+'/LabelToDICOMSEGConverter' qt.QDir().mkpath(reportingTempDir) dicomFilesDirectory = reportingTempDir + '/dicomFiles' self.cleanupDir(dicomFilesDirectory) qt.QDir().mkpath(dicomFilesDirectory) slicer.app.applicationLogic().Unzip(filePath, dicomFilesDirectory) try: self.delayDisplay("Switching to temp database directory") tempDatabaseDirectory = reportingTempDir + '/tempDICOMDatbase' qt.QDir().mkpath(tempDatabaseDirectory) self.cleanupDir(tempDatabaseDirectory) if slicer.dicomDatabase: self.originalDatabaseDirectory = os.path.split(slicer.dicomDatabase.databaseFilename)[0] else: self.originalDatabaseDirectory = None settings = qt.QSettings() settings.setValue('DatabaseDirectory', tempDatabaseDirectory) dicomWidget = slicer.modules.dicom.widgetRepresentation().self() dicomWidget.onDatabaseDirectoryChanged(tempDatabaseDirectory) self.delayDisplay('Importing DICOM') mainWindow = slicer.util.mainWindow() mainWindow.moduleSelector().selectModule('DICOM') self.importDICOM(slicer.dicomDatabase, dicomFilesDirectory) patient = slicer.dicomDatabase.patients()[0] studies = slicer.dicomDatabase.studiesForPatient(patient) series = [slicer.dicomDatabase.seriesForStudy(study) for study in studies] seriesUIDs = [uid for uidList in series for uid in uidList] dicomWidget.detailsPopup.offerLoadables(seriesUIDs, 'SeriesUIDList') dicomWidget.detailsPopup.examineForLoading() loadablesByPlugin = dicomWidget.detailsPopup.loadablesByPlugin self.delayDisplay('Loading Selection') dicomWidget.detailsPopup.loadCheckedLoadables() # initialize the module with the report and volume volumes = slicer.util.getNodes('vtkMRMLScalarVolumeNode*') self.assertTrue(len(volumes) == 1) (name,volume) = volumes.items()[0] self.delayDisplay('Loaded volume name %s' % volume.GetName()) self.delayDisplay('Configure Module') mainWindow = slicer.util.mainWindow() mainWindow.moduleSelector().selectModule('LabelToDICOMSEGConverter') module = slicer.modules.labeltodicomsegconverter.widgetRepresentation().self() # add label node volumesLogic = slicer.modules.volumes.logic() labelNode = volumesLogic.CreateAndAddLabelVolume(slicer.mrmlScene, volume, "Segmentation") labelNode.SetAttribute('AssociatedNodeID', volume.GetID()) labelDisplayNode = labelNode.GetDisplayNode() labelDisplayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeFileGenericAnatomyColors.txt') image = volume.GetImageData() thresh = vtk.vtkImageThreshold() if vtk.vtkVersion().GetVTKMajorVersion() < 6: thresh.SetInput(image) else: thresh.SetInputData(image) thresh.ThresholdBetween(10,400) thresh.SetInValue(10) thresh.SetOutValue(0) thresh.Update() labelNode.SetAndObserveImageData(thresh.GetOutput()) module.segmentationSelector.setCurrentNode(labelNode) module.volumeSelector.setCurrentNode(volume) self.delayDisplay('Input label initialized') module.outputDir = reportingTempDir+'/Output' # Save the report exportDir = reportingTempDir+'/Output' qt.QDir().mkpath(exportDir) self.cleanupDir(exportDir) module.onLabelExport() self.delayDisplay('Report saved') self.importDICOM(slicer.dicomDatabase, exportDir) slicer.mrmlScene.Clear(0) patient = slicer.dicomDatabase.patients()[0] studies = slicer.dicomDatabase.studiesForPatient(patient) series = [slicer.dicomDatabase.seriesForStudy(study) for study in studies] seriesUIDs = [uid for uidList in series for uid in uidList] dicomWidget.detailsPopup.offerLoadables(seriesUIDs, 'SeriesUIDList') dicomWidget.detailsPopup.examineForLoading() loadablesByPlugin = dicomWidget.detailsPopup.loadablesByPlugin self.delayDisplay('Wait',10000) dicomWidget.detailsPopup.loadCheckedLoadables() volumes = slicer.util.getNodes('vtkMRMLLabelMapVolumeNode*') for n,v in volumes.items(): print('Label volume found: '+v.GetID()) self.assertTrue(len(volumes) == 1) for name,volume in volumes.items(): image = volume.GetImageData() previousImage = thresh.GetOutput() diff = vtk.vtkImageDifference() if vtk.vtkVersion().GetVTKMajorVersion() < 6: diff.SetInput(thresh.GetOutput()) else: diff.SetInputData(thresh.GetOutput()) diff.SetImage(image) diff.Update() if diff.GetThresholdedError() > 1: self.delayDisplay('Reloaded image does not match') self.assertTrue(False) self.delayDisplay('Test passed') self.delayDisplay("Restoring original database directory") if self.originalDatabaseDirectory: dicomWidget.onDatabaseDirectoryChanged(self.originalDatabaseDirectory) except Exception, e: if self.originalDatabaseDirectory: dicomWidget.onDatabaseDirectoryChanged(self.originalDatabaseDirectory) import traceback traceback.print_exc() self.delayDisplay('Test caused exception!\n' + str(e)) self.assertTrue(False)
def removeIslands(self): # # change the label values based on the parameter node # if not self.sliceLogic: self.sliceLogic = self.editUtil.getSliceLogic() parameterNode = self.editUtil.getParameterNode() minimumSize = int( parameterNode.GetParameter("IslandEffect,minimumSize")) fullyConnected = bool( parameterNode.GetParameter("IslandEffect,fullyConnected")) label = self.editUtil.getLabel() # first, create an inverse binary version of the image # so that islands inside segemented object will be detected, along # with a big island of the background preThresh = vtk.vtkImageThreshold() preThresh.SetInValue(0) preThresh.SetOutValue(1) preThresh.ReplaceInOn() preThresh.ReplaceOutOn() preThresh.ThresholdBetween(label, label) preThresh.SetInput(self.getScopedLabelInput()) preThresh.SetOutputScalarTypeToUnsignedLong() # now identify the islands in the inverted volume # and find the pixel that corresponds to the background islandMath = vtkITK.vtkITKIslandMath() islandMath.SetInput(preThresh.GetOutput()) islandMath.SetFullyConnected(fullyConnected) islandMath.SetMinimumSize(minimumSize) # TODO: $this setProgressFilter $islandMath "Calculating Islands..." islandMath.Update() islandCount = islandMath.GetNumberOfIslands() islandOrigCount = islandMath.GetOriginalNumberOfIslands() ignoredIslands = islandOrigCount - islandCount print("%d islands created (%d ignored)" % (islandCount, ignoredIslands)) if islandCount == 0: return bgPixel = self.findNonZeroBorderPixel(islandMath.GetOutput()) # now rethreshold so that everything which is not background becomes the label postThresh = vtk.vtkImageThreshold() postThresh.SetInValue(0) postThresh.SetOutValue(label) postThresh.ReplaceInOn() postThresh.ReplaceOutOn() postThresh.ThresholdBetween(bgPixel, bgPixel) postThresh.SetOutputScalarTypeToShort() postThresh.SetInput(islandMath.GetOutput()) postThresh.SetOutput(self.getScopedLabelOutput()) # TODO $this setProgressFilter $postThresh "Applying to Label Map..." postThresh.Update() self.applyScopedLabel() if False: # some code for debugging - leave it in layerLogic = self.sliceLogic.GetLabelLayer() labelNode = layerLogic.GetVolumeNode() volumesLogic = slicer.modules.volumes.logic() thresh1 = volumesLogic.CloneVolume(slicer.mrmlScene, labelNode, 'thres1') islands = volumesLogic.CloneVolume(slicer.mrmlScene, labelNode, 'islands') thresh2 = volumesLogic.CloneVolume(slicer.mrmlScene, labelNode, 'thres2') cast = vtk.vtkImageCast() cast.SetOutputScalarTypeToShort() cast.SetInput(preThresh.GetOutput()) cast.Update() thresh1.SetAndObserveImageData(cast.GetOutput()) cast2 = vtk.vtkImageCast() cast2.SetOutputScalarTypeToShort() cast2.SetInput(islandMath.GetOutput()) cast2.Update() islands.SetAndObserveImageData(cast2.GetOutput()) thresh2.SetAndObserveImageData(postThresh.GetOutput())
def __init__(self, grayscaleNode, labelNode, KEV120, KEV80, fileName=None): #import numpy self.keys = ("Index", "Label Name", "Agatston Score", "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'] = [] stataccum = vtk.vtkImageAccumulate() if vtk.VTK_MAJOR_VERSION <= 5: stataccum.SetInput(labelNode.GetImageData()) else: stataccum.SetInputConnection(labelNode.GetImageDataConnection()) stataccum.Update() lo = int(stataccum.GetMin()[0]) hi = int(stataccum.GetMax()[0]) displayNode = labelNode.GetDisplayNode() colorNode = displayNode.GetColorNode() self.labelNode = labelNode self.grayscaleNode = grayscaleNode self.KEV80 = KEV80 self.KEV120 = KEV120 self.calculateAgatstonScores() for i in xrange(lo, 7): # skip indices 0 (background) and 1 (default threshold pixels) # because these are not calcium and do not have an Agatston score if i == 0 or i == 1: continue # this->SetProgress((float)i/hi); # std::string event_message = "Label "; std::stringstream s; s << i; event_message.append(s.str()); # this->InvokeEvent(vtkLabelStatisticsLogic::LabelStatsOuterLoop, (void*)event_message.c_str()); # logic copied from slicer3 LabelStatistics # to create the binary volume of the label # //logic copied from slicer2 LabelStatistics MaskStat # // create the binary volume of the label thresholder = vtk.vtkImageThreshold() if vtk.VTK_MAJOR_VERSION <= 5: thresholder.SetInput(labelNode.GetImageData()) else: thresholder.SetInputConnection( labelNode.GetImageDataConnection()) thresholder.SetInValue(1) thresholder.SetOutValue(0) thresholder.ReplaceOutOn() if i != 6: thresholder.ThresholdBetween(i, i) else: # label 6 is the total calcium pixels in labels 2, 3, 4 and 5 thresholder.ThresholdBetween(2, 5) thresholder.SetOutputScalarType( grayscaleNode.GetImageData().GetScalarType()) thresholder.Update() # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.25"); # use vtk's statistics class with the binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() if vtk.VTK_MAJOR_VERSION <= 5: stencil.SetInput(thresholder.GetOutput()) else: stencil.SetInputConnection(thresholder.GetOutputPort()) stencil.ThresholdBetween(1, 1) # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.5") stat1 = vtk.vtkImageAccumulate() if vtk.VTK_MAJOR_VERSION <= 5: stat1.SetInput(grayscaleNode.GetImageData()) stat1.SetStencil(stencil.GetOutput()) else: stat1.SetInputConnection( grayscaleNode.GetImageDataConnection()) stencil.Update() stat1.SetStencilData(stencil.GetOutput()) stat1.Update() # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.75") if stat1.GetVoxelCount() > 0: # add an entry to the LabelStats list self.labelStats["Labels"].append(i) self.labelStats[i, "Index"] = i self.labelStats[i, "Label Name"] = colorNode.GetColorName(i) self.labelStats[ i, "Agatston Score"] = self.AgatstonScoresPerLabel[i] self.labelStats[i, "Count"] = stat1.GetVoxelCount() self.labelStats[i, "Volume mm^3"] = self.labelStats[ i, "Count"] * cubicMMPerVoxel self.labelStats[i, "Volume cc"] = self.labelStats[ i, "Volume mm^3"] * ccPerCubicMM self.labelStats[i, "Min"] = stat1.GetMin()[0] self.labelStats[i, "Max"] = stat1.GetMax()[0] self.labelStats[i, "Mean"] = stat1.GetMean()[0] self.labelStats[i, "StdDev"] = stat1.GetStandardDeviation()[0]
def __init__(self, grayscaleNode, labelNode, fileName=None): #import numpy self.keys = ("Index", "Count", "Volume mm^3", "Volume cc", "Min", "Max", "Mean", "StdDev") cubicMMPerVoxel = reduce(lambda x, y: x * y, labelNode.GetSpacing()) ccPerCubicMM = 0.001 #geting a set of labels from a label map labels = self.getLabelsFromLabelMap(labelNode) print "NON - ZERO LABELS-----------------------------" print labels # TODO: progress and status updates # this->InvokeEvent(vtkLabelStatisticsLogic::StartLabelStats, (void*)"start label stats") self.labelStats = {} self.labelStats['Labels'] = [] stataccum = vtk.vtkImageAccumulate() stataccum.SetInput(labelNode.GetImageData()) stataccum.Update() lo = int(stataccum.GetMin()[0]) hi = int(stataccum.GetMax()[0]) aux1 = 999999999999999999999999999999999 aux2 = 999999999999999999999999999999999 for i in xrange(lo, hi + 1): print i thresholder = vtk.vtkImageThreshold() thresholder.SetInput(labelNode.GetImageData()) thresholder.SetInValue(1) thresholder.SetOutValue(0) thresholder.ReplaceOutOn() thresholder.ThresholdBetween(i, i) thresholder.SetOutputScalarType( grayscaleNode.GetImageData().GetScalarType()) thresholder.Update() # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.25"); # use vtk's statistics class with the binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() stencil.SetInput(thresholder.GetOutput()) stencil.ThresholdBetween(1, 1) # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.5") stat1 = vtk.vtkImageAccumulate() stat1.SetInput(grayscaleNode.GetImageData()) stat1.SetStencil(stencil.GetOutput()) stat1.Update() # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.75") if stat1.GetVoxelCount() > 0: # add an entry to the LabelStats list self.labelStats["Labels"].append(i) self.labelStats[i, "Index"] = i self.labelStats[i, "Count"] = stat1.GetVoxelCount() print stat1.GetVoxelCount() self.labelStats[i, "Volume mm^3"] = self.labelStats[ i, "Count"] * cubicMMPerVoxel self.labelStats[i, "Volume cc"] = self.labelStats[ i, "Volume mm^3"] * ccPerCubicMM self.labelStats[i, "Min"] = stat1.GetMin()[0] self.labelStats[i, "Max"] = stat1.GetMax()[0] self.labelStats[i, "Mean"] = stat1.GetMean()[0] self.labelStats[i, "StdDev"] = stat1.GetStandardDeviation()[0] aux1 = stat1.GetVoxelCount() if aux1 < aux2: aux2 = aux1 print "el menor" print aux2
def __init__(self, grayscaleNode, labelNode, fileName=None): #import numpy self.keys = ("Index", "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'] = [] stataccum = vtk.vtkImageAccumulate() stataccum.SetInput(labelNode.GetImageData()) stataccum.Update() lo = int(stataccum.GetMin()[0]) hi = int(stataccum.GetMax()[0]) for i in xrange(lo, hi + 1): # this->SetProgress((float)i/hi); # std::string event_message = "Label "; std::stringstream s; s << i; event_message.append(s.str()); # this->InvokeEvent(vtkLabelStatisticsLogic::LabelStatsOuterLoop, (void*)event_message.c_str()); # logic copied from slicer3 LabelStatistics # to create the binary volume of the label # //logic copied from slicer2 LabelStatistics MaskStat # // create the binary volume of the label thresholder = vtk.vtkImageThreshold() thresholder.SetInput(labelNode.GetImageData()) thresholder.SetInValue(1) thresholder.SetOutValue(0) thresholder.ReplaceOutOn() thresholder.ThresholdBetween(i, i) thresholder.SetOutputScalarType( grayscaleNode.GetImageData().GetScalarType()) thresholder.Update() # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.25"); # use vtk's statistics class with the binary labelmap as a stencil stencil = vtk.vtkImageToImageStencil() stencil.SetInput(thresholder.GetOutput()) stencil.ThresholdBetween(1, 1) # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.5") stat1 = vtk.vtkImageAccumulate() stat1.SetInput(grayscaleNode.GetImageData()) stat1.SetStencil(stencil.GetOutput()) stat1.Update() # this.InvokeEvent(vtkLabelStatisticsLogic::LabelStatsInnerLoop, (void*)"0.75") if stat1.GetVoxelCount() > 0: # add an entry to the LabelStats list self.labelStats["Labels"].append(i) self.labelStats[i, "Index"] = i self.labelStats[i, "Count"] = stat1.GetVoxelCount() self.labelStats[i, "Volume mm^3"] = self.labelStats[ i, "Count"] * cubicMMPerVoxel self.labelStats[i, "Volume cc"] = self.labelStats[ i, "Volume mm^3"] * ccPerCubicMM self.labelStats[i, "Min"] = stat1.GetMin()[0] self.labelStats[i, "Max"] = stat1.GetMax()[0] self.labelStats[i, "Mean"] = stat1.GetMean()[0] self.labelStats[i, "StdDev"] = stat1.GetStandardDeviation()[0]
def DoIt(inputDir, labelFile, outputDir, forceLabel, forceResample): dbDir1 = slicer.app.temporaryPath+'/LabelConverter' if not hasattr(slicer.modules, 'reporting'): print 'The Reporting module has not been loaded into Slicer, script cannot run!\n\tTry setting the --additional-module-path parameter.' sys.exit(1) reportingLogic = slicer.modules.reporting.logic() print('Temporary directory location: '+dbDir1) qt.QDir().mkpath(dbDir1) dbDir0 = None if slicer.dicomDatabase: dbDir0 = os.path.split(slicer.dicomDatabase.databaseFilename)[0] dicomWidget = slicer.modules.dicom.widgetRepresentation().self() dicomWidget.onDatabaseDirectoryChanged(dbDir1) # import DICOM study indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, inputDir, None) indexer.waitForImportFinished() print('DICOM import finished!') # # Read the input DICOM series as a volume # dcmList = [] for dcm in os.listdir(inputDir): if len(dcm)-dcm.rfind('.dcm') == 4: dcmList.append(inputDir+'/'+dcm) scalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']() loadables = scalarVolumePlugin.examine([dcmList]) if len(loadables) == 0: print 'Could not parse the DICOM Study!' sys.exit(1) inputVolume = scalarVolumePlugin.load(loadables[0]) print 'Input volume loaded! ID = ', inputVolume.GetID() # read the label volume labelVolume = slicer.vtkMRMLLabelMapVolumeNode() sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() sNode.SetFileName(labelFile) sNode.ReadData(labelVolume) if forceLabel>0: # print('Forcing label to '+str(forceLabel)) labelImage = labelVolume.GetImageData() thresh = vtk.vtkImageThreshold() if vtk.vtkVersion().GetVTKMajorVersion() < 6: thresh.SetInput(labelImage) else: thresh.SetInputData(labelImage) thresh.ThresholdBetween(1, labelImage.GetScalarRange()[1]) thresh.SetInValue(int(forceLabel)) thresh.SetOutValue(0) thresh.ReplaceInOn() thresh.ReplaceOutOn() thresh.Update() labelImage = thresh.GetOutput() labelVolume.SetAndObserveImageData(labelImage) slicer.mrmlScene.AddNode(labelVolume) print 'Label volume added, id = ', labelVolume.GetID() # ensure that the label volume scalar type is unsigned short if labelVolume.GetImageData() != None: scalarType = labelVolume.GetImageData().GetScalarType() if scalarType != vtk.VTK_UNSIGNED_SHORT: print 'Label volume has pixel type of ',vtk.vtkImageScalarTypeNameMacro(scalarType),', casting to unsigned short' cast = vtk.vtkImageCast() cast.SetOutputScalarTypeToUnsignedShort() if vtk.vtkVersion().GetVTKMajorVersion() < 6: cast.SetInput(labelVolume.GetImageData()) cast.Update() labelVolume.SetAndObserveImageData(cast.GetOutput()) else: cast.SetInputConnection(labelVolume.GetImageDataConnection()) cast.Update() labelVolume.SetImageDataConnection(cast.GetOutputPort()) if labelVolume.GetImageData().GetScalarType() != vtk.VTK_UNSIGNED_SHORT: print 'Failed to cast label volume to unsigned short, type is ', vtk.vtkImageScalarTypeNameMacro(labelVolume.GetImageData().GetScalarType()) sys.exit(1) volumesLogic = slicer.modules.volumes.logic() geometryCheckString = volumesLogic.CheckForLabelVolumeValidity(inputVolume, labelVolume) if geometryCheckString != "": # has the user specified that forced resampling is okay? if forceResample == False: print 'Label volume mismatch with input volume:\n',geometryCheckString,'\nForced resample not specified, aborting. Re-run with --force option to ignore geometric inconsistencies' sys.exit(1) # resample label to the input volume raster resampledLabel = slicer.vtkMRMLLabelMapVolumeNode() slicer.mrmlScene.AddNode(resampledLabel) print 'Resampled label added, id = ', resampledLabel.GetID() resampledLabel = volumesLogic.ResampleVolumeToReferenceVolume(labelVolume, inputVolume) labelVolume = resampledLabel displayNode = slicer.vtkMRMLLabelMapVolumeDisplayNode() displayNode.SetAndObserveColorNodeID(reportingLogic.GetDefaultColorNode().GetID()) slicer.mrmlScene.AddNode(displayNode) labelVolume.SetAttribute('AssociatedNodeID',inputVolume.GetID()) labelVolume.SetAndObserveDisplayNodeID(displayNode.GetID()) # initialize the DICOM DB for Reporting logic, save as DICOM SEG labelCollection = vtk.vtkCollection() labelCollection.AddItem(labelVolume) print('About to write DICOM SEG!') dbFileName = slicer.dicomDatabase.databaseFilename reportingLogic.InitializeDICOMDatabase(dbFileName) reportingLogic.DicomSegWrite(labelCollection, outputDir) dicomWidget.onDatabaseDirectoryChanged(dbDir0) exit()
def test_setSliceViewerLayers(self): self.delayDisplay('Testing slicer.util.setSliceViewerLayers') layoutManager = slicer.app.layoutManager() layoutManager.layout = slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView redSliceCompositeNode = slicer.mrmlScene.GetNodeByID( 'vtkMRMLSliceCompositeNodeRed') self.assertIsNotNone(redSliceCompositeNode) self.assertIsNone(redSliceCompositeNode.GetBackgroundVolumeID()) self.assertIsNone(redSliceCompositeNode.GetForegroundVolumeID()) self.assertIsNone(redSliceCompositeNode.GetLabelVolumeID()) import SampleData sampleDataLogic = SampleData.SampleDataLogic() backgroundNode = sampleDataLogic.downloadMRHead() backgroundNode.SetName('Background') foregroundNode = sampleDataLogic.downloadMRHead() foregroundNode.SetName('Foreground') volumesLogic = slicer.modules.volumes.logic() labelmapNode = volumesLogic.CreateAndAddLabelVolume( slicer.mrmlScene, backgroundNode, 'Labelmap') thresholder = vtk.vtkImageThreshold() thresholder.SetInputData(backgroundNode.GetImageData()) thresholder.ThresholdByLower(80) thresholder.Update() labelmapNode.SetAndObserveImageData(thresholder.GetOutput()) # Try with nothing slicer.util.setSliceViewerLayers(background=None, foreground=None, label=None) self.assertIsNone(redSliceCompositeNode.GetBackgroundVolumeID()) self.assertIsNone(redSliceCompositeNode.GetForegroundVolumeID()) self.assertIsNone(redSliceCompositeNode.GetLabelVolumeID()) # Try with nodes slicer.util.setSliceViewerLayers(background=backgroundNode, foreground=foregroundNode, label=labelmapNode, foregroundOpacity=0.5, labelOpacity=0.1) self.assertEqual(redSliceCompositeNode.GetBackgroundVolumeID(), backgroundNode.GetID()) self.assertEqual(redSliceCompositeNode.GetForegroundVolumeID(), foregroundNode.GetID()) self.assertEqual(redSliceCompositeNode.GetLabelVolumeID(), labelmapNode.GetID()) self.assertEqual(redSliceCompositeNode.GetForegroundOpacity(), 0.5) self.assertEqual(redSliceCompositeNode.GetLabelOpacity(), 0.1) # Try to reset otherBackgroundNode = sampleDataLogic.downloadMRHead() otherBackgroundNode.SetName('OtherBackground') otherForegroundNode = sampleDataLogic.downloadMRHead() otherForegroundNode.SetName('OtherForeground') otherLabelmapNode = volumesLogic.CreateAndAddLabelVolume( slicer.mrmlScene, backgroundNode, 'OtherLabelmap') # Try with node id's slicer.util.setSliceViewerLayers( background=otherBackgroundNode.GetID(), foreground=otherForegroundNode.GetID(), label=otherLabelmapNode.GetID(), foregroundOpacity=0.0, labelOpacity=1.0) self.assertEqual(redSliceCompositeNode.GetBackgroundVolumeID(), otherBackgroundNode.GetID()) self.assertEqual(redSliceCompositeNode.GetForegroundVolumeID(), otherForegroundNode.GetID()) self.assertEqual(redSliceCompositeNode.GetLabelVolumeID(), otherLabelmapNode.GetID()) self.assertEqual(redSliceCompositeNode.GetForegroundOpacity(), 0.0) self.assertEqual(redSliceCompositeNode.GetLabelOpacity(), 1.0) self.delayDisplay('Testing slicer.util.setSliceViewerLayers passed')
def createROI(self): labelim=vtk.vtkImageData() inputImage=self.volume.GetImageData() labelImage=self.label.GetImageData() IJKToRAS = vtk.vtkMatrix4x4() self.volume.GetIJKToRASMatrix(IJKToRAS) thresh = vtk.vtkImageThreshold() thresh.SetInputData(inputImage) lo, hi = inputImage.GetScalarRange() minimum=lo + 0.25 * (hi-lo) maximum=hi thresh.ThresholdBetween(minimum, maximum) thresh.SetInValue(1) thresh.SetOutValue(0) thresh.SetOutputScalarType(vtk.VTK_SHORT) thresh.Modified() thresh.Update() node=slicer.vtkMRMLScalarVolumeNode() node.SetIJKToRASMatrix(IJKToRAS) node.SetAndObserveImageData(thresh.GetOutput()) slicer.mrmlScene.AddNode(node) node.SetName('tmp') qu=QCLib.QCUtil() rect=qu.minRectangle(node) slicer.mrmlScene.RemoveNode(node) dim1=inputImage.GetDimensions()[0] dim2=inputImage.GetDimensions()[1] dim3=inputImage.GetDimensions()[2] # coln.SetColor(0,'bg',0,0,0) # coln.SetColor(1,'n',1,0,0) # coln.SetColor(2,'ne',0,1,0) # coln.SetColor(3,'nw',0,0,1) # coln.SetColor(4,'e',1,1,0) # coln.SetColor(5,'w',1,0,1) # coln.SetColor(6,'s',0,1,1) # coln.SetColor(7,'se',1,1,1) # coln.SetColor(8,'sw',1,0.5,0) VOIList=[] for z in range(dim3): VOIn=[rect['xmin'].values()[z],rect['xmax'].values()[z],1,rect['ymin'].values()[z],1] VOIne=[rect['xmax'].values()[z],dim1-1,1,rect['ymin'].values()[z],2] VOInw=[1,rect['xmin'].values()[z],1,rect['ymin'].values()[z],3] VOIe=[rect['xmax'].values()[z],dim1-1,rect['ymin'].values()[z],rect['ymax'].values()[z],4] VOIw=[1,rect['xmin'].values()[z],rect['ymin'].values()[z],rect['ymax'].values()[z],5] VOIs=[rect['xmin'].values()[z],rect['xmax'].values()[z],rect['ymax'].values()[z],dim2-1,6] VOIse=[rect['xmax'].values()[z],dim1-1,rect['ymax'].values()[z],dim2-1,7] VOIsw=[1,rect['xmin'].values()[z],rect['ymax'].values()[z],dim2-1,8] VOIList.append(VOIn) VOIList.append(VOIne) VOIList.append(VOInw) VOIList.append(VOIe) VOIList.append(VOIw) VOIList.append(VOIs) VOIList.append(VOIse) VOIList.append(VOIsw) for v in range(VOIList.__len__()): VOI=VOIList[v] z=v/8 for x in range(VOI[0],VOI[1]+1): for y in range(VOI[2],VOI[3]+1): labelImage.SetScalarComponentFromDouble(x,y,z,0,VOI[4])