def createMaskfromMesh(self, VOI_mesh, im): """ Takes an image and a VOI_mesh and returns a boolean image with only 1s inside the VOI_mesh """ VOIStencil = vtk.vtkROIStencilSource() VOIStencil.SetShapeToBox() VOIStencil.SetBounds( VOI_mesh.GetBounds() ) VOIStencil.SetInformationInput(im) VOIStencil.Update() # cut the corresponding white image and set the background: imgstenc = vtk.vtkImageStencil() imgstenc.SetInput(im) imgstenc.SetStencil(VOIStencil.GetOutput()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(5000) imgstenc.Update() # write to image dims = im.GetDimensions() scalars = imgstenc.GetOutput().GetPointData().GetScalars() np_scalars = vtk_to_numpy(scalars) np_scalars = np_scalars.reshape(dims[2], dims[1], dims[0]) np_scalars = np_scalars.transpose(2,1,0) return np_scalars
def extract_lesionSI_mha(self, T2image, lesion3D, image_pos_pat, image_ori_pat, loadDisplay): """ extract_lesionSI: Use lesion segmentation to extract lesion SI INPUTS: ======= images: (vtkImageData) list of Input image to Transform lesion3D: (vtkPolyData) segmentation OUTPUTS: ======= lesionSI (float) Signal intensity from lesion lesion_scalar_range (float[3]) SI range inside lesion """ ## Transform T2 img loadDisplay = Display() # Proceed to build reference frame for display objects based on DICOM coords t_T2image = loadDisplay.mhaTransform(T2image, image_pos_pat, image_ori_pat) # Update info t_T2image.UpdateInformation() # create a simple box VOI mask shape using previously found boundsPlane_preselected VOIStencil = vtk.vtkROIStencilSource() VOIStencil.SetShapeToBox() VOIStencil.SetBounds( lesion3D.GetBounds() ) VOIStencil.SetInformationInput(t_T2image) VOIStencil.Update() self.boxWidget.PlaceWidget( lesion3D.GetBounds() ) self.boxWidget.On() # cut the corresponding VOI region and set the background: extractVOIlesion_imgstenc = vtk.vtkImageStencil() extractVOIlesion_imgstenc.SetInput(t_T2image) extractVOIlesion_imgstenc.SetStencil(VOIStencil.GetOutput()) extractVOIlesion_imgstenc.ReverseStencilOff() extractVOIlesion_imgstenc.SetBackgroundValue(5000) extractVOIlesion_imgstenc.Update() # take out average image finallesionSIIm = vtk.vtkImageData() finallesionSIIm = extractVOIlesion_imgstenc.GetOutput() ## extract scalars dims = finallesionSIIm.GetDimensions() scalars = finallesionSIIm.GetPointData().GetScalars() np_scalars = vtk_to_numpy(scalars) np_scalars = np_scalars.reshape(dims[2], dims[1], dims[0]) np_scalars = np_scalars.transpose(2,1,0) lesionSI = np_scalars[np_scalars<5000] print "\nLesion_scalar Range:" lesion_scalar_range = [lesionSI.min(), lesionSI.max()] print lesion_scalar_range[0], lesion_scalar_range[1] return lesionSI, lesion_scalar_range
def getModelROIStencil(self): import time _t0 = time.time() t1 = self.__Transform.GetInverse() roi_type = self.getModelROIType() roi_orientation = self.getModelROIOrientation() # bounds, extent and center b = self.getModelROIBounds() # abort early if we haven't been fully set up yet if b is None: return None # determine transformed boundary _index = [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3, 5]] b_t = [1e38, -1e38, 1e38, -1e38, 1e38, -1e38] is_identity = True # is transform identity? is_identity = self.__Transform.GetMatrix().Determinant() == 1.0 # is_identity = False for i in range(8): i2 = _index[i] pt = [b[i2[0]], b[i2[1]], b[i2[2]]] _temp = self.__Transform.TransformPoint(pt[0], pt[1], pt[2]) b_t[0] = min(_temp[0], b_t[0]) b_t[1] = max(_temp[0], b_t[1]) b_t[2] = min(_temp[1], b_t[2]) b_t[3] = max(_temp[1], b_t[3]) b_t[4] = min(_temp[2], b_t[4]) b_t[5] = max(_temp[2], b_t[5]) e_t = self._BoundsToExtent(b_t) # sanity check - check for inversion (caused by negative spacing) e_t = list(e_t) for i in range(3): if e_t[i * 2] > e_t[i * 2 + 1]: v = e_t[i * 2] e_t[i * 2] = e_t[i * 2 + 1] e_t[i * 2 + 1] = v # expand stencil extent by one pixel on all sides e_t = (e_t[0] - 1, e_t[1] + 1, e_t[2] - 1, e_t[3] + 1, e_t[4] - 1, e_t[5] + 1) # make sure we're dealing with ints e_t = map(int, e_t) if is_identity: # fast, but limited to canonical objects self._StencilGenerator = vtk.vtkROIStencilSource() else: # slow, but more generic self._StencilGenerator = vtk.vtkImplicitFunctionToImageStencil() self._StencilGenerator.SetOutputOrigin(self.getImageOrigin()) self._StencilGenerator.SetOutputSpacing(self.getImageSpacing()) # set extent of stencil - taking into account transformation self._StencilGenerator.SetOutputWholeExtent(e_t) if is_identity: # use DG's fast routines if roi_type == "box": self._StencilGenerator.SetShapeToBox() elif roi_type == "cylinder": if roi_orientation == "X": self._StencilGenerator.SetShapeToCylinderX() elif roi_orientation == "Y": self._StencilGenerator.SetShapeToCylinderY() elif roi_orientation == "Z": self._StencilGenerator.SetShapeToCylinderZ() elif roi_type == "ellipsoid": self._StencilGenerator.SetShapeToEllipsoid() self._StencilGenerator.SetBounds(b) else: # use JG's slow routines if roi_type == "box": obj = vtk.vtkBox() obj.SetTransform(t1) obj.SetBounds(b) elif roi_type == "cylinder": cyl = vtk.vtkCylinder() cyl.SetRadius(1.0) xc, yc, zc = (b[1] + b[0]) * 0.5, (b[3] + b[2]) * 0.5, (b[5] + b[4]) * 0.5 diam_a, diam_b, diam_c = (b[1] - b[0]), (b[3] - b[2]), (b[5] - b[4]) # The cylinder is infinite in extent, so needs to be cropped by using the intersection # of three implicit functions -- the cylinder, and two cropping # planes obj = vtk.vtkImplicitBoolean() obj.SetOperationTypeToIntersection() obj.AddFunction(cyl) clip1 = vtk.vtkPlane() clip1.SetNormal(0, 1, 0) obj.AddFunction(clip1) clip2 = vtk.vtkPlane() clip2.SetNormal(0, -1, 0) obj.AddFunction(clip2) t2 = vtk.vtkTransform() t2.Translate(xc, yc, zc) if roi_orientation == "X": # cylinder is infinite in extent in the y-axis t2.Scale(1, diam_b / 2.0, diam_c / 2.0) t2.RotateZ(90) r = diam_a / 2.0 elif roi_orientation == "Y": # cylinder is infinite in extent in the y-axis t2.Scale(diam_a / 2.0, 1, diam_c / 2.0) r = diam_b / 2.0 elif roi_orientation == "Z": # cylinder is infinite in extent in the y-axis t2.Scale(diam_a / 2.0, diam_b / 2.0, 1) t2.RotateX(90) r = diam_c / 2.0 clip1.SetOrigin(0, r, 0) clip2.SetOrigin(0, -r, 0) # combine transforms t2.SetInput(self.__Transform) obj.SetTransform(t2.GetInverse()) elif roi_type == "ellipsoid": obj = vtk.vtkSphere() obj.SetRadius(1.0) xc, yc, zc = (b[1] + b[0]) * 0.5, (b[3] + b[2]) * 0.5, (b[5] + b[4]) * 0.5 diam_a, diam_b, diam_c = (b[1] - b[0]), (b[3] - b[2]), (b[5] - b[4]) t2 = vtk.vtkTransform() t2.Translate(xc, yc, zc) t2.Scale(diam_a / 2.0, diam_b / 2.0, diam_c / 2.0) # combine transforms t2.SetInput(self.__Transform) obj.SetTransform(t2.GetInverse()) self._StencilGenerator.SetInput(obj) _t1 = time.time() self._StencilGenerator.Update() _t2 = time.time() return self._StencilGenerator.GetOutput()
def segmentFromSeeds(self, images, image_pos_pat, image_ori_pat, seeds, iren, xplane, yplane, zplane): """ segmentFromSeeds: Extracts VOI from seeds INPUTS: ======= images: (vtkImageData) list of Input image to Transform seeds: vtkPoints list of seeded coordinates from picker OUTPUTS: ======= transformed_image (vtkImageData) Transformed imaged mapped to dicom coords frame transform (vtkTransform) Transform used """ for postS in range(1,len(images)): print "\n Segmenting image post no : %s " % str(postS) subimage = self.loadDisplay.subImage(images, postS) # Proceed to build reference frame for display objects based on DICOM coords [transformed_image, transform_cube] = self.loadDisplay.dicomTransform(subimage, image_pos_pat, image_ori_pat) # Calculate the center of the volume transformed_image.UpdateInformation() print "\nBoxwidget placed..." ################################################################# # The box widget observes the events invoked by the render window # interactor. These events come from user interaction in the render # window. # Place the interactor initially. The output of the reader is used to # place the box widget. self.boxWidget = vtk.vtkBoxWidget() self.boxWidget.SetInteractor(iren) self.boxWidget.SetPlaceFactor(1) self.boxWidget.SetInput(transformed_image) if( self.boundsPlane_presel != []): self.boxWidget.PlaceWidget( self.boundsPlane_presel ) # Construct a bounding box around the seeds init_seedsBounds = [0,0,0,0,0,0] seeds.GetBounds( init_seedsBounds ) if postS == 1: # polygonal data --> image stencil: # create a simple box VOI mask shape using previously found boundsPlane_preselected VOIStencil = vtk.vtkROIStencilSource() VOIStencil.SetShapeToBox() VOIStencil.SetBounds( init_seedsBounds ) VOIStencil.SetInformationInput(transformed_image) VOIStencil.Update() # cut the corresponding VOI region and set the background: extractVOI_imgstenc = vtk.vtkImageStencil() extractVOI_imgstenc.SetInput(transformed_image) extractVOI_imgstenc.SetStencil(VOIStencil.GetOutput()) extractVOI_imgstenc.ReverseStencilOff() extractVOI_imgstenc.SetBackgroundValue(0.0) extractVOI_imgstenc.Update() allSeededIm = vtk.vtkImageData() allSeededIm.DeepCopy( extractVOI_imgstenc.GetOutput() ) # Add some bounding box radius self.boxWidget.PlaceWidget( init_seedsBounds ) self.boundsPlane_presel = init_seedsBounds print "seeds.GetBounds" print init_seedsBounds self.boxWidget.AddObserver("InteractionEvent", self.SelectPolygons) self.boxWidget.On() # turn off planes xplane.Off() yplane.Off() iren.Start() self.boxWidget.Off() # polygonal data --> image stencil: print "\n Create vtkPolyDataToImageStencil with bounds:" print self.boundsPlane_presel # create a simple box VOI mask shape using previously found boundsPlane_preselected VOIStencil = vtk.vtkROIStencilSource() VOIStencil.SetShapeToBox() VOIStencil.SetBounds( self.boundsPlane_presel ) VOIStencil.SetInformationInput(transformed_image) VOIStencil.Update() # cut the corresponding VOI region and set the background: extractVOI_imgstenc = vtk.vtkImageStencil() extractVOI_imgstenc.SetInput(transformed_image) extractVOI_imgstenc.SetStencil(VOIStencil.GetOutput()) extractVOI_imgstenc.ReverseStencilOff() extractVOI_imgstenc.SetBackgroundValue(0.0) extractVOI_imgstenc.Update() # add subsecuent VOI stencils addsegROI = vtk.vtkImageMathematics() addsegROI.SetInput(0, allSeededIm) addsegROI.SetInput(1, extractVOI_imgstenc.GetOutput()) addsegROI.SetOperationToAdd() addsegROI.Update() # turn off the box allSeededIm = addsegROI.GetOutput() avegSeededIm = vtk.vtkImageMathematics() avegSeededIm.SetInput(0, allSeededIm) avegSeededIm.SetOperationToMultiplyByK() avegSeededIm.SetConstantK( 0.2 ) avegSeededIm.Update() # take out average image finalSeedIm = avegSeededIm.GetOutput() xplane.SetInput( finalSeedIm ) yplane.SetInput( finalSeedIm ) zplane.SetInput( finalSeedIm ) image_scalar_range = finalSeedIm.GetScalarRange() lThre = image_scalar_range[0] uThre = image_scalar_range[1] print "\n Image Scalar Range:" print image_scalar_range[0], image_scalar_range[1] print "Uper thresholding by" print uThre*0.25 ## Display histogram scalars = finalSeedIm.GetPointData().GetScalars() np_scalars = vtk_to_numpy(scalars) pylab.figure() pylab.hist(np_scalars.flatten(), histtype='bar') pylab.show() # Now performed threshold on initialized VOI # vtkImageThresholdConnectivity will perform a flood fill on an image, given upper and lower pixel intensity # thresholds. It works similarly to vtkImageThreshold, but also allows the user to set seed points to limit # the threshold operation to contiguous regions of the image. The filled region, or the "inside", will be passed # through to the output by default, while the "outside" will be replaced with zeros. The scalar type of the output is the same as the input. thresh_sub = vtk.vtkImageThresholdConnectivity() thresh_sub.SetSeedPoints(seeds) thresh_sub.SetNeighborhoodRadius(3, 3, 2) #The radius of the neighborhood that must be within the threshold values in order for the voxel to be included in the mask. The default radius is zero (one single voxel). The radius is measured in voxels thresh_sub.SetNeighborhoodFraction(0.10) #The fraction of the neighborhood that must be within the thresholds. The default value is 0.5. thresh_sub.ThresholdBetween(0.25*uThre, uThre); thresh_sub.SetInput( finalSeedIm ) thresh_sub.Update() xplane.SetInput( thresh_sub.GetOutput() ) yplane.SetInput( thresh_sub.GetOutput() ) zplane.SetInput( thresh_sub.GetOutput() ) iren.Start() # Convert VOIlesion into polygonal struct VOIlesion_poly = vtk.vtkMarchingCubes() VOIlesion_poly.SetValue(0,255) VOIlesion_poly.SetInput(thresh_sub.GetOutput()) VOIlesion_poly.ComputeNormalsOff() VOIlesion_poly.Update() # Recalculate num_voxels and vol_lesion on VOI nvoxels = VOIlesion_poly.GetOutput().GetNumberOfCells() print "\n Number of Voxels: %d" % nvoxels # After the filter has executed, use GetNumberOfVoxels() to find out how many voxels were filled. return VOIlesion_poly.GetOutput()
#!/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 the vtkROIStencilSource reader = vtk.vtkPNGReader() reader.SetDataSpacing(0.8,0.8,1.5) reader.SetDataOrigin(0.0,0.0,0.0) reader.SetFileName("" + str(VTK_DATA_ROOT) + "/Data/fullhead15.png") shiftScale = vtk.vtkImageShiftScale() shiftScale.SetInputConnection(reader.GetOutputPort()) shiftScale.SetScale(0.2) shiftScale.Update() roiStencil1 = vtk.vtkROIStencilSource() roiStencil1.SetShapeToEllipsoid() roiStencil1.SetBounds(20,300,80,150,0,0) roiStencil1.SetInformationInput(reader.GetOutput()) roiStencil2 = vtk.vtkROIStencilSource() roiStencil2.SetShapeToCylinderX() roiStencil2.SetBounds(20,300,80,150,0,0) roiStencil2.SetInformationInput(reader.GetOutput()) roiStencil3 = vtk.vtkROIStencilSource() roiStencil3.SetShapeToCylinderZ() roiStencil3.SetBounds(20,300,80,150,0,0) roiStencil3.SetInformationInput(reader.GetOutput()) roiStencil4 = vtk.vtkROIStencilSource() roiStencil4.SetShapeToBox() roiStencil4.SetBounds(20,300,80,150,0,0) roiStencil4.SetInformationInput(reader.GetOutput())
def load_muscleSI_mha(self, T2image, image_pos_pat, image_ori_pat, m_bounds, iren): """ load_muscleSI: Place automatically a widget over muscle location from file INPUTS: ======= images: (vtkImageData) list of Input image to Transform OUTPUTS: ======= muscleSI (float) Signal intensity from muscle muscleSIcoords (float[3]) cords where Signal intensity from muscle is measured """ ## Transform T2 img loadDisplay = Display() # Proceed to build reference frame for display objects based on DICOM coords t_T2image = loadDisplay.mhaTransform(T2image, image_pos_pat, image_ori_pat) # Calculate the center of the volume t_T2image.UpdateInformation() print "\nBoxwidget placed..." ################################################################# # The box widget observes the events invoked by the render window # interactor. These events come from user interaction in the render # window. # Place the interactor initially. The output of the reader is used to # place the box widget. self.boxWidget = vtk.vtkBoxWidget() self.boxWidget.SetInteractor(iren) self.boxWidget.SetPlaceFactor(1) self.boxWidget.SetInput(t_T2image) self.boxWidget.ScalingEnabledOff() self.boxWidget.OutlineCursorWiresOn() # Construct a bounding box bwidg = [0,0,0,0,0,0] bwidg[0] = m_bounds[0]; bwidg[1] = m_bounds[1]; bwidg[2] = m_bounds[2]; bwidg[3] = m_bounds[3]; bwidg[4] = m_bounds[4]; bwidg[5] = m_bounds[5]; self.bounds_muscleSI = bwidg print "\nbounds_muscleSI " print self.bounds_muscleSI # add to visualize self.boxWidget.PlaceWidget( self.bounds_muscleSI ) self.boxWidget.On() ########## ### Set image stencil for muscle # create a simple box VOI mask shape using previously found boundsPlane_preselected VOIStencil = vtk.vtkROIStencilSource() VOIStencil.SetShapeToBox() VOIStencil.SetBounds( self.bounds_muscleSI ) VOIStencil.SetInformationInput(t_T2image) VOIStencil.Update() # cut the corresponding VOI region and set the background: extractVOI_imgstenc = vtk.vtkImageStencil() extractVOI_imgstenc.SetInput(t_T2image) extractVOI_imgstenc.SetStencil(VOIStencil.GetOutput()) extractVOI_imgstenc.ReverseStencilOff() extractVOI_imgstenc.SetBackgroundValue(5000) extractVOI_imgstenc.Update() # take out average image finalmuscleSIIm = vtk.vtkImageData() finalmuscleSIIm = extractVOI_imgstenc.GetOutput() finalmuscleSIIm.Update() ## Display histogram dims = finalmuscleSIIm .GetDimensions() scalars = finalmuscleSIIm.GetPointData().GetScalars() np_scalars = vtk_to_numpy(scalars) np_scalars = np_scalars.reshape(dims[2], dims[1], dims[0]) np_scalars = np_scalars.transpose(2,1,0) muscleSI = np_scalars[np_scalars<5000] muscle_scalar_range = [muscleSI.min(), muscleSI.max()] print "\nMuscle scalar Range:" print muscle_scalar_range[0], muscle_scalar_range[1] return muscleSI, muscle_scalar_range, self.bounds_muscleSI
def load_muscleSI(self, t_T2image, m_bounds, iren, ren, picker, xplane, yplane, zplane): """ load_muscleSI: Place automatically a widget over muscle location from file INPUTS: ======= images: (vtkImageData) list of Input image to Transform OUTPUTS: ======= muscleSI (float) Signal intensity from muscle muscleSIcoords (float[3]) cords where Signal intensity from muscle is measured """ ## Transform T2 img # loadDisplay = Display() # # # Proceed to build reference frame for display objects based on DICOM coords # [t_T2image, transform_cube] = loadDisplay.dicomTransform(T2image, image_pos_pat, image_ori_pat) # # # Calculate the center of the volume # t_T2image.UpdateInformation() print "\nBoxwidget placed..." ################################################################# # The box widget observes the events invoked by the render window # interactor. These events come from user interaction in the render # window. # Place the interactor initially. The output of the reader is used to # place the box widget. self.boxWidget = vtk.vtkBoxWidget() self.boxWidget.SetInteractor(iren) self.boxWidget.SetPlaceFactor(1) self.boxWidget.SetInput(t_T2image) self.boxWidget.ScalingEnabledOff() self.boxWidget.OutlineCursorWiresOn() # Construct a bounding box bwidg = [0,0,0,0,0,0] bwidg[0] = m_bounds[0]; bwidg[1] = m_bounds[1]; bwidg[2] = m_bounds[2]; bwidg[3] = m_bounds[3]; bwidg[4] = m_bounds[4]; bwidg[5] = m_bounds[5]; self.bounds_muscleSI = bwidg print "\nbounds_muscleSI " print self.bounds_muscleSI # add to visualize self.boxWidget.PlaceWidget( self.bounds_muscleSI ) self.boxWidget.On() #iren.Start() ############################# Do extract_muscleSI print "\n Re-extract muscle VOI? " rexorNot=0 rexorNot = int(raw_input('type 1 to Re-extract or anykey: ')) if rexorNot == 1: # custom interaction self.picker = picker self.textMapper = vtk.vtkTextMapper() tprop = self.textMapper.GetTextProperty() tprop.SetFontFamilyToArial() tprop.SetFontSize(10) tprop.BoldOn() tprop.ShadowOn() tprop.SetColor(1, 0, 0) self.textActor = vtk.vtkActor2D() self.textActor.VisibilityOff() self.textActor.SetMapper(self.textMapper) ren.AddActor2D(self.textActor) picker.AddObserver("EndPickEvent", self.annotatePick) iren.Start() # Construct a bounding box bwidg = [0,0,0,0,0,0] bwidg[0] = self.pickPos[0]; bwidg[1] = self.pickPos[0]+5; bwidg[2] = self.pickPos[1]; bwidg[3] = self.pickPos[1]+5; bwidg[4] = self.pickPos[2]; bwidg[5] = self.pickPos[2]+5; self.bounds_muscleSI = bwidg print "\nbounds_muscleSI " print self.bounds_muscleSI self.boxWidget.PlaceWidget( self.bounds_muscleSI ) # turn off planes xplane.Off() yplane.Off() self.boxWidget.On() ########## ### Set image stencil for muscle # create a simple box VOI mask shape using previously found boundsPlane_preselected VOIStencil = vtk.vtkROIStencilSource() VOIStencil.SetShapeToBox() VOIStencil.SetBounds( self.bounds_muscleSI ) VOIStencil.SetInformationInput(t_T2image) VOIStencil.Update() # cut the corresponding VOI region and set the background: extractVOI_imgstenc = vtk.vtkImageStencil() extractVOI_imgstenc.SetInput(t_T2image) extractVOI_imgstenc.SetStencil(VOIStencil.GetOutput()) extractVOI_imgstenc.ReverseStencilOff() extractVOI_imgstenc.SetBackgroundValue(5000) extractVOI_imgstenc.Update() # take out average image finalmuscleSIIm = vtk.vtkImageData() finalmuscleSIIm = extractVOI_imgstenc.GetOutput() finalmuscleSIIm.Update() ## Display histogram dims = finalmuscleSIIm .GetDimensions() scalars = finalmuscleSIIm.GetPointData().GetScalars() np_scalars = vtk_to_numpy(scalars) np_scalars = np_scalars.reshape(dims[2], dims[1], dims[0]) np_scalars = np_scalars.transpose(2,1,0) muscleSI = np_scalars[np_scalars<5000] print "ave. T2_muscleSI: %d" % mean(muscleSI) muscle_scalar_range = [muscleSI.min(), muscleSI.max()] print "\nMuscle scalar Range:" print muscle_scalar_range[0], muscle_scalar_range[1] return muscleSI, muscle_scalar_range, self.bounds_muscleSI
#!/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 the vtkROIStencilSource reader = vtk.vtkPNGReader() reader.SetDataSpacing(0.8, 0.8, 1.5) reader.SetDataOrigin(0.0, 0.0, 0.0) reader.SetFileName("" + str(VTK_DATA_ROOT) + "/Data/fullhead15.png") shiftScale = vtk.vtkImageShiftScale() shiftScale.SetInputConnection(reader.GetOutputPort()) shiftScale.SetScale(0.2) shiftScale.Update() roiStencil1 = vtk.vtkROIStencilSource() roiStencil1.SetShapeToEllipsoid() roiStencil1.SetBounds(20, 300, 80, 150, 0, 0) roiStencil1.SetInformationInput(reader.GetOutput()) roiStencil2 = vtk.vtkROIStencilSource() roiStencil2.SetShapeToCylinderX() roiStencil2.SetBounds(20, 300, 80, 150, 0, 0) roiStencil2.SetInformationInput(reader.GetOutput()) roiStencil3 = vtk.vtkROIStencilSource() roiStencil3.SetShapeToCylinderZ() roiStencil3.SetBounds(20, 300, 80, 150, 0, 0) roiStencil3.SetInformationInput(reader.GetOutput()) roiStencil4 = vtk.vtkROIStencilSource() roiStencil4.SetShapeToBox() roiStencil4.SetBounds(20, 300, 80, 150, 0, 0) roiStencil4.SetInformationInput(reader.GetOutput())
def getModelROIStencil(self): import time _t0 = time.time() t1 = self.__Transform.GetInverse() roi_type = self.getModelROIType() roi_orientation = self.getModelROIOrientation() # bounds, extent and center b = self.getModelROIBounds() # abort early if we haven't been fully set up yet if b is None: return None # determine transformed boundary _index = [ [0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3, 5], ] b_t = [1e38, -1e38, 1e38, -1e38, 1e38, -1e38] is_identity = True # is transform identity? is_identity = self.__Transform.GetMatrix().Determinant() == 1.0 #is_identity = False for i in range(8): i2 = _index[i] pt = [b[i2[0]], b[i2[1]], b[i2[2]]] _temp = self.__Transform.TransformPoint(pt[0], pt[1], pt[2]) b_t[0] = min(_temp[0], b_t[0]) b_t[1] = max(_temp[0], b_t[1]) b_t[2] = min(_temp[1], b_t[2]) b_t[3] = max(_temp[1], b_t[3]) b_t[4] = min(_temp[2], b_t[4]) b_t[5] = max(_temp[2], b_t[5]) e_t = self._BoundsToExtent(b_t) # sanity check - check for inversion (caused by negative spacing) e_t = list(e_t) for i in range(3): if e_t[i * 2] > e_t[i * 2 + 1]: v = e_t[i * 2] e_t[i * 2] = e_t[i * 2 + 1] e_t[i * 2 + 1] = v # expand stencil extent by one pixel on all sides e_t = (e_t[0] - 1, e_t[1] + 1, e_t[2] - 1, e_t[3] + 1, e_t[4] - 1, e_t[5] + 1) # make sure we're dealing with ints e_t = map(int, e_t) if is_identity: # fast, but limited to canonical objects self._StencilGenerator = vtk.vtkROIStencilSource() else: # slow, but more generic self._StencilGenerator = vtk.vtkImplicitFunctionToImageStencil() self._StencilGenerator.SetOutputOrigin(self.getImageOrigin()) self._StencilGenerator.SetOutputSpacing(self.getImageSpacing()) # set extent of stencil - taking into account transformation self._StencilGenerator.SetOutputWholeExtent(e_t) if is_identity: # use DG's fast routines if roi_type == 'box': self._StencilGenerator.SetShapeToBox() elif roi_type == 'cylinder': if roi_orientation == 'X': self._StencilGenerator.SetShapeToCylinderX() elif roi_orientation == 'Y': self._StencilGenerator.SetShapeToCylinderY() elif roi_orientation == 'Z': self._StencilGenerator.SetShapeToCylinderZ() elif roi_type == 'ellipsoid': self._StencilGenerator.SetShapeToEllipsoid() self._StencilGenerator.SetBounds(b) else: # use JG's slow routines if roi_type == 'box': obj = vtk.vtkBox() obj.SetTransform(t1) obj.SetBounds(b) elif roi_type == 'cylinder': cyl = vtk.vtkCylinder() cyl.SetRadius(1.0) xc, yc, zc = (b[1] + b[0]) * \ 0.5, (b[3] + b[2]) * 0.5, (b[5] + b[4]) * 0.5 diam_a, diam_b, diam_c = ( b[1] - b[0]), (b[3] - b[2]), (b[5] - b[4]) # The cylinder is infinite in extent, so needs to be cropped by using the intersection # of three implicit functions -- the cylinder, and two cropping # planes obj = vtk.vtkImplicitBoolean() obj.SetOperationTypeToIntersection() obj.AddFunction(cyl) clip1 = vtk.vtkPlane() clip1.SetNormal(0, 1, 0) obj.AddFunction(clip1) clip2 = vtk.vtkPlane() clip2.SetNormal(0, -1, 0) obj.AddFunction(clip2) t2 = vtk.vtkTransform() t2.Translate(xc, yc, zc) if roi_orientation == 'X': # cylinder is infinite in extent in the y-axis t2.Scale(1, diam_b / 2.0, diam_c / 2.0) t2.RotateZ(90) r = diam_a / 2.0 elif roi_orientation == 'Y': # cylinder is infinite in extent in the y-axis t2.Scale(diam_a / 2.0, 1, diam_c / 2.0) r = diam_b / 2.0 elif roi_orientation == 'Z': # cylinder is infinite in extent in the y-axis t2.Scale(diam_a / 2.0, diam_b / 2.0, 1) t2.RotateX(90) r = diam_c / 2.0 clip1.SetOrigin(0, r, 0) clip2.SetOrigin(0, -r, 0) # combine transforms t2.SetInput(self.__Transform) obj.SetTransform(t2.GetInverse()) elif roi_type == 'ellipsoid': obj = vtk.vtkSphere() obj.SetRadius(1.0) xc, yc, zc = (b[1] + b[0]) * \ 0.5, (b[3] + b[2]) * 0.5, (b[5] + b[4]) * 0.5 diam_a, diam_b, diam_c = ( b[1] - b[0]), (b[3] - b[2]), (b[5] - b[4]) t2 = vtk.vtkTransform() t2.Translate(xc, yc, zc) t2.Scale(diam_a / 2.0, diam_b / 2.0, diam_c / 2.0) # combine transforms t2.SetInput(self.__Transform) obj.SetTransform(t2.GetInverse()) self._StencilGenerator.SetInput(obj) _t1 = time.time() self._StencilGenerator.Update() _t2 = time.time() return self._StencilGenerator.GetOutput()