def contourSequence2Volume(cs, spacing=[1, 1, 1]): polylines = drt2polylines.contourSequence2PolyLines(cs) stencil = vtk.vtkPolyDataToImageStencil() stencil.SetInputData(polylines) bounds = polylines.GetBounds() i = 0 bounds2 = [] for x in bounds: if i & 1: y = math.ceil(x) + 1 else: y = math.floor(x) - 1 bounds2.append(y) i = i + 1 stencil.SetOutputWholeExtent(bounds2[0], bounds2[1], bounds2[2], bounds2[3], bounds2[4], bounds2[5]) stencil.SetOutputSpacing(spacing[0], spacing[1], spacing[2]) stencil.Update() sten2img = vtk.vtkImageStencilToImage() sten2img.SetInputConnection(stencil.GetOutputPort()) sten2img.SetOutsideValue(0) sten2img.SetInsideValue(255) sten2img.Update() vtkimg = sten2img.GetOutput() return vtkimg
def cutSurfaceWithModel(self, segmentMarkupNode, segmentModel): import vtkSegmentationCorePython as vtkSegmentationCore if not segmentMarkupNode: raise AttributeError("{}: segment markup node not set.".format( self.__class__.__name__)) if not segmentModel: raise AttributeError("{}: segment model not set.".format( self.__class__.__name__)) if segmentMarkupNode and segmentModel.GetPolyData().GetNumberOfPolys( ) > 0: operationName = self.scriptedEffect.parameter("Operation") segmentationNode = self.scriptedEffect.parameterSetNode( ).GetSegmentationNode() if not segmentationNode: raise AttributeError("{}: Segmentation node not set.".format( self.__class__.__name__)) modifierLabelmap = self.scriptedEffect.defaultModifierLabelmap() if not modifierLabelmap: raise AttributeError( "{}: ModifierLabelmap not set. This can happen for various reasons:\n" "No master volume set for segmentation,\n" "No existing segments for segmentation, or\n" "No referenceImageGeometry is specified in the segmentation" .format(self.__class__.__name__)) WorldToModifierLabelmapIjkTransform = vtk.vtkTransform() WorldToModifierLabelmapIjkTransformer = vtk.vtkTransformPolyDataFilter( ) WorldToModifierLabelmapIjkTransformer.SetTransform( WorldToModifierLabelmapIjkTransform) WorldToModifierLabelmapIjkTransformer.SetInputConnection( segmentModel.GetPolyDataConnection()) segmentationToSegmentationIjkTransformMatrix = vtk.vtkMatrix4x4() modifierLabelmap.GetImageToWorldMatrix( segmentationToSegmentationIjkTransformMatrix) segmentationToSegmentationIjkTransformMatrix.Invert() WorldToModifierLabelmapIjkTransform.Concatenate( segmentationToSegmentationIjkTransformMatrix) worldToSegmentationTransformMatrix = vtk.vtkMatrix4x4() slicer.vtkMRMLTransformNode.GetMatrixTransformBetweenNodes( None, segmentationNode.GetParentTransformNode(), worldToSegmentationTransformMatrix) WorldToModifierLabelmapIjkTransform.Concatenate( worldToSegmentationTransformMatrix) WorldToModifierLabelmapIjkTransformer.Update() polyToStencil = vtk.vtkPolyDataToImageStencil() polyToStencil.SetOutputSpacing(1.0, 1.0, 1.0) polyToStencil.SetInputConnection( WorldToModifierLabelmapIjkTransformer.GetOutputPort()) boundsIjk = WorldToModifierLabelmapIjkTransformer.GetOutput( ).GetBounds() modifierLabelmapExtent = self.scriptedEffect.modifierLabelmap( ).GetExtent() polyToStencil.SetOutputWholeExtent(modifierLabelmapExtent[0], modifierLabelmapExtent[1], modifierLabelmapExtent[2], modifierLabelmapExtent[3], int(round(boundsIjk[4])), int(round(boundsIjk[5]))) polyToStencil.Update() stencilData = polyToStencil.GetOutput() stencilExtent = [0, -1, 0, -1, 0, -1] stencilData.SetExtent(stencilExtent) stencilToImage = vtk.vtkImageStencilToImage() stencilToImage.SetInputConnection(polyToStencil.GetOutputPort()) if operationName in ("FILL_INSIDE", "ERASE_INSIDE", "SET"): stencilToImage.SetInsideValue(1.0) stencilToImage.SetOutsideValue(0.0) else: stencilToImage.SetInsideValue(0.0) stencilToImage.SetOutsideValue(1.0) stencilToImage.SetOutputScalarType( modifierLabelmap.GetScalarType()) stencilPositioner = vtk.vtkImageChangeInformation() stencilPositioner.SetInputConnection( stencilToImage.GetOutputPort()) stencilPositioner.SetOutputSpacing(modifierLabelmap.GetSpacing()) stencilPositioner.SetOutputOrigin(modifierLabelmap.GetOrigin()) stencilPositioner.Update() orientedStencilPositionerOutput = vtkSegmentationCore.vtkOrientedImageData( ) orientedStencilPositionerOutput.ShallowCopy( stencilToImage.GetOutput()) imageToWorld = vtk.vtkMatrix4x4() modifierLabelmap.GetImageToWorldMatrix(imageToWorld) orientedStencilPositionerOutput.SetImageToWorldMatrix(imageToWorld) vtkSegmentationCore.vtkOrientedImageDataResample.ModifyImage( modifierLabelmap, orientedStencilPositionerOutput, vtkSegmentationCore.vtkOrientedImageDataResample. OPERATION_MAXIMUM) modMode = slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeAdd if operationName == "ERASE_INSIDE" or operationName == "ERASE_OUTSIDE": modMode = slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeRemove elif operationName == "SET": modMode = slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeSet self.scriptedEffect.modifySelectedSegmentByLabelmap( modifierLabelmap, modMode) # get fiducial positions as space-separated list import numpy n = segmentMarkupNode.GetNumberOfFiducials() fPos = [] for i in range(n): coord = [0.0, 0.0, 0.0] segmentMarkupNode.GetNthFiducialPosition(i, coord) fPos.extend(coord) fPosString = ' '.join(map(str, fPos)) segmentID = self.scriptedEffect.parameterSetNode( ).GetSelectedSegmentID() segment = segmentationNode.GetSegmentation().GetSegment(segmentID) segment.SetTag("SurfaceCutEffectMarkupPositions", fPosString)
def apply(self, segmentMarkupNode, segmentModel, text, textDepth, mode): self.updateModel(segmentMarkupNode, segmentModel, text, textDepth) import vtkSegmentationCore if not segmentMarkupNode: raise AttributeError(f"{self.__class__.__name__}: segment markup node not set.") if not segmentModel: raise AttributeError(f"{self.__class__.__name__}: segment model not set.") if segmentMarkupNode and segmentModel.GetPolyData().GetNumberOfCells() > 0: segmentationNode = self.scriptedEffect.parameterSetNode().GetSegmentationNode() if not segmentationNode: raise AttributeError(f"{self.__class__.__name__}: Segmentation node not set.") modifierLabelmap = self.scriptedEffect.defaultModifierLabelmap() if not modifierLabelmap: raise AttributeError("{}: ModifierLabelmap not set. This can happen for various reasons:\n" "No master volume set for segmentation,\n" "No existing segments for segmentation, or\n" "No referenceImageGeometry is specified in the segmentation".format(self.__class__.__name__)) WorldToModifierLabelmapIjkTransform = vtk.vtkTransform() WorldToModifierLabelmapIjkTransformer = vtk.vtkTransformPolyDataFilter() WorldToModifierLabelmapIjkTransformer.SetTransform(WorldToModifierLabelmapIjkTransform) WorldToModifierLabelmapIjkTransformer.SetInputConnection(segmentModel.GetPolyDataConnection()) segmentationToSegmentationIjkTransformMatrix = vtk.vtkMatrix4x4() modifierLabelmap.GetImageToWorldMatrix(segmentationToSegmentationIjkTransformMatrix) segmentationToSegmentationIjkTransformMatrix.Invert() WorldToModifierLabelmapIjkTransform.Concatenate(segmentationToSegmentationIjkTransformMatrix) worldToSegmentationTransformMatrix = vtk.vtkMatrix4x4() slicer.vtkMRMLTransformNode.GetMatrixTransformBetweenNodes(None, segmentationNode.GetParentTransformNode(), worldToSegmentationTransformMatrix) WorldToModifierLabelmapIjkTransform.Concatenate(worldToSegmentationTransformMatrix) WorldToModifierLabelmapIjkTransformer.Update() polyToStencil = vtk.vtkPolyDataToImageStencil() polyToStencil.SetOutputSpacing(1.0, 1.0, 1.0) polyToStencil.SetInputConnection(WorldToModifierLabelmapIjkTransformer.GetOutputPort()) boundsIjk = WorldToModifierLabelmapIjkTransformer.GetOutput().GetBounds() modifierLabelmapExtent = self.scriptedEffect.modifierLabelmap().GetExtent() polyToStencil.SetOutputWholeExtent(modifierLabelmapExtent[0], modifierLabelmapExtent[1], modifierLabelmapExtent[2], modifierLabelmapExtent[3], int(round(boundsIjk[4])), int(round(boundsIjk[5]))) polyToStencil.Update() stencilData = polyToStencil.GetOutput() stencilExtent = [0, -1, 0, -1, 0, -1] stencilData.SetExtent(stencilExtent) stencilToImage = vtk.vtkImageStencilToImage() stencilToImage.SetInputConnection(polyToStencil.GetOutputPort()) stencilToImage.SetInsideValue(1.0) stencilToImage.SetOutsideValue(0.0) stencilToImage.SetOutputScalarType(modifierLabelmap.GetScalarType()) stencilPositioner = vtk.vtkImageChangeInformation() stencilPositioner.SetInputConnection(stencilToImage.GetOutputPort()) stencilPositioner.SetOutputSpacing(modifierLabelmap.GetSpacing()) stencilPositioner.SetOutputOrigin(modifierLabelmap.GetOrigin()) stencilPositioner.Update() orientedStencilPositionerOutput = vtkSegmentationCore.vtkOrientedImageData() orientedStencilPositionerOutput.ShallowCopy(stencilToImage.GetOutput()) imageToWorld = vtk.vtkMatrix4x4() modifierLabelmap.GetImageToWorldMatrix(imageToWorld) orientedStencilPositionerOutput.SetImageToWorldMatrix(imageToWorld) vtkSegmentationCore.vtkOrientedImageDataResample.ModifyImage( modifierLabelmap, orientedStencilPositionerOutput, vtkSegmentationCore.vtkOrientedImageDataResample.OPERATION_MAXIMUM) modeName = self.scriptedEffect.parameter("Mode") if modeName == "EMBOSS": mode = slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeAdd elif modeName == "ENGRAVE": mode = slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeRemove else: logging.error("Invalid mode: "+modeName+" (valid modes: EMBOSS, ENGRAVE)") self.scriptedEffect.modifySelectedSegmentByLabelmap(modifierLabelmap, mode) # get plane parameters as space-separated string list planeParameters = [] if segmentMarkupNode.GetIsPlaneValid(): planeParameters.extend(segmentMarkupNode.GetOriginWorld()) xAxis = [1, 0, 0] yAxis = [0, 1, 0] zAxis = [0, 0, 1] segmentMarkupNode.GetAxesWorld(xAxis, yAxis, zAxis) planeParameters.extend(xAxis) planeParameters.extend(yAxis) planeParameters.extend(zAxis) planeParameters.extend(segmentMarkupNode.GetPlaneBounds()) planeParametersString = ' '.join(map(str, planeParameters)) segmentID = self.scriptedEffect.parameterSetNode().GetSelectedSegmentID() segment = segmentationNode.GetSegmentation().GetSegment(segmentID) segment.SetTag("EngraveEffectPlaneParameters", planeParametersString)
def StereologyAnalysis(self): """Perform stereology analysis on a sub-region of an image""" # user have to define an ROI - enforce fore now... # should allow to use whole image as default event.notify(ProgressEvent("Stereology...", 0.0)) state = self._app_states[self._current_image_index] origin = self._Origin spacing = self._Spacing # --- generate a mask from stencil ---- self.__stencil_data.Update() stencil_image = vtk.vtkImageStencilToImage() stencil_image.SetInput(self.__stencil_data) stencil_image.SetInsideValue(255) stencil_image.SetOutsideValue(0) stencil_image.SetOutputScalarTypeToUnsignedChar() stencil_image.Update() # --- image purify ----- event.notify(ProgressEvent("Stereology: Purify...", 0.2)) roi_image_reslice = self.GetROIImage() # optionally create a purification filter if state.bEnablePurify: purify = _MicroView.vtkImagePurify() purify.SetInputConnection(roi_image_reslice.GetOutputPort()) purify.SetThreshold(self._Threshold) purify.UpdateInformation() # --- Create an object to calculate stereology parameters stereology = _MicroView.vtkImageStereology() if state.bEnablePurify: stereology.SetInputConnection(purify.GetOutputPort()) stereology.SetThreshold(1) else: stereology.SetInputConnection(roi_image_reslice.GetOutputPort()) stereology.SetThreshold(self._Threshold) stereology.SetImageMask(stencil_image.GetOutput()) event.notify(ProgressEvent("Stereology...", 0.4)) stereology.Update() event.notify(ProgressEvent("Stereology...", 0.8)) outfile = StringIO.StringIO() outfile.write('\n==============\n') outfile.write('= Stereology\n') outfile.write('==============\n') outfile.write(' Total # of points used: {0}\n'.format( stereology.GetnumVoxels())) voxel_volume = self._Spacing[0] * self._Spacing[1] * self._Spacing[2] outfile.write(" Total volume of examined region (mm^3): %10.4f\n" % (stereology.GetnumVoxels() * voxel_volume, )) if state.bVerboseOutput: outfile.write('\n') outfile.write( ' The total number of voxels occupied by bone: %d\n' % int(stereology.GetPp() * stereology.GetnumVoxels())) outfile.write( ' The number of intersections (entering and leaving) for each direction:\n' ) outfile.write(' %d %d : %d %d : %d %d\n' % (stereology.GetIntX(), stereology.GetIntXO(), stereology.GetIntY(), stereology.GetIntYO(), stereology.GetIntZ(), stereology.GetIntZO())) outfile.write('\n') outfile.write( ' The Euler # found using 27 surrounding voxels: {0}\n'.format( stereology.GetEuler3D())) outfile.write( " -Euler # / Volume analyzed (1/mm^3): %0.5f\n" % (-1.0 * stereology.GetEuler3D() / voxel_volume / stereology.GetnumVoxels())) outfile.write('\n') outfile.write( ' Morphologic variables calculated from total planar intersection counts:\n' ) outfile.write( ' BV/TV BS/BV Tb.Th Tb.N Tb.Sp\n') format = '%0.6f %0.6f %0.6f %0.6f %0.6f' if state.bVerboseOutput: outfile.write(' (x) ' + format % (stereology.GetBVTV(), stereology.GetxBSBV(), stereology.GetxTbTh(), stereology.GetxTbN(), stereology.GetxTbSp()) + '\n') outfile.write(' (y) ' + format % (stereology.GetBVTV(), stereology.GetyBSBV(), stereology.GetyTbTh(), stereology.GetyTbN(), stereology.GetyTbSp()) + '\n') outfile.write(' (z) ' + format % (stereology.GetBVTV(), stereology.GetzBSBV(), stereology.GetzTbTh(), stereology.GetzTbN(), stereology.GetzTbSp()) + '\n') outfile.write(' (avg) ' + format % (stereology.GetBVTV(), stereology.GetBSBV(), stereology.GetTbTh(), stereology.GetTbN(), stereology.GetTbSp()) + '\n') outfile.write('\n') self._ResultsDict['StereologyTotalPoints'] = stereology.GetnumVoxels() self._ResultsDict['StereologyTotalVolume'] = stereology.GetnumVoxels( ) * voxel_volume self._ResultsDict['StereologyBoneVoxels'] = int( stereology.GetPp() * stereology.GetnumVoxels()) self._ResultsDict['StereologyEulerNumber'] = stereology.GetEuler3D() self._ResultsDict['StereologyEulerVolume'] = -1.0 * \ stereology.GetEuler3D() / voxel_volume / stereology.GetnumVoxels() self._ResultsDict['StereologyAvgBVTV'] = stereology.GetBVTV() self._ResultsDict['StereologyAvgBSBV'] = stereology.GetBSBV() self._ResultsDict['StereologyAvgTbTh'] = stereology.GetTbTh() self._ResultsDict['StereologyAvgTbN'] = stereology.GetTbN() self._ResultsDict['StereologyAvgTbSp'] = stereology.GetTbSp() self._StereologyOutStr = outfile.getvalue() outfile.close() event.notify(ProgressEvent("Stereology: Done.", 1.0)) # normal status return 0
#!/usr/bin/env python import vtk from vtk.test import Testing from vtk.util.misc import vtkGetDataRoot VTK_DATA_ROOT = vtkGetDataRoot() # A script to test converting a stencil to a binary image sphere = vtk.vtkSphere() sphere.SetCenter(128, 128, 0) sphere.SetRadius(80) functionToStencil = vtk.vtkImplicitFunctionToImageStencil() functionToStencil.SetInput(sphere) functionToStencil.SetOutputOrigin(0, 0, 0) functionToStencil.SetOutputSpacing(1, 1, 1) functionToStencil.SetOutputWholeExtent(0, 255, 0, 255, 0, 0) stencilToImage = vtk.vtkImageStencilToImage() stencilToImage.SetInputConnection(functionToStencil.GetOutputPort()) stencilToImage.SetOutsideValue(0) stencilToImage.SetInsideValue(255) viewer = vtk.vtkImageViewer() viewer.SetInputConnection(stencilToImage.GetOutputPort()) viewer.SetZSlice(0) viewer.SetColorWindow(255) viewer.SetColorLevel(127.5) viewer.Render() # --- end of script --
def onApply(self): import vtkSegmentationCorePython as vtkSegmentationCore # Allow users revert to this state by clicking Undo self.scriptedEffect.saveStateForUndo() # This can be a long operation - indicate it to the user qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor) if self.segmentMarkupNode and ( self.segmentModel.GetPolyData().GetNumberOfPolys() > 0): self.observeSegmentation(False) operationName = self.scriptedEffect.parameter("Operation") modifierLabelmap = self.scriptedEffect.defaultModifierLabelmap() segmentationNode = self.scriptedEffect.parameterSetNode( ).GetSegmentationNode() WorldToModifierLabelmapIjkTransform = vtk.vtkTransform() WorldToModifierLabelmapIjkTransformer = vtk.vtkTransformPolyDataFilter( ) WorldToModifierLabelmapIjkTransformer.SetTransform( WorldToModifierLabelmapIjkTransform) WorldToModifierLabelmapIjkTransformer.SetInputConnection( self.segmentModel.GetPolyDataConnection()) segmentationToSegmentationIjkTransformMatrix = vtk.vtkMatrix4x4() modifierLabelmap.GetImageToWorldMatrix( segmentationToSegmentationIjkTransformMatrix) segmentationToSegmentationIjkTransformMatrix.Invert() WorldToModifierLabelmapIjkTransform.Concatenate( segmentationToSegmentationIjkTransformMatrix) worldToSegmentationTransformMatrix = vtk.vtkMatrix4x4() slicer.vtkMRMLTransformNode.GetMatrixTransformBetweenNodes( None, segmentationNode.GetParentTransformNode(), worldToSegmentationTransformMatrix) WorldToModifierLabelmapIjkTransform.Concatenate( worldToSegmentationTransformMatrix) WorldToModifierLabelmapIjkTransformer.Update() polyToStencil = vtk.vtkPolyDataToImageStencil() polyToStencil.SetOutputSpacing(1.0, 1.0, 1.0) polyToStencil.SetInputConnection( WorldToModifierLabelmapIjkTransformer.GetOutputPort()) boundsIjk = WorldToModifierLabelmapIjkTransformer.GetOutput( ).GetBounds() modifierLabelmapExtent = self.scriptedEffect.modifierLabelmap( ).GetExtent() polyToStencil.SetOutputWholeExtent(modifierLabelmapExtent[0], modifierLabelmapExtent[1], modifierLabelmapExtent[2], modifierLabelmapExtent[3], int(round(boundsIjk[4])), int(round(boundsIjk[5]))) polyToStencil.Update() stencilData = polyToStencil.GetOutput() stencilExtent = [0, -1, 0, -1, 0, -1] stencilData.SetExtent(stencilExtent) stencilToImage = vtk.vtkImageStencilToImage() stencilToImage.SetInputConnection(polyToStencil.GetOutputPort()) if operationName in ("FILL_INSIDE", "ERASE_INSIDE", "SET"): stencilToImage.SetInsideValue(1.0) stencilToImage.SetOutsideValue(0.0) else: stencilToImage.SetInsideValue(0.0) stencilToImage.SetOutsideValue(1.0) stencilToImage.SetOutputScalarType( modifierLabelmap.GetScalarType()) stencilPositioner = vtk.vtkImageChangeInformation() stencilPositioner.SetInputConnection( stencilToImage.GetOutputPort()) stencilPositioner.SetOutputSpacing(modifierLabelmap.GetSpacing()) stencilPositioner.SetOutputOrigin(modifierLabelmap.GetOrigin()) stencilPositioner.Update() orientedStencilPositionerOuput = vtkSegmentationCore.vtkOrientedImageData( ) orientedStencilPositionerOuput.ShallowCopy( stencilToImage.GetOutput()) imageToWorld = vtk.vtkMatrix4x4() modifierLabelmap.GetImageToWorldMatrix(imageToWorld) orientedStencilPositionerOuput.SetImageToWorldMatrix(imageToWorld) vtkSegmentationCore.vtkOrientedImageDataResample.ModifyImage( modifierLabelmap, orientedStencilPositionerOuput, vtkSegmentationCore.vtkOrientedImageDataResample. OPERATION_MAXIMUM) modMode = slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeAdd if operationName == "ERASE_INSIDE" or operationName == "ERASE_OUTSIDE": modMode = slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeRemove elif operationName == "SET": modMode = slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeSet self.scriptedEffect.modifySelectedSegmentByLabelmap( modifierLabelmap, modMode) import numpy n = self.segmentMarkupNode.GetNumberOfFiducials() # get fiducial positions fPos = numpy.zeros((n, 3)) for i in xrange(n): coord = [0.0, 0.0, 0.0] self.segmentMarkupNode.GetNthFiducialPosition(i, coord) fPos[i] = coord segmentID = self.scriptedEffect.parameterSetNode( ).GetSelectedSegmentID() segment = segmentationNode.GetSegmentation().GetSegment(segmentID) segment.SetTag("fP", fPos.tostring()) segment.SetTag("fN", n) self.reset() self.createNewMarkupNode() self.fiducialPlacementToggle.setCurrentNode(self.segmentMarkupNode) self.observeSegmentation(True) qt.QApplication.restoreOverrideCursor()
#!/usr/bin/env python import vtk from vtk.test import Testing from vtk.util.misc import vtkGetDataRoot VTK_DATA_ROOT = vtkGetDataRoot() # A script to test converting a stencil to a binary image sphere = vtk.vtkSphere() sphere.SetCenter(128,128,0) sphere.SetRadius(80) functionToStencil = vtk.vtkImplicitFunctionToImageStencil() functionToStencil.SetInput(sphere) functionToStencil.SetOutputOrigin(0,0,0) functionToStencil.SetOutputSpacing(1,1,1) functionToStencil.SetOutputWholeExtent(0,255,0,255,0,0) stencilToImage = vtk.vtkImageStencilToImage() stencilToImage.SetInputConnection(functionToStencil.GetOutputPort()) stencilToImage.SetOutsideValue(0) stencilToImage.SetInsideValue(255) viewer = vtk.vtkImageViewer() viewer.SetInputConnection(stencilToImage.GetOutputPort()) viewer.SetZSlice(0) viewer.SetColorWindow(255) viewer.SetColorLevel(127.5) viewer.Render() # --- end of script --
def cutSurfaceWithModel(self, segmentMarkupNode, segmentModel): import vtkSegmentationCore if not segmentMarkupNode: raise AttributeError( f"{self.__class__.__name__}: segment markup node not set.") if not segmentModel: raise AttributeError( f"{self.__class__.__name__}: segment model not set.") if segmentMarkupNode and segmentModel.GetPolyData().GetNumberOfCells( ) > 0: segmentationNode = self.scriptedEffect.parameterSetNode( ).GetSegmentationNode() if not segmentationNode: raise AttributeError( f"{self.__class__.__name__}: Segmentation node not set.") modifierLabelmap = self.scriptedEffect.defaultModifierLabelmap() if not modifierLabelmap: raise AttributeError( "{}: ModifierLabelmap not set. This can happen for various reasons:\n" "No master volume set for segmentation,\n" "No existing segments for segmentation, or\n" "No referenceImageGeometry is specified in the segmentation" .format(self.__class__.__name__)) WorldToModifierLabelmapIjkTransform = vtk.vtkTransform() WorldToModifierLabelmapIjkTransformer = vtk.vtkTransformPolyDataFilter( ) WorldToModifierLabelmapIjkTransformer.SetTransform( WorldToModifierLabelmapIjkTransform) WorldToModifierLabelmapIjkTransformer.SetInputConnection( segmentModel.GetPolyDataConnection()) segmentationToSegmentationIjkTransformMatrix = vtk.vtkMatrix4x4() modifierLabelmap.GetImageToWorldMatrix( segmentationToSegmentationIjkTransformMatrix) segmentationToSegmentationIjkTransformMatrix.Invert() WorldToModifierLabelmapIjkTransform.Concatenate( segmentationToSegmentationIjkTransformMatrix) worldToSegmentationTransformMatrix = vtk.vtkMatrix4x4() slicer.vtkMRMLTransformNode.GetMatrixTransformBetweenNodes( None, segmentationNode.GetParentTransformNode(), worldToSegmentationTransformMatrix) WorldToModifierLabelmapIjkTransform.Concatenate( worldToSegmentationTransformMatrix) WorldToModifierLabelmapIjkTransformer.Update() polyToStencil = vtk.vtkPolyDataToImageStencil() polyToStencil.SetOutputSpacing(1.0, 1.0, 1.0) polyToStencil.SetInputConnection( WorldToModifierLabelmapIjkTransformer.GetOutputPort()) boundsIjk = WorldToModifierLabelmapIjkTransformer.GetOutput( ).GetBounds() modifierLabelmapExtent = self.scriptedEffect.modifierLabelmap( ).GetExtent() polyToStencil.SetOutputWholeExtent(modifierLabelmapExtent[0], modifierLabelmapExtent[1], modifierLabelmapExtent[2], modifierLabelmapExtent[3], int(round(boundsIjk[4])), int(round(boundsIjk[5]))) polyToStencil.Update() stencilData = polyToStencil.GetOutput() stencilExtent = [0, -1, 0, -1, 0, -1] stencilData.SetExtent(stencilExtent) stencilToImage = vtk.vtkImageStencilToImage() stencilToImage.SetInputConnection(polyToStencil.GetOutputPort()) stencilToImage.SetInsideValue(1.0) stencilToImage.SetOutsideValue(0.0) stencilToImage.SetOutputScalarType( modifierLabelmap.GetScalarType()) stencilPositioner = vtk.vtkImageChangeInformation() stencilPositioner.SetInputConnection( stencilToImage.GetOutputPort()) stencilPositioner.SetOutputSpacing(modifierLabelmap.GetSpacing()) stencilPositioner.SetOutputOrigin(modifierLabelmap.GetOrigin()) stencilPositioner.Update() orientedStencilPositionerOutput = vtkSegmentationCore.vtkOrientedImageData( ) orientedStencilPositionerOutput.ShallowCopy( stencilToImage.GetOutput()) imageToWorld = vtk.vtkMatrix4x4() modifierLabelmap.GetImageToWorldMatrix(imageToWorld) orientedStencilPositionerOutput.SetImageToWorldMatrix(imageToWorld) vtkSegmentationCore.vtkOrientedImageDataResample.ModifyImage( modifierLabelmap, orientedStencilPositionerOutput, vtkSegmentationCore.vtkOrientedImageDataResample. OPERATION_MAXIMUM) self.scriptedEffect.modifySelectedSegmentByLabelmap( modifierLabelmap, slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeSet) fPosString = self.getPointsAsString(segmentMarkupNode) segmentID = self.scriptedEffect.parameterSetNode( ).GetSelectedSegmentID() segment = segmentationNode.GetSegmentation().GetSegment(segmentID) segment.SetTag("DrawTubeEffectMarkupPositions", fPosString)
def StereologyAnalysis(self): """Perform stereology analysis on a sub-region of an image""" # user have to define an ROI - enforce fore now... # should allow to use whole image as default event.notify(ProgressEvent("Stereology...", 0.0)) state = self._app_states[self._current_image_index] origin = self._Origin spacing = self._Spacing # --- generate a mask from stencil ---- self.__stencil_data.Update() stencil_image = vtk.vtkImageStencilToImage() stencil_image.SetInput(self.__stencil_data) stencil_image.SetInsideValue(255) stencil_image.SetOutsideValue(0) stencil_image.SetOutputScalarTypeToUnsignedChar() stencil_image.Update() # --- image purify ----- event.notify(ProgressEvent("Stereology: Purify...", 0.2)) roi_image_reslice = self.GetROIImage() # optionally create a purification filter if state.bEnablePurify: purify = _MicroView.vtkImagePurify() purify.SetInputConnection(roi_image_reslice.GetOutputPort()) purify.SetThreshold(self._Threshold) purify.UpdateInformation() # --- Create an object to calculate stereology parameters stereology = _MicroView.vtkImageStereology() if state.bEnablePurify: stereology.SetInputConnection(purify.GetOutputPort()) stereology.SetThreshold(1) else: stereology.SetInputConnection(roi_image_reslice.GetOutputPort()) stereology.SetThreshold(self._Threshold) stereology.SetImageMask(stencil_image.GetOutput()) event.notify(ProgressEvent("Stereology...", 0.4)) stereology.Update() event.notify(ProgressEvent("Stereology...", 0.8)) outfile = StringIO.StringIO() outfile.write('\n==============\n') outfile.write('= Stereology\n') outfile.write('==============\n') outfile.write( ' Total # of points used: {0}\n'.format(stereology.GetnumVoxels())) voxel_volume = self._Spacing[0] * self._Spacing[1] * self._Spacing[2] outfile.write(" Total volume of examined region (mm^3): %10.4f\n" % ( stereology.GetnumVoxels() * voxel_volume,)) if state.bVerboseOutput: outfile.write('\n') outfile.write(' The total number of voxels occupied by bone: %d\n' % int(stereology.GetPp() * stereology.GetnumVoxels())) outfile.write( ' The number of intersections (entering and leaving) for each direction:\n') outfile.write(' %d %d : %d %d : %d %d\n' % ( stereology.GetIntX(), stereology.GetIntXO(), stereology.GetIntY(), stereology.GetIntYO(), stereology.GetIntZ(), stereology.GetIntZO())) outfile.write('\n') outfile.write(' The Euler # found using 27 surrounding voxels: {0}\n'.format( stereology.GetEuler3D())) outfile.write(" -Euler # / Volume analyzed (1/mm^3): %0.5f\n" % ( -1.0 * stereology.GetEuler3D() / voxel_volume / stereology.GetnumVoxels())) outfile.write('\n') outfile.write( ' Morphologic variables calculated from total planar intersection counts:\n') outfile.write( ' BV/TV BS/BV Tb.Th Tb.N Tb.Sp\n') format = '%0.6f %0.6f %0.6f %0.6f %0.6f' if state.bVerboseOutput: outfile.write(' (x) ' + format % ( stereology.GetBVTV(), stereology.GetxBSBV(), stereology.GetxTbTh(), stereology.GetxTbN(), stereology.GetxTbSp()) + '\n') outfile.write(' (y) ' + format % ( stereology.GetBVTV(), stereology.GetyBSBV(), stereology.GetyTbTh(), stereology.GetyTbN(), stereology.GetyTbSp()) + '\n') outfile.write(' (z) ' + format % ( stereology.GetBVTV(), stereology.GetzBSBV(), stereology.GetzTbTh(), stereology.GetzTbN(), stereology.GetzTbSp()) + '\n') outfile.write(' (avg) ' + format % ( stereology.GetBVTV(), stereology.GetBSBV(), stereology.GetTbTh(), stereology.GetTbN(), stereology.GetTbSp()) + '\n') outfile.write('\n') self._ResultsDict['StereologyTotalPoints'] = stereology.GetnumVoxels() self._ResultsDict[ 'StereologyTotalVolume'] = stereology.GetnumVoxels() * voxel_volume self._ResultsDict['StereologyBoneVoxels'] = int( stereology.GetPp() * stereology.GetnumVoxels()) self._ResultsDict['StereologyEulerNumber'] = stereology.GetEuler3D() self._ResultsDict['StereologyEulerVolume'] = -1.0 * \ stereology.GetEuler3D() / voxel_volume / stereology.GetnumVoxels() self._ResultsDict['StereologyAvgBVTV'] = stereology.GetBVTV() self._ResultsDict['StereologyAvgBSBV'] = stereology.GetBSBV() self._ResultsDict['StereologyAvgTbTh'] = stereology.GetTbTh() self._ResultsDict['StereologyAvgTbN'] = stereology.GetTbN() self._ResultsDict['StereologyAvgTbSp'] = stereology.GetTbSp() self._StereologyOutStr = outfile.getvalue() outfile.close() event.notify(ProgressEvent("Stereology: Done.", 1.0)) # normal status return 0