def maskVolume(self, volumeIn, roiNode, inPlace=False): # Clone input volume, unless inPlace inPlace = False # TODO: make this work nameout = volumeIn.GetName() if not "masked" in nameout: nameout += " masked" if inPlace: outData = vtk.vtkImageData() volumeIn.SetName(volumeIn.GetName() + " masked") else: volumeOut = slicer.modules.volumes.logic().CloneVolume(volumeIn, nameout) outData = volumeOut.GetImageData() # Get transform into image space IJKtoRAS = vtk.vtkMatrix4x4() volumeIn.GetIJKToRASMatrix(IJKtoRAS) # Get ROI to image transform ROItoImage = vtk.vtkMatrix4x4() ROItoImage.Identity() parentNode = roiNode.GetParentTransformNode() if parentNode is None and volumeIn.GetParentTransformNode(): volumeIn.GetParentTransformNode().GetMatrixTransformToWorld(ROItoImage) # don't invert here, this is already the proper direction. if parentNode is not None: parentNode.GetMatrixTransformToNode(volumeIn.GetParentTransformNode(), ROItoImage) ROItoImage.Invert() # Transformations tfm = vtk.vtkTransform() tfm.SetMatrix(IJKtoRAS) tfm.PostMultiply() tfm.Concatenate(ROItoImage) # Get planes and apply transform planes = vtk.vtkPlanes() roiNode.GetTransformedPlanes(planes) planes.SetTransform(tfm) # Blot out selected region tostencil = vtk.vtkImplicitFunctionToImageStencil() tostencil.SetInput(planes) imgstencil = vtk.vtkImageStencil() imgstencil.SetInput(volumeIn.GetImageData()) imgstencil.SetStencil(tostencil.GetOutput()) imgstencil.SetBackgroundValue(0) imgstencil.ReverseStencilOn() # Write the changes imgstencil.SetOutput(outData) imgstencil.Update()
def clipVolumeWithRoi(self, roiNode, volumeNode, fillValue, clipOutsideSurface, outputVolume): # Create a box implicit function that will be used as a stencil to fill the volume roiBox = vtk.vtkBox() roiCenter = [0, 0, 0] roiNode.GetXYZ(roiCenter) roiRadius = [0, 0, 0] roiNode.GetRadiusXYZ(roiRadius) roiBox.SetBounds(roiCenter[0] - roiRadius[0], roiCenter[0] + roiRadius[0], roiCenter[1] - roiRadius[1], roiCenter[1] + roiRadius[1], roiCenter[2] - roiRadius[2], roiCenter[2] + roiRadius[2]) # Determine the transform between the box and the image IJK coordinate systems rasToBox = vtk.vtkMatrix4x4() if roiNode.GetTransformNodeID() != None: roiBoxTransformNode = slicer.mrmlScene.GetNodeByID( roiNode.GetTransformNodeID()) boxToRas = vtk.vtkMatrix4x4() roiBoxTransformNode.GetMatrixTransformToWorld(boxToRas) rasToBox.DeepCopy(boxToRas) rasToBox.Invert() ijkToRas = vtk.vtkMatrix4x4() volumeNode.GetIJKToRASMatrix(ijkToRas) ijkToBox = vtk.vtkMatrix4x4() vtk.vtkMatrix4x4.Multiply4x4(rasToBox, ijkToRas, ijkToBox) ijkToBoxTransform = vtk.vtkTransform() ijkToBoxTransform.SetMatrix(ijkToBox) roiBox.SetTransform(ijkToBoxTransform) # Use the stencil to fill the volume imageData = volumeNode.GetImageData() # Convert the implicit function to a stencil functionToStencil = vtk.vtkImplicitFunctionToImageStencil() functionToStencil.SetInput(roiBox) functionToStencil.SetOutputOrigin(imageData.GetOrigin()) functionToStencil.SetOutputSpacing(imageData.GetSpacing()) functionToStencil.SetOutputWholeExtent(imageData.GetExtent()) functionToStencil.Update() # Apply the stencil to the volume stencilToImage = vtk.vtkImageStencil() stencilToImage.SetInputData(imageData) stencilToImage.SetStencilData(functionToStencil.GetOutput()) if clipOutsideSurface: stencilToImage.ReverseStencilOff() else: stencilToImage.ReverseStencilOn() stencilToImage.SetBackgroundValue(fillValue) stencilToImage.Update() # Update the volume with the stencil operation result outputImageData = vtk.vtkImageData() outputImageData.DeepCopy(stencilToImage.GetOutput()) outputVolume.SetAndObserveImageData(outputImageData) outputVolume.SetIJKToRASMatrix(ijkToRas) # Add a default display node to output volume node if it does not exist yet if not outputVolume.GetDisplayNode: displayNode = slicer.vtkMRMLScalarVolumeDisplayNode() displayNode.SetAndObserveColorNodeID("vtkMRMLColorTableNodeGrey") slicer.mrmlScene.AddNode(displayNode) outputVolume.SetAndObserveDisplayNodeID(displayNode.GetID())
def clipVolumeWithModel(self, inputVolume, clippingModel, clipOutsideSurface, fillOutsideValue, clipInsideSurface, fillInsideValue, outputVolume): """ Fill voxels of the input volume inside/outside the clipping model with the provided fill value """ # Determine the transform between the box and the image IJK coordinate systems rasToModel = vtk.vtkMatrix4x4() if clippingModel.GetTransformNodeID() != None: modelTransformNode = slicer.mrmlScene.GetNodeByID( clippingModel.GetTransformNodeID()) boxToRas = vtk.vtkMatrix4x4() modelTransformNode.GetMatrixTransformToWorld(boxToRas) rasToModel.DeepCopy(boxToRas) rasToModel.Invert() ijkToRas = vtk.vtkMatrix4x4() inputVolume.GetIJKToRASMatrix(ijkToRas) ijkToModel = vtk.vtkMatrix4x4() vtk.vtkMatrix4x4.Multiply4x4(rasToModel, ijkToRas, ijkToModel) modelToIjkTransform = vtk.vtkTransform() modelToIjkTransform.SetMatrix(ijkToModel) modelToIjkTransform.Inverse() transformModelToIjk = vtk.vtkTransformPolyDataFilter() transformModelToIjk.SetTransform(modelToIjkTransform) transformModelToIjk.SetInputConnection( clippingModel.GetPolyDataConnection()) # Use the stencil to fill the volume # Convert model to stencil polyToStencil = vtk.vtkPolyDataToImageStencil() polyToStencil.SetInputConnection(transformModelToIjk.GetOutputPort()) polyToStencil.SetOutputSpacing(inputVolume.GetImageData().GetSpacing()) polyToStencil.SetOutputOrigin(inputVolume.GetImageData().GetOrigin()) polyToStencil.SetOutputWholeExtent( inputVolume.GetImageData().GetExtent()) # Apply the stencil to the volume stencilToImage = vtk.vtkImageStencil() stencilToImage.SetInputConnection(inputVolume.GetImageDataConnection()) stencilToImage.SetStencilConnection(polyToStencil.GetOutputPort()) # Create a copy of the input volume to work on outputImageData = vtk.vtkImageData() outputImageData.DeepCopy(inputVolume.GetImageData()) outputVolume.SetAndObserveImageData(outputImageData) outputVolume.SetIJKToRASMatrix(ijkToRas) # Update volume with the stencil operation result depending on user choices if clipOutsideSurface: stencilToImage.ReverseStencilOff() stencilToImage.SetBackgroundValue(fillOutsideValue) stencilToImage.Update() outputImageData.DeepCopy(stencilToImage.GetOutput()) outputVolume.SetAndObserveImageData(outputImageData) outputVolume.SetIJKToRASMatrix(ijkToRas) if clipInsideSurface: stencilToImage.SetInputConnection( outputVolume.GetImageDataConnection()) stencilToImage.ReverseStencilOn() stencilToImage.SetBackgroundValue(fillInsideValue) stencilToImage.Update() outputImageData.DeepCopy(stencilToImage.GetOutput()) outputVolume.SetAndObserveImageData(outputImageData) outputVolume.SetIJKToRASMatrix(ijkToRas) # Add a default display node to output volume node if it does not exist yet if not outputVolume.GetDisplayNode: displayNode = slicer.vtkMRMLScalarVolumeDisplayNode() displayNode.SetAndObserveColorNodeID("vtkMRMLColorTableNodeGrey") slicer.mrmlScene.AddNode(displayNode) outputVolume.SetAndObserveDisplayNodeID(displayNode.GetID()) return True
def makeMaskVolumeFromROI(self, refVolumeNode, maskVolumeNode, roiNode): # Create a box implicit function that will be used as a stencil to fill the volume roiBox = vtk.vtkBox() roiCenter = [0, 0, 0] roiNode.GetXYZ( roiCenter ) roiRadius = [0, 0, 0] roiNode.GetRadiusXYZ( roiRadius ) roiBox.SetBounds(roiCenter[0] - roiRadius[0], roiCenter[0] + roiRadius[0], roiCenter[1] - roiRadius[1], roiCenter[1] + roiRadius[1], roiCenter[2] - roiRadius[2], roiCenter[2] + roiRadius[2]) # Determine the transform between the box and the image IJK coordinate systems rasToBox = vtk.vtkMatrix4x4() if roiNode.GetTransformNodeID() != None: roiBoxTransformNode = slicer.mrmlScene.GetNodeByID(roiNode.GetTransformNodeID()) boxToRas = vtk.vtkMatrix4x4() roiBoxTransformNode.GetMatrixTransformToWorld(boxToRas) rasToBox.DeepCopy(boxToRas) rasToBox.Invert() ijkToRas = vtk.vtkMatrix4x4() refVolumeNode.GetIJKToRASMatrix( ijkToRas ) ijkToBox = vtk.vtkMatrix4x4() vtk.vtkMatrix4x4.Multiply4x4(rasToBox,ijkToRas,ijkToBox) ijkToBoxTransform = vtk.vtkTransform() ijkToBoxTransform.SetMatrix(ijkToBox) roiBox.SetTransform(ijkToBoxTransform) # Use the stencil to fill the volume imageData = vtk.vtkImageData() refImageData = refVolumeNode.GetImageData() imageData.SetOrigin(refImageData.GetOrigin()) imageData.SetSpacing(refImageData.GetSpacing()) if vtk.VTK_MAJOR_VERSION <= 5: imageData.SetExtent(refImageData.GetWholeExtent()) imageData.SetScalarTypeToUnsignedChar() imageData.AllocateScalars() else: imageData.SetExtent(refImageData.GetExtent()) imageData.AllocateScalars(vtk.VTK_UNSIGNED_CHAR,1) # Convert the implicit function to a stencil functionToStencil = vtk.vtkImplicitFunctionToImageStencil() functionToStencil.SetInput(roiBox) functionToStencil.SetOutputOrigin(refImageData.GetOrigin()) functionToStencil.SetOutputSpacing(refImageData.GetSpacing()) if vtk.VTK_MAJOR_VERSION <= 5: functionToStencil.SetOutputWholeExtent(refImageData.GetWholeExtent()) else: functionToStencil.SetOutputWholeExtent(refImageData.GetExtent()) functionToStencil.Update() # Apply the stencil to the volume stencilToImage=vtk.vtkImageStencil() if vtk.VTK_MAJOR_VERSION <= 5: stencilToImage.SetInput(imageData) stencilToImage.SetStencil(functionToStencil.GetOutput()) else: stencilToImage.SetInputData(imageData) stencilToImage.SetStencilData(functionToStencil.GetOutput()) stencilToImage.ReverseStencilOn() stencilToImage.SetBackgroundValue(1) stencilToImage.Update() # Update the volume with the stencil operation result maskVolumeNode.SetAndObserveImageData(stencilToImage.GetOutput()) maskVolumeNode.CopyOrientation(refVolumeNode)
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 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 createSyntheticMask(self, maskVolumeNode, radius): """ Run the actual algorithm """ roiSphere = vtk.vtkSphere() roiCenter = [0, 0, 0] roiOrigin = [0, 0, 0] roiSpacing = [1, 1, 1] roiDimension = [100, 100, 100] # roiDimension = refVolumeNode.GetImageData().GetDimensions() roiCenter[0] = roiOrigin[0] + roiDimension[0] * roiSpacing[0] / 2 roiCenter[1] = roiOrigin[1] + roiDimension[1] * roiSpacing[1] / 2 roiCenter[2] = roiOrigin[2] + roiDimension[2] * roiSpacing[2] / 2 print "roiCenter", roiCenter """ ijkToRas = vtk.vtkMatrix4x4() refVolumeNode.GetIJKToRASMatrix( ijkToRas ) roiPoint = [0,0,0,1]; roiPoint[0] = roiCenter[0] roiPoint[1] = roiCenter[1] roiPoint[2] = roiCenter[2] roiPoint = ijkToRas.MultiplyPoint(roiPoint) roiCenter[0] = roiPoint[0] roiCenter[1] = roiPoint[1] roiCenter[2] = roiPoint[2] print "roiCenter", roiCenter """ roiSphere.SetCenter(roiCenter) roiSphere.SetRadius(radius) # Determine the transform between the box and the image IJK coordinate systems rasToSphere = vtk.vtkMatrix4x4() # if roiNode.GetTransformNodeID() != None: # roiSphereTransformNode = slicer.mrmlScene.GetNodeByID(roiNode.GetTransformNodeID()) # sphereToRas = vtk.vtkMatrix4x4() # roiSphereTransformNode.GetMatrixTransformToWorld(sphereToRas) # rasToSphere.DeepCopy(sphereToRas) # rasToSphere.Invert() """ ijkToSphere = vtk.vtkMatrix4x4() vtk.vtkMatrix4x4.Multiply4x4(rasToSphere,ijkToRas,ijkToSphere) ijkToSphereTransform = vtk.vtkTransform() ijkToSphereTransform.SetMatrix(ijkToSphere) roiSphere.SetTransform(ijkToSphereTransform) # Use the stencil to fill the volume refImageData = refVolumeNode.GetImageData() """ imageSource = vtk.vtkImageNoiseSource() imageSource.SetMinimum(0) imageSource.SetMaximum(0) imageSource.SetWholeExtent(0, roiDimension[0] - 1, 0, roiDimension[1] - 1, 0, roiDimension[2] - 1) imageSource.Update() imageCast = vtk.vtkImageCast() imageCast.SetInputData(imageSource.GetOutput()) imageCast.SetOutputScalarTypeToUnsignedChar() imageCast.Update() """ changeInfo = vtk.vtkImageChangeInformation() changeInfo.SetInputData(imageCast.GetOutput()) changeInfo.SetOutputOrigin(refImageData.GetOrigin()) changeInfo.SetOutputSpacing(refImageData.GetSpacing()) changeInfo.Update() """ # Convert the implicit function to a stencil functionToStencil = vtk.vtkImplicitFunctionToImageStencil() functionToStencil.SetInput(roiSphere) functionToStencil.SetOutputOrigin(0, 0, 0) functionToStencil.SetOutputSpacing(1, 1, 1) functionToStencil.SetOutputWholeExtent(0, roiDimension[0] - 1, 0, roiDimension[1] - 1, 0, roiDimension[2] - 1) functionToStencil.Update() # Apply the stencil to the volume stencilToImage = vtk.vtkImageStencil() stencilToImage.SetInputData(imageCast.GetOutput()) stencilToImage.SetStencilData(functionToStencil.GetOutput()) stencilToImage.ReverseStencilOn() stencilToImage.SetBackgroundValue(1) stencilToImage.Update() """ extent = refImageData.GetWholeExtent() resample = vtk.vtkImageReslice() resample.SetInputData(stencilToImage.GetOutput()) resample.SetOutputOrigin(refImageData.GetOrigin()) resample.SetOutputSpacing(refImageData.GetSpacing()[0]/2, refImageData.GetSpacing()[1]/2, refImageData.GetSpacing()[2]/2 ) resample.SetOutputExtent(extent[0], (extent[1]-extent[0])*2-1, extent[2], (extent[3]-extent[2])*2-1, extent[4], (extent[5]-extent[4])*2-1) resample.Update() changeInfo2 = vtk.vtkImageChangeInformation() changeInfo2.SetInputData(resample.GetOutput()) changeInfo2.SetOutputOrigin(refImageData.GetOrigin()) changeInfo2.SetOutputSpacing(refImageData.GetSpacing()) changeInfo2.Update() """ # Update the volume with the stencil operation result maskVolumeNode.SetAndObserveImageData(stencilToImage.GetOutput()) maskVolumeNode.SetOrigin(0, 0, 0) maskVolumeNode.SetSpacing(1, 1, 1) # maskVolumeNode.CopyOrientation(refVolumeNode) mgr = slicer.app.layoutManager() mgr.sliceWidget( 'Red').sliceLogic().GetSliceCompositeNode().SetLabelVolumeID( maskVolumeNode.GetID()) mgr.sliceWidget( 'Yellow').sliceLogic().GetSliceCompositeNode().SetLabelVolumeID( maskVolumeNode.GetID()) mgr.sliceWidget( 'Green').sliceLogic().GetSliceCompositeNode().SetLabelVolumeID( maskVolumeNode.GetID())
def clipImageWithPolyData(self, inputImageData, outputImageData, clippingPolyData, rasToModel, inputIjkToRas, outputIjkToRas, clipOutsideSurface=True, fillValue=0, reduceExtent=False): """ Fill voxels of the input volume inside/outside the clipping model with the provided fill value If reduceExtent is True then the extent of the volume will be reduced to the smallest possible box that still contains all the non-zero voxels. """ # Determine the transform between the box and the image IJK coordinate systems ijkToModel = vtk.vtkMatrix4x4() vtk.vtkMatrix4x4.Multiply4x4(rasToModel, inputIjkToRas, ijkToModel) modelToIjkTransform = vtk.vtkTransform() modelToIjkTransform.SetMatrix(ijkToModel) modelToIjkTransform.Inverse() transformModelToIjk = vtk.vtkTransformPolyDataFilter() transformModelToIjk.SetTransform(modelToIjkTransform) transformModelToIjk.SetInputData(clippingPolyData) # Use the stencil to fill the volume # Convert model to stencil polyToStencil = vtk.vtkPolyDataToImageStencil() polyToStencil.SetInputConnection(transformModelToIjk.GetOutputPort()) polyToStencil.SetOutputSpacing(inputImageData.GetSpacing()) polyToStencil.SetOutputOrigin(inputImageData.GetOrigin()) polyToStencil.SetOutputWholeExtent(inputImageData.GetExtent()) # Apply the stencil to the volume stencilToImage = vtk.vtkImageStencil() stencilToImage.SetInputData(inputImageData) stencilToImage.SetStencilConnection(polyToStencil.GetOutputPort()) if clipOutsideSurface: stencilToImage.ReverseStencilOff() else: stencilToImage.ReverseStencilOn() stencilToImage.SetBackgroundValue(fillValue) stencilToImage.Update() # Update the volume with the stencil operation result if reduceExtent: clippingPolyDataBounds_Ijk = [0, 0, 0, 0, 0, 0] transformModelToIjk.GetOutput().GetBounds( clippingPolyDataBounds_Ijk) inputVolumeExtent_Ijk = inputImageData.GetExtent() outputVolumeExtent_Ijk = list(inputVolumeExtent_Ijk) # make a copy for i in range(3): a = int(math.floor(clippingPolyDataBounds_Ijk[i * 2])) if a > outputVolumeExtent_Ijk[i * 2]: outputVolumeExtent_Ijk[i * 2] = a b = int(math.ceil(clippingPolyDataBounds_Ijk[i * 2 + 1])) if b < outputVolumeExtent_Ijk[i * 2 + 1]: outputVolumeExtent_Ijk[i * 2 + 1] = b clipper = vtk.vtkImageClip() clipper.SetOutputWholeExtent(outputVolumeExtent_Ijk) clipper.ClipDataOn() clipper.SetInputConnection(stencilToImage.GetOutputPort()) clipper.Update() outputImageData.DeepCopy(clipper.GetOutput()) # Offset the extent to start at [0,0,0] # (maybe this is not needed, but we do it because some code may assume the image extent starts from zero) outputVolumeExtent_Ijk = list(outputImageData.GetExtent()) outputIjkToInputIjk = vtk.vtkMatrix4x4() for i in range(3): outputVolumeExtentOffset = outputVolumeExtent_Ijk[i * 2] outputVolumeExtent_Ijk[i * 2] = outputVolumeExtent_Ijk[ i * 2] - outputVolumeExtentOffset outputVolumeExtent_Ijk[i * 2 + 1] = outputVolumeExtent_Ijk[ i * 2 + 1] - outputVolumeExtentOffset outputIjkToInputIjk.SetElement(i, 3, outputVolumeExtentOffset) outputImageData.SetExtent(outputVolumeExtent_Ijk) vtk.vtkMatrix4x4.Multiply4x4(inputIjkToRas, outputIjkToInputIjk, outputIjkToRas) else: outputImageData.DeepCopy(stencilToImage.GetOutput()) outputIjkToRas.DeepCopy(inputIjkToRas)
def roiSegment(self, inputSelector, seedingSelector, seedingBSelector, labelmapSelector): ########################## ## read input volume node #### inputVolume = inputSelector.currentNode() # extract array inputVolumeData = slicer.util.array(inputVolume.GetID()) # input label map labelMap = labelmapSelector.currentNode() ########################## ## read seeding ROI #### seedingROI = seedingSelector boundROI = seedingBSelector # center and radius of foreground seeding points seedingROIcenter = [0, 0, 0] seedingROIRadius = [0, 0, 0] seedingROI.GetXYZ(seedingROIcenter) seedingROI.GetRadiusXYZ(seedingROIRadius) roiSBox = vtk.vtkBox() roiSBox.SetBounds(seedingROIcenter[0] - seedingROIRadius[0], seedingROIcenter[0] + seedingROIRadius[0], seedingROIcenter[1] - seedingROIRadius[1], seedingROIcenter[1] + seedingROIRadius[1], seedingROIcenter[2] - seedingROIRadius[2], seedingROIcenter[2] + seedingROIRadius[2]) # center and radius of bounding box boundROIcenter = [0, 0, 0] boundROIRadius = [0, 0, 0] boundROI.GetXYZ(boundROIcenter) boundROI.GetRadiusXYZ(boundROIRadius) roiBBox = vtk.vtkBox() roiBBox.SetBounds(boundROIcenter[0] - boundROIRadius[0], boundROIcenter[0] + boundROIRadius[0], boundROIcenter[1] - boundROIRadius[1], boundROIcenter[1] + boundROIRadius[1], boundROIcenter[2] - boundROIRadius[2], boundROIcenter[2] + boundROIRadius[2]) # transform between ijk and ras rasToBox = vtk.vtkMatrix4x4() if boundROI.GetTransformNodeID() != None: roiBoxTransformNode = slicer.mrmlScene.GetNodeByID( boundROI.GetTransformNodeID()) boxToRas = vtk.vtkMatrix4x4() roiBoxTransformNode.GetMatrixTransformToWorld(boxToRas) rasToBox.DeepCopy(boxToRas) rasToBox.Invert() rasToSBox = vtk.vtkMatrix4x4() if seedingROI.GetTransformNodeID() != None: seedingBoxTransformNode = slicer.mrmlScene.GetNodeByID( seedingROI.GetTransformNodeID()) sboxToRas = vtk.vtkMatrix4x4() seedingBoxTransformNode.GetMatrixTransformToWorld(sboxToRas) rasToSBox.DeepCopy(sboxToRas) rasToSBox.Invert() ijkToRas = vtk.vtkMatrix4x4() labelMap.GetIJKToRASMatrix(ijkToRas) ijkToBox = vtk.vtkMatrix4x4() ijkToSBox = vtk.vtkMatrix4x4() vtk.vtkMatrix4x4.Multiply4x4(rasToBox, ijkToRas, ijkToBox) vtk.vtkMatrix4x4.Multiply4x4(rasToSBox, ijkToRas, ijkToSBox) ijkToBoxTransform = vtk.vtkTransform() ijkToBoxTransform.SetMatrix(ijkToBox) roiBBox.SetTransform(ijkToBoxTransform) ijkToBoxTransform.SetMatrix(ijkToSBox) roiSBox.SetTransform(ijkToBoxTransform) imageData = labelMap.GetImageData() # show boudning area and seeding area in label map # label the bounding region functionToStencil = vtk.vtkImplicitFunctionToImageStencil() functionToStencil.SetInput(roiBBox) functionToStencil.SetOutputOrigin(imageData.GetOrigin()) functionToStencil.SetOutputSpacing(imageData.GetSpacing()) functionToStencil.SetOutputWholeExtent(imageData.GetExtent()) functionToStencil.Update() stencilToImage = vtk.vtkImageStencil() stencilToImage.SetInputData(imageData) stencilToImage.SetStencilData(functionToStencil.GetOutput()) stencilToImage.ReverseStencilOn() stencilToImage.SetBackgroundValue(2.00) # set background label to 2 stencilToImage.Update() imageData.DeepCopy(stencilToImage.GetOutput()) # label the seeding region functionToStencil = vtk.vtkImplicitFunctionToImageStencil() functionToStencil.SetInput(roiSBox) functionToStencil.SetOutputOrigin(imageData.GetOrigin()) functionToStencil.SetOutputSpacing(imageData.GetSpacing()) functionToStencil.SetOutputWholeExtent(imageData.GetExtent()) functionToStencil.Update() stencilToImage = vtk.vtkImageStencil() stencilToImage.SetInputData(imageData) stencilToImage.SetStencilData(functionToStencil.GetOutput()) stencilToImage.ReverseStencilOn() stencilToImage.SetBackgroundValue(3.00) stencilToImage.Update() imageData.DeepCopy(stencilToImage.GetOutput()) # update label map labelMap.Modified() ########################## ## output label map #### labelMapData = slicer.util.array(labelMap.GetID()) ########################## ## segmentation #### #determine threshold from seeding points s = np.where(labelMapData == 3) # get seeding points location threshold = np.median(inputVolumeData[s[0], s[1], s[2]]) # check voxels within the bounding region t = np.where(np.logical_or(labelMapData == 2, labelMapData == 3)) for w in range(len(t[0])): i = t[0][w] j = t[1][w] k = t[2][w] if (inputVolumeData[i, j, k] < threshold + 50) and ( inputVolumeData[i, j, k] > threshold - 30): labelMapData[i, j, k] = 1 ####################################################### # set background to zero labelMapData[labelMapData != 1] = 0