def ClipData(self, ROI, noisySurfacePolyData): """ Returns the clipped polydata from the region defined by the ROI Turn on the Debug to make the clipped object appear, For specific filter functionality see DataFlow doc: ClipData.pdf """ connectivityFilter = vtk.vtkPolyDataConnectivityFilter() self.utility.PolyDataWriter( noisySurfacePolyData, "C:\\MakeHDRApplicatorMask\\doc\\" + "DebugPolyData\\PreClipped.vtk" ) connectivityFilter.SetInputData(noisySurfacePolyData) connectivityFilter.SetExtractionModeToLargestRegion() connectivityFilter.Update() self.skinSurface = connectivityFilter.GetOutput() # skinSurface Set if self.DEBUG_CONNECTIVITYFACE: self.utility.DisplayPolyData("ConnectedFace", self.skinSurface) # Expansion of ROI is explained in vtkImplicitModeller limitations ROIExtents = self.utility.GetROIExtents(ROI) BiggerROI = self.utility.ExpandExtents(ROIExtents, 0.5) # See vtkImplicitModdeler limitations.pdf for explanation implicitBoxRegion = vtk.vtkBox() implicitBoxRegion.SetBounds(BiggerROI) clipper = vtk.vtkClipPolyData() clipper.InsideOutOn() # Clip the regions outside of implicit function clipper.SetInputConnection(connectivityFilter.GetOutputPort()) clipper.SetClipFunction(implicitBoxRegion) clipper.Update() self.clippedSurface = clipper.GetOutput() return clipper
def cropScrew(self,input, area): #Get bounds of screw bounds = input.GetPolyData().GetBounds() print bounds #Define bounds for cropping out the head or shaft of the screw respectively if area == 'head': i = bounds[2] j = bounds[3]-17 elif area == 'shaft': i = bounds[3]-17 j = bounds[3] #Create a box with bounds equal to that of the screw minus the head (-17) cropBox = vtk.vtkBox() cropBox.SetBounds(bounds[0],bounds[1],i,j,bounds[4],bounds[5]) #Crop out head of screw extract = vtk.vtkExtractPolyDataGeometry() extract.SetImplicitFunction(cropBox) extract.SetInput(input.GetPolyData()) extract.Update() #PolyData of cropped screw output = extract.GetOutput() return output
def cropScrew(self, input, area): #Get bounds of screw bounds = input.GetPolyData().GetBounds() logging.debug(bounds) #Define bounds for cropping out the head or shaft of the screw respectively if area == 'head': i = bounds[2] j = bounds[3] - 17 elif area == 'shaft': i = bounds[3] - 17 j = bounds[3] #Create a box with bounds equal to that of the screw minus the head (-17) cropBox = vtk.vtkBox() cropBox.SetBounds(bounds[0], bounds[1], i, j, bounds[4], bounds[5]) #Crop out head of screw extract = vtk.vtkExtractPolyDataGeometry() extract.SetImplicitFunction(cropBox) extract.SetInputData(input.GetPolyData()) extract.Update() #PolyData of cropped screw output = extract.GetOutput() return output
def ClipData(self, ROI, noisySurfacePolyData): """ Returns the clipped polydata from the region defined by the ROI Turn on the Debug to make the clipped object appear, For specific filter functionality see DataFlow doc: ClipData.pdf """ connectivityFilter = vtk.vtkPolyDataConnectivityFilter() self.utility.PolyDataWriter(noisySurfacePolyData, "C:\\MakeHDRApplicatorMask\\doc\\"+\ "DebugPolyData\\PreClipped.vtk") connectivityFilter.SetInputData(noisySurfacePolyData) connectivityFilter.SetExtractionModeToLargestRegion() connectivityFilter.Update() self.skinSurface = connectivityFilter.GetOutput() #skinSurface Set if self.DEBUG_CONNECTIVITYFACE: self.utility.DisplayPolyData("ConnectedFace", self.skinSurface) # Expansion of ROI is explained in vtkImplicitModeller limitations ROIExtents = self.utility.GetROIExtents(ROI) BiggerROI = self.utility.ExpandExtents(ROIExtents, .5) #See vtkImplicitModdeler limitations.pdf for explanation implicitBoxRegion = vtk.vtkBox() implicitBoxRegion.SetBounds(BiggerROI) clipper = vtk.vtkClipPolyData() clipper.InsideOutOn() # Clip the regions outside of implicit function clipper.SetInputConnection(connectivityFilter.GetOutputPort()) clipper.SetClipFunction(implicitBoxRegion) clipper.Update() self.clippedSurface = clipper.GetOutput() return clipper
def MinimumDistanceMask(self, vtkAlgorythmObject, distanceFromMask, ROI, ruler, isBubble=False): """ Takes an algorythm object which is will send through a pipeline to create a mask defining the minimum distance value from the skin surface returns an algorythm object as well to preform GetOutput() -> polydata or GetOutputPort() -> algorythm see MinimumDistanceMask.pdf """ if distanceFromMask < 2: print "WARNING: MouldLogic: MinimumDistanceMask implicit", "modeling is very unstable below 1.5 , mask may degrade", "and lines will become discontinuous." Extents = self.utility.GetROIExtents(ROI) if (isBubble): Extents = self.utility.ExpandExtents(Extents, 100) implicitModeller = vtk.vtkImplicitModeller() implicitModeller.SetInputConnection(vtkAlgorythmObject.GetOutputPort()) implicitModeller.SetMaximumDistance(distanceFromMask) implicitModeller.SetModelBounds(Extents) implicitModeller.AdjustBoundsOn() implicitModeller.SetAdjustBounds(10) # Removes the boundary effects implicitModeller.CappingOff( ) # Important to create disjoint inner and outer masks implicitModeller.SetProcessModeToPerVoxel() implicitModeller.Update() contourFilter = vtk.vtkContourFilter() contourFilter.SetValue(0, distanceFromMask) contourFilter.SetInputConnection(implicitModeller.GetOutputPort()) contourFilter.Update() normalsFunction = vtk.vtkPolyDataNormals() normalsFunction.FlipNormalsOn() normalsFunction.AddInputConnection(contourFilter.GetOutputPort()) normalsFunction.Update() implicitBoxRegion = vtk.vtkBox() implicitBoxRegion.SetBounds(Extents) clipper2 = vtk.vtkClipPolyData() clipper2.InsideOutOn() # Clip the regions outside of implicit function clipper2.SetInputConnection(normalsFunction.GetOutputPort()) clipper2.SetClipFunction(implicitBoxRegion) clipper2.Update() closestPoint = [0, 0, 0] ruler.GetPosition1(closestPoint) connectivityFilter = vtk.vtkPolyDataConnectivityFilter() connectivityFilter.SetInputConnection(clipper2.GetOutputPort()) connectivityFilter.SetExtractionModeToClosestPointRegion() connectivityFilter.SetClosestPoint(closestPoint) connectivityFilter.Update() return connectivityFilter.GetOutput()
def MinimumDistanceMask(self, vtkAlgorythmObject, distanceFromMask, ROI, ruler, isBubble=False): """ Takes an algorythm object which is will send through a pipeline to create a mask defining the minimum distance value from the skin surface returns an algorythm object as well to preform GetOutput() -> polydata or GetOutputPort() -> algorythm see MinimumDistanceMask.pdf """ if distanceFromMask < 2: print "WARNING: MouldLogic: MinimumDistanceMask implicit", "modeling is very unstable below 1.5 , mask may degrade", "and lines will become discontinuous." Extents = self.utility.GetROIExtents(ROI) if isBubble: Extents = self.utility.ExpandExtents(Extents, 100) implicitModeller = vtk.vtkImplicitModeller() implicitModeller.SetInputConnection(vtkAlgorythmObject.GetOutputPort()) implicitModeller.SetMaximumDistance(distanceFromMask) implicitModeller.SetModelBounds(Extents) implicitModeller.AdjustBoundsOn() implicitModeller.SetAdjustBounds(10) # Removes the boundary effects implicitModeller.CappingOff() # Important to create disjoint inner and outer masks implicitModeller.SetProcessModeToPerVoxel() implicitModeller.Update() contourFilter = vtk.vtkContourFilter() contourFilter.SetValue(0, distanceFromMask) contourFilter.SetInputConnection(implicitModeller.GetOutputPort()) contourFilter.Update() normalsFunction = vtk.vtkPolyDataNormals() normalsFunction.FlipNormalsOn() normalsFunction.AddInputConnection(contourFilter.GetOutputPort()) normalsFunction.Update() implicitBoxRegion = vtk.vtkBox() implicitBoxRegion.SetBounds(Extents) clipper2 = vtk.vtkClipPolyData() clipper2.InsideOutOn() # Clip the regions outside of implicit function clipper2.SetInputConnection(normalsFunction.GetOutputPort()) clipper2.SetClipFunction(implicitBoxRegion) clipper2.Update() closestPoint = [0, 0, 0] ruler.GetPosition1(closestPoint) connectivityFilter = vtk.vtkPolyDataConnectivityFilter() connectivityFilter.SetInputConnection(clipper2.GetOutputPort()) connectivityFilter.SetExtractionModeToClosestPointRegion() connectivityFilter.SetClosestPoint(closestPoint) connectivityFilter.Update() return connectivityFilter.GetOutput()
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 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 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