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 createMaskfromMesh(self, VOI_mesh, im): """ Takes an image and a VOI_mesh and returns a boolean image with only 1s inside the VOI_mesh """ # Create an Image of Fext white_image = vtk.vtkImageData() white_image.DeepCopy(im) # polygonal data --> image stencil: pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetInput(VOI_mesh) pol2stenc.SetOutputOrigin(im.GetOrigin()) pol2stenc.SetOutputSpacing(im.GetSpacing()) pol2stenc.SetOutputWholeExtent(white_image.GetExtent()) pol2stenc.Update() # cut the corresponding white image and set the background: imgstenc = vtk.vtkImageStencil() imgstenc.SetInput(white_image) imgstenc.SetStencil(pol2stenc.GetOutput()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(0.0) 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 createVTKMaskfromMesh(self, VOI_mesh, im): """ Takes an image and a VOI_mesh and returns a boolean image with only 1s inside the VOI_mesh """ # Create an Image of Fext white_image = vtk.vtkImageData() white_image.DeepCopy(im) white_image.SetScalarTypeToUnsignedChar() white_image.AllocateScalars() count = white_image.GetNumberOfPoints() for i in range(count): white_image.GetPointData().GetScalars().SetTuple1(i, 1.0) # polygonal data --> image stencil: pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetInput(VOI_mesh) pol2stenc.SetOutputOrigin(im.GetOrigin()) pol2stenc.SetOutputSpacing(im.GetSpacing()) pol2stenc.SetOutputWholeExtent(im.GetExtent()) pol2stenc.Update() # cut the corresponding white image and set the background: imgstenc = vtk.vtkImageStencil() imgstenc.SetInput(white_image) imgstenc.SetStencil(pol2stenc.GetOutput()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(0.0) imgstenc.Update() return imgstenc.GetOutput()
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 """ # Create an Image of Fext white_image = vtk.vtkImageData() white_image.DeepCopy(im) # polygonal data --> image stencil: pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetInputData(VOI_mesh) pol2stenc.SetOutputOrigin(im.GetOrigin()) pol2stenc.SetOutputSpacing(im.GetSpacing()) pol2stenc.SetOutputWholeExtent(white_image.GetExtent()) pol2stenc.SetInformationInput(white_image) pol2stenc.Update() # cut the corresponding white image and set the background: imgstenc = vtk.vtkImageStencil() imgstenc.SetInputData(white_image) imgstenc.SetStencilData(pol2stenc.GetOutput()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(0.0) 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 convertPolyDataToImageData(poly, ref_im): """ Convert the vtk polydata to imagedata Args: poly: vtkPolyData ref_im: reference vtkImage to match the polydata with Returns: output: resulted vtkImageData """ ref_im.GetPointData().SetScalars( numpy_to_vtk( np.zeros(vtk_to_numpy(ref_im.GetPointData().GetScalars()).shape))) ply2im = vtk.vtkPolyDataToImageStencil() ply2im.SetTolerance(0.05) ply2im.SetInputData(poly) ply2im.SetOutputSpacing(ref_im.GetSpacing()) ply2im.SetInformationInput(ref_im) ply2im.Update() stencil = vtk.vtkImageStencil() stencil.SetInputData(ref_im) stencil.ReverseStencilOn() stencil.SetStencilData(ply2im.GetOutput()) stencil.Update() output = stencil.GetOutput() return output
def __init__(self, module_manager): SimpleVTKClassModuleBase.__init__( self, module_manager, vtk.vtkPolyDataToImageStencil(), 'Processing.', ('vtkPolyData',), ('vtkImageStencilData',), replaceDoc=True, inputFunctions=None, outputFunctions=None)
def importSTL(filename): reader = vtk.vtkSTLReader() reader.SetFileName(filename) reader.Update() outputVol = np.zeros((500,500,500)) outputVTK = vtk_import_numpy_array(outputVol) dataToStencil = vtk.vtkPolyDataToImageStencil() dataToStencil.SetInputConnection(reader.GetOutputPort()) dataToStencil.SetOutputSpacing(0.5, 0.5, 0.5) dataToStencil.SetOutputOrigin(0.0, 0.0, 0.0) dataToStencil.Update() stencil = vtk.vtkImageStencil() stencil.SetInput(outputVTK.GetOutput()) stencil.SetStencil(dataToStencil.GetOutput()) stencil.ReverseStencilOn() stencil.Update() im = stencil.GetOutput() rows, cols, lines = im.GetDimensions() sc = im.GetPointData().GetScalars() a = vtk_to_numpy(sc) a = a.reshape((lines,cols,rows)) return a
def convert_polydata_to_image_data(poly, ref_im, reverse=True): """ Convert the vtk polydata to imagedata Args: poly: vtkPolyData ref_im: reference vtkImage to match the polydata with Returns: output: resulted vtkImageData """ from vtk.util.numpy_support import vtk_to_numpy, numpy_to_vtk # Have to copy to create a zeroed vtk image data ref_im_zeros = vtk.vtkImageData() ref_im_zeros.DeepCopy(ref_im) ref_im_zeros.GetPointData().SetScalars( numpy_to_vtk( np.zeros( vtk_to_numpy(ref_im_zeros.GetPointData().GetScalars()).shape))) ply2im = vtk.vtkPolyDataToImageStencil() ply2im.SetTolerance(0.05) ply2im.SetInputData(poly) ply2im.SetOutputSpacing(ref_im.GetSpacing()) ply2im.SetInformationInput(ref_im_zeros) ply2im.Update() stencil = vtk.vtkImageStencil() stencil.SetInputData(ref_im_zeros) if reverse: stencil.ReverseStencilOn() stencil.SetStencilData(ply2im.GetOutput()) stencil.Update() output = stencil.GetOutput() return output
def MeshToVolume(Filename): reader = vtk.vtkPolyDataReader() pol2stenc = vtk.vtkPolyDataToImageStencil() imgstenc = vtk.vtkImageStencil() reader.SetFileName(os.path.join(subjects_dir,subject_dir,Filename)) reader.Update() ref_mesh = reader.GetOutput() ref_volume = vtk.vtkImageData() # define output volume dimension spacing = (0.5,0.5,0.5) ref_volume.SetSpacing(spacing) bounds = ref_mesh.GetBounds() dim = [math.ceil(bounds[ii*2+1] - bounds[ii*2] / spacing[ii]) for ii in range(0,3)] origin = [bounds[ii*2] + spacing[ii] / 2 for ii in range(0,3)] extent = (0,dim[0] - 1,0,dim[1] -1 ,0,dim[2]-1) ref_volume.SetOrigin(origin) ref_volume.SetDimensions(dim) ref_volume.SetExtent(extent) ref_volume.SetScalarTypeToUnsignedChar() ref_volume.AllocateScalars() # Fill the image with white voxels for i in range(0,ref_volume.GetNumberOfPoints()): ref_volume.GetPointData().GetScalars().SetTuple1(i,255) print ref_volume.GetNumberOfPoints() pol2stenc.SetInput(ref_mesh) pol2stenc.SetOutputOrigin(origin) pol2stenc.SetOutputSpacing(spacing) pol2stenc.SetOutputWholeExtent(ref_volume.GetExtent()) pol2stenc.Update() imgstenc.SetInput(ref_volume) imgstenc.SetStencil(pol2stenc.GetOutput()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(0) imgstenc.Update() tmp = imgstenc.GetOutput() writer = vtk.vtkImageWriter() writer.SetFileName('prova.nii.gz') writer.SetInput(ref_volume) writer.Update() out = v2n(tmp.GetPointData().GetScalars()) return np.reshape(out, (dim[0],dim[1],dim[2]))
def surf_fill_vtk(vertices, polys, mat, shape): import vtk from vtk.util import numpy_support voxverts = nb.affines.apply_affine(np.linalg.inv(mat), vertices) points = vtk.vtkPoints() points.SetNumberOfPoints(len(voxverts)) for i, pt in enumerate(voxverts): points.InsertPoint(i, pt) tris = vtk.vtkCellArray() for vert in polys: tris.InsertNextCell(len(vert)) for v in vert: tris.InsertCellPoint(v) pd = vtk.vtkPolyData() pd.SetPoints(points) pd.SetPolys(tris) del points, tris whiteimg = vtk.vtkImageData() whiteimg.SetDimensions(shape) if vtk.VTK_MAJOR_VERSION <= 5: whiteimg.SetScalarType(vtk.VTK_UNSIGNED_CHAR) else: info = vtk.vtkInformation() whiteimg.SetPointDataActiveScalarInfo(info, vtk.VTK_UNSIGNED_CHAR, 1) ones = np.ones(np.prod(shape), dtype=np.uint8) whiteimg.GetPointData().SetScalars(numpy_support.numpy_to_vtk(ones)) pdtis = vtk.vtkPolyDataToImageStencil() if vtk.VTK_MAJOR_VERSION <= 5: pdtis.SetInput(pd) else: pdtis.SetInputData(pd) pdtis.SetOutputWholeExtent(whiteimg.GetExtent()) pdtis.Update() imgstenc = vtk.vtkImageStencil() if vtk.VTK_MAJOR_VERSION <= 5: imgstenc.SetInput(whiteimg) imgstenc.SetStencil(pdtis.GetOutput()) else: imgstenc.SetInputData(whiteimg) imgstenc.SetStencilConnection(pdtis.GetOutputPort()) imgstenc.SetBackgroundValue(0) imgstenc.Update() data = numpy_support.vtk_to_numpy( imgstenc.GetOutput().GetPointData().GetScalars()).reshape( shape).transpose(2, 1, 0) del pd, voxverts, whiteimg, pdtis, imgstenc return data
def _polydataToLabelmap(polydata, spacing=1.0, extraMarginToBounds=0, referenceImage=None): binaryLabelmap = vtk.vtkImageData() if referenceImage: origin = referenceImage.GetOrigin() spacing3 = referenceImage.GetSpacing() extent = referenceImage.GetExtent() else: bounds = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] polydata.GetBounds(bounds) bounds[0] -= extraMarginToBounds bounds[2] -= extraMarginToBounds bounds[4] -= extraMarginToBounds bounds[1] += extraMarginToBounds bounds[3] += extraMarginToBounds bounds[5] += extraMarginToBounds spacing3 = np.ones(3) * spacing dim = [0, 0, 0] for i in range(3): # Add 3 to the dimensions to have at least 1 voxel thickness and 1 voxel margin on both sides dim[i] = int( math.ceil( (bounds[i * 2 + 1] - bounds[i * 2]) / spacing3[i])) + 3 # Subtract one spacing to ensure there is a margin origin = [ bounds[0] - spacing3[0], bounds[2] - spacing3[1], bounds[4] - spacing3[2] ] extent = [0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1] binaryLabelmap.SetOrigin(origin) binaryLabelmap.SetSpacing(spacing3) binaryLabelmap.SetExtent(extent) binaryLabelmap.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) binaryLabelmap.GetPointData().GetScalars().Fill(0) pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetInputData(polydata) pol2stenc.SetOutputOrigin(origin) pol2stenc.SetOutputSpacing(spacing3) pol2stenc.SetOutputWholeExtent(binaryLabelmap.GetExtent()) imgstenc = vtk.vtkImageStencil() imgstenc.SetInputData(binaryLabelmap) imgstenc.SetStencilConnection(pol2stenc.GetOutputPort()) imgstenc.ReverseStencilOn() imgstenc.SetBackgroundValue(1) imgstenc.Update() return imgstenc.GetOutput()
def surf_fill_vtk(vertices, polys, mat, shape): import vtk from vtk.util import numpy_support voxverts = nb.affines.apply_affine(np.linalg.inv(mat), vertices) points = vtk.vtkPoints() points.SetNumberOfPoints(len(voxverts)) for i, pt in enumerate(voxverts): points.InsertPoint(i, pt) tris = vtk.vtkCellArray() for vert in polys: tris.InsertNextCell(len(vert)) for v in vert: tris.InsertCellPoint(v) pd = vtk.vtkPolyData() pd.SetPoints(points) pd.SetPolys(tris) del points, tris whiteimg = vtk.vtkImageData() whiteimg.SetDimensions(shape) if vtk.VTK_MAJOR_VERSION <= 5: whiteimg.SetScalarType(vtk.VTK_UNSIGNED_CHAR) else: info = vtk.vtkInformation() whiteimg.SetPointDataActiveScalarInfo(info, vtk.VTK_UNSIGNED_CHAR, 1) ones = np.ones(np.prod(shape), dtype=np.uint8) whiteimg.GetPointData().SetScalars(numpy_support.numpy_to_vtk(ones)) pdtis = vtk.vtkPolyDataToImageStencil() if vtk.VTK_MAJOR_VERSION <= 5: pdtis.SetInput(pd) else: pdtis.SetInputData(pd) pdtis.SetOutputWholeExtent(whiteimg.GetExtent()) pdtis.Update() imgstenc = vtk.vtkImageStencil() if vtk.VTK_MAJOR_VERSION <= 5: imgstenc.SetInput(whiteimg) imgstenc.SetStencil(pdtis.GetOutput()) else: imgstenc.SetInputData(whiteimg) imgstenc.SetStencilConnection(pdtis.GetOutputPort()) imgstenc.SetBackgroundValue(0) imgstenc.Update() data = ( numpy_support.vtk_to_numpy(imgstenc.GetOutput().GetPointData().GetScalars()).reshape(shape).transpose(2, 1, 0) ) del pd, voxverts, whiteimg, pdtis, imgstenc return data
def __init__(self, module_manager): SimpleVTKClassModuleBase.__init__(self, module_manager, vtk.vtkPolyDataToImageStencil(), 'Processing.', ('vtkPolyData', ), ('vtkImageStencilData', ), replaceDoc=True, inputFunctions=None, outputFunctions=None)
def poly_data_to_nii(poly_data, reference_path, result_path): """ TODO: stop reading and writing so much stuff Write to buffer? Bytes? Investigate this """ nii = nib.load(str(reference_path)) image_stencil_array = np.ones(nii.shape, dtype=np.uint8) image_stencil_nii = nib.Nifti1Image(image_stencil_array, nii.get_qform()) with NamedTemporaryFile(suffix='.nii') as f: stencil_path = f.name image_stencil_nii.to_filename(stencil_path) image_stencil_reader = vtk.vtkNIFTIImageReader() image_stencil_reader.SetFileName(stencil_path) image_stencil_reader.Update() image_stencil = image_stencil_reader.GetOutput() xyz_to_ijk = image_stencil_reader.GetQFormMatrix() if xyz_to_ijk is None: import warnings warnings.warn('No qform found. Using sform') xyz_to_ijk = image_stencil_reader.GetSFormMatrix() xyz_to_ijk.Invert() transform = vtk.vtkTransform() transform.SetMatrix(xyz_to_ijk) transform_poly_data = vtk.vtkTransformPolyDataFilter() transform_poly_data.SetTransform(transform) transform_poly_data.SetInputData(poly_data) transform_poly_data.Update() pd_ijk = transform_poly_data.GetOutput() polyDataToImageStencil = vtk.vtkPolyDataToImageStencil() polyDataToImageStencil.SetInputData(pd_ijk) polyDataToImageStencil.SetOutputSpacing(image_stencil.GetSpacing()) polyDataToImageStencil.SetOutputOrigin(image_stencil.GetOrigin()) polyDataToImageStencil.SetOutputWholeExtent(image_stencil.GetExtent()) polyDataToImageStencil.Update() stencil = vtk.vtkImageStencil() stencil.SetInputData(image_stencil) stencil.SetStencilData(polyDataToImageStencil.GetOutput()) stencil.SetBackgroundValue(0) stencil.Update() image_output = stencil.GetOutput() data_object = dsa.WrapDataObject(image_output) array = data_object.PointData['NIFTI'] array = array.reshape(nii.shape, order='F') # C didn't work :) array = check_qfac(nii, array) output_nii = nib.Nifti1Image(array, nii.affine) output_nii.header['sform_code'] = 0 output_nii.header['qform_code'] = 1 output_nii.to_filename(result_path)
def voxelizer(polydata, scale=SCALE, radius=RADIUS): """ volume voxelization not anti-aliased """ # Get selection boundaries. (minX, maxX, minY, maxY, minZ, maxZ) = [int(x * scale) for x in polydata.GetBounds()] # convert tuple of floats to ints # print(" Selection bounds are %s" % str((minX, maxX, minY, maxY, minZ, maxZ))) # dimensions of the resulting image # print(" Dimensions: %s" % str((maxX - minX, maxY - minY, maxZ - minZ))) padd = radius + 6 (minX, maxX, minY, maxY, minZ, maxZ) = (minX - padd, maxX + padd, minY - padd, maxY + padd, minZ - padd, maxZ + padd) ps1 = 1.0 / float( scale) # pixel size for the stencil, make sure it's a float division! ps2 = 1.0 # pixel size for the image ## Convert a surface mesh into an image stencil that can be used to mask an image with vtkImageStencil. polyToStencilFilter = vtk.vtkPolyDataToImageStencil() polyToStencilFilter.SetInputData(polydata) polyToStencilFilter.SetOutputWholeExtent(minX, maxX, minY, maxY, minZ, maxZ) polyToStencilFilter.SetOutputSpacing(ps1, ps1, ps1) polyToStencilFilter.SetOutputOrigin(0.0, 0.0, 0.0) polyToStencilFilter.Update() # Create an empty (3D) image of appropriate size. image = vtk.vtkImageData() image.SetSpacing(ps2, ps2, ps2) image.SetOrigin(0.0, 0.0, 0.0) image.SetExtent(minX, maxX, minY, maxY, minZ, maxZ) image.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) # Mask the empty image with the image stencil. # First All the background to 0 # Needed otherwise introduces noise stencil = vtk.vtkImageStencil() stencil.SetInputData(image) stencil.SetStencilData(polyToStencilFilter.GetOutput()) stencil.ReverseStencilOff() stencil.SetBackgroundValue(0) stencil.Update() # Foreground to 255 stencil2 = vtk.vtkImageStencil() stencil2.SetInputData(stencil.GetOutput()) stencil2.SetStencilData(polyToStencilFilter.GetOutput()) stencil2.ReverseStencilOn() stencil2.SetBackgroundValue(255) stencil2.Update() finishImage = stencil2.GetOutput() print(finishImage.GetNumberOfCells()) return stencil2.GetOutput()
def generateTree_vtk(self): """ | Funkce na vygenerování objemu stromu ze zadaných dat. | Veze pro generování pomocí VTK | !!! funguje špatně -> vstupní data musí být pouze povrchové body, jinak generuje ve výstupních datech dutiny """ # get vtkPolyData tree_data = gen_vtk_tree.process_tree(self.rawdata['Graph']) polyData = gen_vtk_tree.gen_tree(tree_data) polyData.GetBounds() # bounds = polyData.GetBounds() white_image = vtk.vtkImageData() white_image.SetSpacing(self.voxelsize_mm) white_image.SetDimensions(self.shape) white_image.SetExtent( [0, self.shape[0] - 1, 0, self.shape[1] - 1, 0, self.shape[2] - 1]) # origin = [(bounds[0] + self.shape[0])/2, (bounds[1] + self.shape[1])/2, (bounds[2] + self.shape[2])/2] # white_image.SetOrigin(origin) #neni potreba? # white_image.SetScalarTypeToUnsignedChar() white_image.AllocateScalars() # fill the image with foreground voxels: (still black until stecil) inval = 255 outval = 0 count = white_image.GetNumberOfPoints() for i in range(0, count): white_image.GetPointData().GetScalars().SetTuple1(i, inval) pol2stencil = vtk.vtkPolyDataToImageStencil() pol2stencil.SetInput(polyData) # pol2stencil.SetOutputOrigin(origin) # TOHLE BLBNE pol2stencil.SetOutputSpacing(self.voxelsize_mm) pol2stencil.SetOutputWholeExtent(white_image.GetExtent()) pol2stencil.Update() imgstenc = vtk.vtkImageStencil() imgstenc.SetInput(white_image) imgstenc.SetStencil(pol2stencil.GetOutput()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(outval) imgstenc.Update() # VTK -> Numpy vtk_img_data = imgstenc.GetOutput() vtk_data = vtk_img_data.GetPointData().GetScalars() numpy_data = numpy_support.vtk_to_numpy(vtk_data) numpy_data = numpy_data.reshape( self.shape[0], self.shape[1], self.shape[2]) numpy_data = numpy_data.transpose(2, 1, 0) self.data3d = numpy_data
def mesh2Volume(mesh, spacing=(1, 1, 1)): """ Convert a mesh it into a ``Volume`` where the foreground (exterior) voxels value is 1 and the background (interior) voxels value is 0. Internally the ``vtkPolyDataToImageStencil`` class is used. |mesh2volume| |mesh2volume.py|_ """ # https://vtk.org/Wiki/VTK/Examples/Cxx/PolyData/PolyDataToImageData pd = mesh.polydata() whiteImage = vtk.vtkImageData() bounds = pd.GetBounds() whiteImage.SetSpacing(spacing) # compute dimensions dim = [0, 0, 0] for i in [0, 1, 2]: dim[i] = int(np.ceil((bounds[i * 2 + 1] - bounds[i * 2]) / spacing[i])) whiteImage.SetDimensions(dim) whiteImage.SetExtent(0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1) origin = [0, 0, 0] origin[0] = bounds[0] + spacing[0] / 2 origin[1] = bounds[2] + spacing[1] / 2 origin[2] = bounds[4] + spacing[2] / 2 whiteImage.SetOrigin(origin) whiteImage.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) # fill the image with foreground voxels: inval = 255 count = whiteImage.GetNumberOfPoints() for i in range(count): whiteImage.GetPointData().GetScalars().SetTuple1(i, inval) # polygonal data --> image stencil: pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetInputData(pd) pol2stenc.SetOutputOrigin(origin) pol2stenc.SetOutputSpacing(spacing) pol2stenc.SetOutputWholeExtent(whiteImage.GetExtent()) pol2stenc.Update() # cut the corresponding white image and set the background: outval = 0 imgstenc = vtk.vtkImageStencil() imgstenc.SetInputData(whiteImage) imgstenc.SetStencilConnection(pol2stenc.GetOutputPort()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(outval) imgstenc.Update() return Volume(imgstenc.GetOutput())
def processStlToImageData(dicomImageData, m_Origin, stlfilepaths): resultary = None for stlfilepath in stlfilepaths: if not os.path.exists(stlfilepath): continue polyData = readStlFile(stlfilepath) orginlData = dicomImageData spacing = orginlData.GetSpacing() outval = 0 whiteData = vtk.vtkImageData() whiteData.DeepCopy(orginlData) pointdata = whiteData.GetPointData() pointscalars = pointdata.GetScalars() # 通过矩阵计算将whiteData中点的颜色全部设置成白色 sc = vtk_to_numpy(pointscalars) sc = np.where(sc < 255, 255, 255) newscalars = numpy_to_vtk(sc) pointdata.SetScalars(newscalars) whiteData.Modified() pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetInputData(polyData) pol2stenc.SetOutputOrigin(m_Origin) pol2stenc.SetOutputSpacing(spacing) pol2stenc.SetOutputWholeExtent(orginlData.GetExtent()) pol2stenc.Update() imgstenc = vtk.vtkImageStencil() imgstenc.SetInputData(whiteData) imgstenc.SetStencilConnection(pol2stenc.GetOutputPort()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(outval) imgstenc.Update() flip = vtk.vtkImageFlip() flip.SetInputData(imgstenc.GetOutput()) flip.SetFilteredAxes(1) flip.Update() flip2 = vtk.vtkImageFlip() flip2.SetInputData(flip.GetOutput()) flip2.SetFilteredAxes(2) flip2.Update() if resultary is None: resultary = [flip2.GetOutput()] else: resultary.append(flip2.GetOutput()) return resultary
def load_vtp_as_vtk_image( poly_data_fname: str, ref_vtk_img: vtk.vtkImageData, roi_value: int = 255) -> Tuple[np.ndarray, vtk.vtkStructuredPoints]: """ load vtk poly data file as vtk image data :param poly_data_fname: filename :param ref_vtk_img: reference vtk image data :param roi_value: roi value :return: img(npy format), img(vtk format) """ reader = vtk.vtkXMLPolyDataReader() reader.SetFileName(poly_data_fname) reader.Update() whiteImage = vtk.vtkImageData() whiteImage.SetSpacing(ref_vtk_img.GetSpacing()) whiteImage.SetDimensions(ref_vtk_img.GetDimensions()) whiteImage.SetExtent(ref_vtk_img.GetExtent()) whiteImage.SetOrigin(ref_vtk_img.GetOrigin()) whiteImage.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) tmp = np.ones(ref_vtk_img.GetDimensions()[::-1], dtype=np.uint8) * roi_value whiteImage.GetPointData().SetScalars( numpy_support.numpy_to_vtk(tmp.flatten(), deep=True, array_type=vtk.VTK_INT)) pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetInputData(reader.GetOutput()) pol2stenc.SetOutputOrigin(ref_vtk_img.GetOrigin()) pol2stenc.SetOutputSpacing(ref_vtk_img.GetSpacing()) pol2stenc.SetOutputWholeExtent(whiteImage.GetExtent()) pol2stenc.Update() imgstenc = vtk.vtkImageStencil() imgstenc.SetInputData(whiteImage) imgstenc.SetStencilConnection(pol2stenc.GetOutputPort()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(0) imgstenc.Update() vtk_img = imgstenc.GetOutput() img = numpy_support.vtk_to_numpy( vtk_img.GetPointData().GetScalars()).reshape( vtk_img.GetDimensions()[::-1]) return img, vtk_img
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 """ # Create an Image white_image = vtk.vtkImageData() white_image.DeepCopy(im) # extract VOI bounds in dicom space self.VOIbounds = VOI_mesh.GetBounds() print "self.VOIbounds:" print self.VOIbounds self.VOIbounds_expand = [] self.VOIbounds_expand.append( self.VOIbounds[0] ) self.VOIbounds_expand.append( self.VOIbounds[1] ) self.VOIbounds_expand.append( self.VOIbounds[2] ) self.VOIbounds_expand.append( self.VOIbounds[3] ) self.VOIbounds_expand.append( self.VOIbounds[4] ) self.VOIbounds_expand.append( self.VOIbounds[5] ) self.VOIbounds = self.VOIbounds_expand roiStencil = vtk.vtkCubeSource() roiStencil.SetBounds(self.VOIbounds) roiStencil.Update() print "\nGetXLength roiStencil: %d " % roiStencil.GetXLength() print "GetYLength roiStencil: %d " % roiStencil.GetYLength() print "GetZLength roiStencil: %d " % roiStencil.GetZLength() # polygonal data --> image stencil: pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetInput(roiStencil.GetOutput()) pol2stenc.SetOutputOrigin(im.GetOrigin()) pol2stenc.SetOutputSpacing(im.GetSpacing()) pol2stenc.SetOutputWholeExtent(im.GetWholeExtent()) pol2stenc.Update() # cut the corresponding white image and set the background: imgstenc = vtk.vtkImageStencil() imgstenc.SetInput(im) imgstenc.SetStencil(pol2stenc.GetOutput()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(0.0) imgstenc.Update() self.VOIdims = imgstenc.GetOutput().GetDimensions() return imgstenc.GetOutput()
def ensureInSegment(self, image, lesionMesh, pathSegment, nameSegment, image_pos_pat, image_ori_pat): # Proceed to build reference frame for display objects based on DICOM coords [transformed_image, transform_cube] = self.loadDisplay.dicomTransform(image, image_pos_pat, image_ori_pat) dataToStencil = vtk.vtkPolyDataToImageStencil() dataToStencil.SetInput(lesionMesh) dataToStencil.SetOutputOrigin(transformed_image.GetOrigin()) print transformed_image.GetOrigin() dataToStencil.SetOutputSpacing(transformed_image.GetSpacing()) print transformed_image.GetSpacing() dataToStencil.SetOutputWholeExtent(transformed_image.GetExtent()) dataToStencil.Update() stencil = vtk.vtkImageStencil() stencil.SetInput(transformed_image) stencil.SetStencil(dataToStencil.GetOutput()) stencil.ReverseStencilOff() stencil.SetBackgroundValue(0.0) stencil.Update() newSegment = vtk.vtkMetaImageWriter() newSegment.SetFileName(pathSegment+'/'+nameSegment+'.mhd') newSegment.SetInput(stencil.GetOutput()) newSegment.Write() thresh = vtk.vtkImageThreshold() thresh.SetInput(stencil.GetOutput()) thresh.ThresholdByUpper(1) thresh.SetInValue(255) thresh.SetOutValue(0) thresh.Update() contouriso = vtk.vtkMarchingCubes() contouriso.SetInput(thresh.GetOutput()) contouriso.SetValue(0,125) contouriso.ComputeScalarsOn() contouriso.Update() # Recalculate num_voxels and vol_lesion on VOI nvoxels = contouriso.GetOutput().GetNumberOfCells() npoints = contouriso.GetOutput().GetNumberOfPoints() print "Number of points: %d" % npoints print "Number of cells: %d" % nvoxels return contouriso.GetOutput()
def SetPolyDataConnection(self, connection, imageData): if self._polydata is None: self._polydata = GeometryObject(self._name, self._name, connection) else: self._polydata.SetInputConnection(connection) self._polydata.SetWireFrameOn() self._polydata.SetVisibilityOff() # set proper tolerance for converter imageData.UpdateInformation() tolerance = 0.001 * min(imageData.GetSpacing()) # update pipeline connection.GetProducer().Update() polyData = connection.GetProducer().GetOutputDataObject(0) b = polyData.GetBounds() s = imageData.GetSpacing() o = imageData.GetOrigin() extent = [int((b[0] - o[0]) / s[0]), int((b[1] - o[0]) / s[0]) + 1, int((b[2] - o[1]) / s[1]), int((b[3] - o[1]) / s[1]) + 1, int((b[4] - o[2]) / s[2]), int((b[5] - o[2]) / s[2]) + 1] stencil = vtk.vtkPolyDataToImageStencil() stencil.ReleaseDataFlagOn() stencil.SetTolerance(tolerance) stencil.SetInputConnection(connection) stencil.SetOutputSpacing(imageData.GetSpacing()) stencil.SetOutputOrigin(imageData.GetOrigin()) stencil.SetOutputWholeExtent(extent) # stencil.GetOutput().SetWholeExtent(extent) # stencil.GetOutput().SetUpdateExtentToWholeExtent() # stencil.GetOutput().SetExtent(imageData.GetExtent()) # stencil.GetOutput().SetOrigin(imageData.GetOrigin()) # stencil.GetOutput().SetSpacing(imageData.GetSpacing()) try: stencil.GetOutput().Update() except: print sys.exc_type, sys.exc_value return -1 self._stencil_data = stencil.GetOutput() self.ClearPolyData()
def clipVolumeWithPolyData(self, inputVolume, polyData, clipOutsideSurface, fillValue, leftTransformMatrix = None): leftMatrix = vtk.vtkMatrix4x4() leftMatrix.Identity() if leftTransformMatrix: leftMatrix.DeepCopy(leftTransformMatrix) ijkToRas = vtk.vtkMatrix4x4() inputVolume.GetIJKToRASMatrix(ijkToRas) ijkToModel = vtk.vtkMatrix4x4() vtk.vtkMatrix4x4.Multiply4x4(leftMatrix, ijkToRas, ijkToModel) modelToIjkTransform = vtk.vtkTransform() modelToIjkTransform.SetMatrix(ijkToModel) modelToIjkTransform.Inverse() transformModelToIjk = vtk.vtkTransformPolyDataFilter() transformModelToIjk.SetTransform(modelToIjkTransform) transformModelToIjk.SetInputData(polyData) transformModelToIjk.Update() # 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()) 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()) return outputImageData
def pd_to_numpy_vol(pd, spacing=[1.,1.,1.], shape=None, origin=None, foreground_value=255, backgroud_value = 0): if shape is None: bnds = np.array(pd.GetBounds()) shape = np.ceil((bnds[1::2]-bnds[::2])/spacing).astype(int)+15 if origin is None: origin = bnds[::2]+(bnds[1::2]-bnds[::2])/2 #make image extent = np.zeros(6).astype(int) extent[1::2] = np.array(shape)-1 imgvtk = vtk.vtkImageData() imgvtk.SetSpacing(spacing) imgvtk.SetOrigin(origin) imgvtk.SetExtent(extent) imgvtk.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) vtk_data_array = numpy_support.numpy_to_vtk(num_array=np.ones(shape[::-1]).ravel()*backgroud_value, # ndarray contains the fitting result from the points. It is a 3D array deep=True, array_type=vtk.VTK_FLOAT) imgvtk.GetPointData().SetScalars(vtk_data_array) #poly2 stencil pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetInputData(pd) pol2stenc.SetOutputSpacing(spacing) pol2stenc.SetOutputOrigin(origin) pol2stenc.SetOutputWholeExtent(extent) pol2stenc.Update() #stencil to image imgstenc = vtk.vtkImageStencil() imgstenc.SetInputData(imgvtk) imgstenc.SetStencilConnection(pol2stenc.GetOutputPort()) imgstenc.ReverseStencilOn() imgstenc.SetBackgroundValue(foreground_value) imgstenc.Update() ndseg = numpy_support.vtk_to_numpy(imgstenc.GetOutputDataObject(0).GetPointData().GetArray(0)) return ndseg.reshape(shape[::-1])
def triSurface2BinaryMask(v, t, imageShape, voxelOrigin=None, voxelSpacing=None, bg=0): imgDtype = np.int16 if voxelOrigin is None: voxelOrigin = [0.0, 0.0, 0.0] if voxelSpacing is None: voxelSpacing = [1.0, 1.0, 1.0] # make into vtkPolydata gfPoly = vtktools.tri2Polydata(v, t) # create mask vtkImage maskImageArray = np.ones(imageShape, dtype=imgDtype) maskVTKImage = vtktools.array2vtkImage(maskImageArray, imgDtype, flipDim=False) # create stencil from polydata stencilMaker = vtk.vtkPolyDataToImageStencil() stencilMaker.SetInput(gfPoly) stencilMaker.SetOutputOrigin(voxelOrigin) stencilMaker.SetOutputSpacing(voxelSpacing) stencilMaker.SetOutputWholeExtent(maskVTKImage.GetExtent()) stencil = vtk.vtkImageStencil() stencil.SetInput(maskVTKImage) stencil.SetStencil(stencilMaker.GetOutput()) stencil.SetBackgroundValue(bg) stencil.ReverseStencilOff() stencil.Update() maskImageArray = vtktools.vtkImage2Array(stencil.GetOutput(), imgDtype, flipDim=True) return maskImageArray, gfPoly
def mesh2image(pd, spacing, bounds, value=255): """Generates an image in which pixels inside the surface set to value.""" # start with white image dim, origin = bounds_dim_origin(bounds, spacing) whiteimage = image_from_value(spacing, dim, origin, value) # polygonal data to image stencil pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetInput(pd) pol2stenc.SetOutputOrigin(origin) pol2stenc.SetOutputSpacing(spacing) pol2stenc.SetOutputWholeExtent(0, dim[0], 0, dim[1], 0, dim[2]) pol2stenc.Update() # cut the corresponding white image and set the background imgstenc = vtk.vtkImageStencil() imgstenc.SetInput(whiteimage) imgstenc.SetStencil(pol2stenc.GetOutput()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(0) imgstenc.Update() return imgstenc.GetOutput()
def polydata_to_volume(polydata): """ Parameters ---------- polydata : vtkPolyData input polydata Returns ------- (numpy arr, 3-tuple, vtkImageData) (volume, origin, imagedata) """ bounds = polydata.GetBounds() spacing = [1., 1., 1.] origin = [ bounds[0] + spacing[0] / 2, bounds[2] + spacing[1] / 2, bounds[4] + spacing[2] / 2 ] whiteImage = vtk.vtkImageData() whiteImage.SetSpacing(spacing) whiteImage.SetOrigin(origin) dim = np.array([ np.ceil(bounds[1] - bounds[0]) / spacing[0], np.ceil(bounds[3] - bounds[2]) / spacing[1], np.ceil(bounds[5] - bounds[4]) / spacing[2] ], np.int) whiteImage.SetDimensions(dim) whiteImage.SetExtent(0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1) # whiteImage.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) n_pts = whiteImage.GetNumberOfPoints() # t = time.time() # inval = 255 # outval = 0 # for i in range(n_pts): # whiteImage.GetPointData().GetScalars().SetTuple1(i, inval) whiteImage.GetPointData().SetScalars( numpy_support.numpy_to_vtk( 255 * np.ones((n_pts, ), np.uint8), deep=True, array_type=vtk.VTK_UNSIGNED_CHAR)) # deep copy must be true # sys.stderr.write('time 1: %.2f\n' % (time.time() - t) ) # t = time.time() pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetInputData(polydata) pol2stenc.SetOutputOrigin(origin) pol2stenc.SetOutputSpacing(spacing) pol2stenc.SetOutputWholeExtent(whiteImage.GetExtent()) pol2stenc.Update() # sys.stderr.write('time 2: %.2f\n' % (time.time() - t) ) # t = time.time() # cut the corresponding white image and set the background: imgstenc = vtk.vtkImageStencil() imgstenc.SetInputData(whiteImage) imgstenc.SetStencilData(pol2stenc.GetOutput()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(0) imgstenc.Update() # sys.stderr.write('time 3: %.2f\n' % (time.time() - t) ) # t = time.time() im = imgstenc.GetOutput() x, y, z = im.GetDimensions() sc = im.GetPointData().GetScalars() a = numpy_support.vtk_to_numpy(sc) b = a.reshape(z, y, x) b = np.transpose(b, [1, 2, 0]) # sys.stderr.write('time 4: %.2f\n' % (time.time() - t) ) return b, origin, im
def main(): # 3D source sphere sphereSource = vtk.vtkSphereSource() sphereSource.SetPhiResolution(30) sphereSource.SetThetaResolution(30) sphereSource.SetCenter(40, 40, 0) sphereSource.SetRadius(20) # generate circle by cutting the sphere with an implicit plane # (through its center, axis-aligned) circleCutter = vtk.vtkCutter() circleCutter.SetInputConnection(sphereSource.GetOutputPort()) cutPlane = vtk.vtkPlane() cutPlane.SetOrigin(sphereSource.GetCenter()) cutPlane.SetNormal(0, 0, 1) circleCutter.SetCutFunction(cutPlane) stripper = vtk.vtkStripper() stripper.SetInputConnection(circleCutter.GetOutputPort()) # valid circle stripper.Update() # that's our circle circle = stripper.GetOutput() # write circle out polyDataWriter = vtk.vtkXMLPolyDataWriter() polyDataWriter.SetInputData(circle) polyDataWriter.SetFileName("circle.vtp") polyDataWriter.SetCompressorTypeToNone() polyDataWriter.SetDataModeToAscii() polyDataWriter.Write() # prepare the binary image's voxel grid whiteImage = vtk.vtkImageData() bounds = [0] * 6 circle.GetBounds(bounds) spacing = [0] * 3 # desired volume spacing spacing[0] = 0.5 spacing[1] = 0.5 spacing[2] = 0.5 whiteImage.SetSpacing(spacing) # compute dimensions dim = [0] * 3 for i in range(3): dim[i] = int( math.ceil((bounds[i * 2 + 1] - bounds[i * 2]) / spacing[i])) + 1 if dim[i] < 1: dim[i] = 1 whiteImage.SetDimensions(dim) whiteImage.SetExtent(0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1) origin = [0] * 3 # NOTE: I am not sure whether or not we had to add some offset! origin[0] = bounds[0] # + spacing[0] / 2 origin[1] = bounds[2] # + spacing[1] / 2 origin[2] = bounds[4] # + spacing[2] / 2 whiteImage.SetOrigin(origin) whiteImage.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) # fill the image with foreground voxels: inval = 255 outval = 0 count = whiteImage.GetNumberOfPoints() # for (vtkIdType i = 0 i < count ++i) for i in range(count): whiteImage.GetPointData().GetScalars().SetTuple1(i, inval) # sweep polygonal data (this is the important thing with contours!) extruder = vtk.vtkLinearExtrusionFilter() extruder.SetInputData(circle) extruder.SetScaleFactor(1.0) #extruder.SetExtrusionTypeToNormalExtrusion() # not working extruder.SetExtrusionTypeToVectorExtrusion() extruder.SetVector(0, 0, 1) extruder.Update() # polygonal data -. image stencil: pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetTolerance(0) # important if extruder.SetVector(0, 0, 1) !!! pol2stenc.SetInputConnection(extruder.GetOutputPort()) #pol2stenc.SetInputData(circle) pol2stenc.SetOutputOrigin(origin) pol2stenc.SetOutputSpacing(spacing) pol2stenc.SetOutputWholeExtent(whiteImage.GetExtent()) pol2stenc.Update() # cut the corresponding white image and set the background: imgstenc = vtk.vtkImageStencil() imgstenc.SetInputData(whiteImage) imgstenc.SetStencilConnection(pol2stenc.GetOutputPort()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(outval) imgstenc.Update() imageWriter = vtk.vtkMetaImageWriter() imageWriter.SetFileName("labelImage.mhd") imageWriter.SetInputConnection(imgstenc.GetOutputPort()) imageWriter.Write() imageWriter = vtk.vtkPNGWriter() imageWriter.SetFileName("labelImage.png") imageWriter.SetInputConnection(imgstenc.GetOutputPort()) imageWriter.Write()
def mesh_2_mask( inputMesh, outputImage, inputImage=None, superRes=False, spacing=(1.0, 1.0, 1.0) ): """ This program takes in a closed 3D surface, vtkPolyData, and converts it into volume representation (vtkImageData) where the foreground voxels are 1 and the background voxels are 0. Internally vtkPolyDataToImageStencil is utilized. The resultant image is saved to disk in NIFTIimage file format. SimpleITK is used to convert images to standard orientation used for 3D medical images. :param inputMesh: a vtkPolyData file of a 3D surface :param outputImage: output file path for NIFTI image :param inputImage: reference image to get desired spacing, origin, and direction. :param superRes: :param spacing: :return: """ VTK_MAJOR_VERSION = str(vtk.vtkVersion().GetVTKVersion()).split(".")[0] outputImage = str(outputImage) if inputImage: inputImage = str(inputImage) # check output image extension out_ext = outputImage.split(".", 1)[-1] if "nii" in out_ext: writer = vtk.vtkNIFTIImageWriter() else: print( "ERROR: Output must be NIFTI image file. \n\tUnrecognized extension: {0}".format( out_ext ) ) return sys.exit(os.EX_IOERR) if inputImage: image = read_vtk_image(inputImage) else: image = None # read the mesh in pd = read_poly_data(inputMesh) pd = preprocess_mesh(pd) # allocate whiteImage whiteImage = vtk.vtkImageData() # polygonal data -. image stencil: pol2stenc = vtk.vtkPolyDataToImageStencil() if VTK_MAJOR_VERSION <= 5: pol2stenc.SetInput(pd) else: pol2stenc.SetInputData(pd) # get the bounds bounds = pd.GetBounds() if image: spacing = image.GetSpacing() dim = image.GetDimensions() # set VTK direction to RAS vtk_direction = (-1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0) # vtk does not get the correct origin # origin = image.GetOrigin () # use SimpleITK instead image_sitk = sitk.ReadImage(inputImage) origin = image_sitk.GetOrigin() direction = image_sitk.GetDirection() print(direction) print(origin) print(spacing) # superRes slows down the script quite a bit if superRes: """Creates an image with pixels a fourth the size of the original This helps allivaite some of the partial voluming effect that can take place.""" denom = 2 spacing = ( spacing[0] / float(denom), spacing[1] / float(denom), spacing[2] / float(denom), ) dim = (dim[0] * denom, dim[1] * denom, dim[2] * denom) # VTKImages seem to always have the same direction origin = ( origin[0] * vtk_direction[0], origin[1] * vtk_direction[4], origin[2] * vtk_direction[8], ) if direction != vtk_direction: if direction == (1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0): origin = ( origin[0] - spacing[0] * (dim[0] - 1), origin[1] - spacing[1] * (dim[1] - 1), origin[2], ) else: print("ERROR: Not sure how to handle input image direction") sys.exit() print(origin) else: if superRes: spacing = ( spacing[0] / float(2), spacing[1] / float(2), spacing[2] / float(2), ) # compute dimensions dim = [0, 0, 0] for i in range(3): dim[i] = int(math.ceil((bounds[i * 2 + 1] - bounds[i * 2]) / spacing[i])) dim = tuple(dim) # get origin origin = [0, 0, 0] origin[0] = bounds[0] + spacing[0] / float(2) origin[1] = bounds[2] + spacing[1] / float(2) origin[2] = bounds[4] + spacing[2] / float(2) origin = tuple(origin) whiteImage.SetSpacing(spacing) whiteImage.SetOrigin(origin) pol2stenc.SetOutputOrigin(origin) pol2stenc.SetOutputSpacing(spacing) # set dimensions whiteImage.SetDimensions(dim) whiteImage.SetExtent(0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1) if VTK_MAJOR_VERSION <= 5: whiteImage.SetScalarTypeToUnsignedChar() whiteImage.AllocateScalars() else: whiteImage.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) # fill the image with foreground voxels: inval = 1 outval = 0 count = whiteImage.GetNumberOfPoints() for i in range(count): whiteImage.GetPointData().GetScalars().SetTuple1(i, inval) # update pol2stenc pol2stenc.SetOutputWholeExtent(whiteImage.GetExtent()) pol2stenc.Update() # cut the corresponding white image and set the background: imgstenc = vtk.vtkImageStencil() if VTK_MAJOR_VERSION <= 5: imgstenc.SetInput(whiteImage) imgstenc.SetStencil(pol2stenc.GetOutput()) else: imgstenc.SetInputData(whiteImage) imgstenc.SetStencilConnection(pol2stenc.GetOutputPort()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(outval) imgstenc.Update() # write image to file writer.SetFileName(outputImage) if inputImage != None and direction != vtk_direction: flipFilter = vtk.vtkImageFlip() flipFilter.SetFilteredAxis(1) # flip y axis flipFilter.SetInputData(imgstenc.GetOutput()) flipFilter.SetFlipAboutOrigin(1) flipFilter.Update() flipFilter2 = vtk.vtkImageFlip() flipFilter2.SetFilteredAxis(0) # flip x axis flipFilter2.SetInputData(flipFilter.GetOutput()) flipFilter2.SetFlipAboutOrigin(1) flipFilter2.Update() if VTK_MAJOR_VERSION <= 5: writer.SetInput(flipFilter2.GetOutput()) else: writer.SetInputData(flipFilter2.GetOutput()) writer.Write() itk_image = sitk.ReadImage(inputImage) out_image = sitk.ReadImage(outputImage) out_image.SetDirection(itk_image.GetDirection()) out_image.SetOrigin(itk_image.GetOrigin()) sitk.WriteImage(out_image, outputImage) else: if VTK_MAJOR_VERSION <= 5: writer.SetInput(imgstenc.GetOutput()) else: writer.SetInputData(imgstenc.GetOutput()) writer.Write() return os.path.abspath(outputImage)
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 _poly2img(self, ind): """ Helper function called by **deformableRegistration()** that generates images from polygonal surfaces in reference/deformed pairs. The voxel dimension of these images is determined by the value for **Precision** in **deformableSettings**. Parameters ---------- ind : int The list index for the current object pair being analyzed. Returns ------- (Reference Image, Deformed Image, Tranformed Reference Surface) """ dim = int(np.ceil(old_div(1.0, self.deformableSettings['Precision']))) + 10 rpoly = vtk.vtkPolyData() rpoly.DeepCopy(self.rsurfs[ind]) dpoly = self.dsurfs[ind] if self.rigidInitial: rot = vtk.vtkTransformPolyDataFilter() rot.SetInputData(rpoly) rot.SetTransform(self.rigidTransforms[ind]) rot.Update() rpoly = rot.GetOutput() rbounds = np.zeros(6, np.float32) dbounds = np.copy(rbounds) rpoly.GetBounds(rbounds) dpoly.GetBounds(dbounds) spacing = np.zeros(3, np.float32) for i in range(3): rspan = rbounds[2 * i + 1] - rbounds[2 * i] dspan = dbounds[2 * i + 1] - dbounds[2 * i] spacing[i] = (np.max([rspan, dspan]) * self.deformableSettings['Precision']) imgs = [] half = old_div(float(dim), 2.0) for i in range(2): arr = np.ones((dim, dim, dim), np.uint8) arr2img = vti.vtkImageImportFromArray() arr2img.SetDataSpacing(spacing) arr2img.SetDataExtent((0, dim - 1, 0, dim - 1, 0, dim - 1)) arr2img.SetArray(arr) arr2img.Update() if i == 0: rimg = arr2img.GetOutput() rimg.SetOrigin((np.mean(rbounds[0:2]) - half * spacing[0] + old_div(spacing[0], 2), np.mean(rbounds[2:4]) - half * spacing[1] + old_div(spacing[1], 2), np.mean(rbounds[4:]) - half * spacing[2] + old_div(spacing[2], 2))) else: dimg = arr2img.GetOutput() dimg.SetOrigin((np.mean(dbounds[0:2]) - half * spacing[0] + old_div(spacing[0], 2), np.mean(dbounds[2:4]) - half * spacing[1] + old_div(spacing[1], 2), np.mean(dbounds[4:]) - half * spacing[2] + old_div(spacing[2], 2))) imgs = [] for (pd, img) in [(rpoly, rimg), (dpoly, dimg)]: pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetInputData(pd) pol2stenc.SetOutputOrigin(img.GetOrigin()) pol2stenc.SetOutputSpacing(img.GetSpacing()) pol2stenc.SetOutputWholeExtent(img.GetExtent()) pol2stenc.SetTolerance(0.0001) pol2stenc.Update() imgstenc = vtk.vtkImageStencil() imgstenc.SetInputData(img) imgstenc.SetStencilConnection(pol2stenc.GetOutputPort()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(0) imgstenc.Update() arr = vtk_to_numpy(imgstenc.GetOutput().GetPointData().GetArray(0)) arr = arr.reshape(dim, dim, dim) itk_img = sitk.GetImageFromArray(arr) itk_img.SetSpacing(img.GetSpacing()) itk_img.SetOrigin(img.GetOrigin()) imgs.append(itk_img) return (imgs[0], imgs[1], rpoly)
def Execute(self): if self.Surface == None: self.PrintError('Error: No Input Surface.') if self.InsideValue > 255: self.PrintError('Error: Cannot assign InsideValue of image to value greater than 255') # Step 1: Convert the input surface into an image mask of unsigned char type and spacing = PolyDataToImageDataSpacing # Where voxels lying inside the surface are set to 255 and voxels outside the image are set to value 0. # since we are creating a new image container from nothing, calculate the origin, extent, and dimensions for the # vtkImageDataObject from the surface parameters. bounds = self.Surface.GetBounds() dim = [] # list of size: 3, type: int for i in range(3): dim.append(int(math.ceil((bounds[i * 2 + 1] - bounds[i * 2]) / self.PolyDataToImageDataSpacing[i]))) origin = [bounds[0] + self.PolyDataToImageDataSpacing[0] / 2, bounds[2] + self.PolyDataToImageDataSpacing[1] / 2, bounds[4] + self.PolyDataToImageDataSpacing[2] / 2] extent = [0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1] whiteImage = vtk.vtkImageData() whiteImage.SetSpacing(self.PolyDataToImageDataSpacing[0], self.PolyDataToImageDataSpacing[1], self.PolyDataToImageDataSpacing[2]) whiteImage.SetDimensions(dim[0], dim[1], dim[2]) whiteImage.SetExtent(extent[0], extent[1], extent[2], extent[3], extent[4], extent[5]) whiteImage.SetOrigin(origin[0], origin[1], origin[2]) whiteImage.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) # initially set all values of the image to a value self.InsideValue npFillImagePoints = np.zeros(whiteImage.GetNumberOfPoints(), dtype=np.uint8) npFillImagePoints[:] = self.InsideValue # it is much faster to use the vtk data set adaptor functions to fill the point data tupples that it is to # loop over each index and set values individually. pointDataArray = dsa.numpyTovtkDataArray(npFillImagePoints, name='ImageScalars', array_type=vtk.VTK_UNSIGNED_CHAR) whiteImage.GetPointData().SetActiveScalars('ImageScalars') whiteImage.GetPointData().SetScalars(pointDataArray) # The vtkPolyDataToImageStencil class will convert polydata into an image stencil, masking an image. # The polydata can either be a closed surface mesh or a series of polyline contours (one contour per slice). polyDataToImageStencilFilter = vtk.vtkPolyDataToImageStencil() polyDataToImageStencilFilter.SetInputData(self.Surface) polyDataToImageStencilFilter.SetOutputSpacing(self.PolyDataToImageDataSpacing[0], self.PolyDataToImageDataSpacing[1], self.PolyDataToImageDataSpacing[2]) polyDataToImageStencilFilter.SetOutputOrigin(origin[0], origin[1], origin[2]) polyDataToImageStencilFilter.Update() # vtkImageStencil combines to images together by using a "cookie-cutter" operation. imageStencil = vtk.vtkImageStencil() imageStencil.SetInputData(whiteImage) imageStencil.SetStencilConnection(polyDataToImageStencilFilter.GetOutputPort()) imageStencil.ReverseStencilOff() imageStencil.SetBackgroundValue(self.OutsideValue) imageStencil.Update() self.Image = imageStencil.GetOutput()
imageBounds = image.GetBounds() #Debugging #Log ("Read %d points from test AIM file." % image.GetNumberOfPoints()) #imageBoundstest = image.GetBounds() #Log ("Image bounds:", ("%.4f" + " %.4f"*5) % imageBoundstest) cortMask = vtk.vtkPolyDataReader() cortMask.SetFileName(inputCortMaskFile) cortMask.Update() #trabMask = vtk.vtkPolyDataReader() #trabMask.SetFileName(trabMaskFile) #trabMask.Update() stencilData = vtk.vtkPolyDataToImageStencil() stencilData.SetInput(cortMask.GetOutput()) stencilData.SetInformationInput(image) stencil = vtk.vtkImageStencil() stencil.SetInput(image) stencil.SetBackgroundValue(-500) stencil.SetStencil(stencilData.GetOutput()) stencil.Update() imagetest = stencil.GetOutput() imageBoundstest = imagetest.GetBounds() #Debugging #Log ("Read %d points from test AIM file." % imagetest.GetNumberOfPoints()) #imageBoundstest = imagetest.GetBounds()
# sweep polygonal data (this is the important thing with contours!) extruder = vtk.vtkLinearExtrusionFilter() if vtk.VTK_MAJOR_VERSION <= 5: extruder.SetInput(circle) else: extruder.SetInputData(circle) extruder.SetScaleFactor(1.) extruder.SetExtrusionTypeToNormalExtrusion() extruder.SetVector(0, 0, 1) extruder.Update() # polygonal data -. image stencil: pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetTolerance(0) # important if extruder.SetVector(0, 0, 1) !!! pol2stenc.SetInputConnection(extruder.GetOutputPort()) pol2stenc.SetOutputOrigin(origin) pol2stenc.SetOutputSpacing(spacing) pol2stenc.SetOutputWholeExtent(whiteImage.GetExtent()) pol2stenc.Update() # cut the corresponding white image and set the background: imgstenc = vtk.vtkImageStencil() if vtk.VTK_MAJOR_VERSION <= 5: imgstenc.SetInput(whiteImage) imgstenc.SetStencil(pol2stenc.GetOutput()) else: imgstenc.SetInputData(whiteImage) imgstenc.SetStencilConnection(pol2stenc.GetOutputPort())
def _buildPipeline(self): """Build underlying pipeline and configure rest of pipeline-dependent UI. """ # add the renderer self._renderer = vtk.vtkRenderer() self._renderer.SetBackground(0.5, 0.5, 0.5) self._viewFrame.rwi.GetRenderWindow().AddRenderer(self._renderer) self._histogram = vtkdevide.vtkImageHistogram2D() # make sure the user can't do anything entirely stupid istyle = vtk.vtkInteractorStyleImage() self._viewFrame.rwi.SetInteractorStyle(istyle) # we'll use this to keep track of our ImagePlaneWidget self._ipw = None self._overlayipw = None self._scalarBarWidget = None # self._appendPD = vtk.vtkAppendPolyData() self._extrude = vtk.vtkLinearExtrusionFilter() self._extrude.SetInput(self._appendPD.GetOutput()) self._extrude.SetScaleFactor(1) self._extrude.SetExtrusionTypeToNormalExtrusion() self._extrude.SetVector(0, 0, 1) self._pdToImageStencil = vtk.vtkPolyDataToImageStencil() self._pdToImageStencil.SetInput(self._extrude.GetOutput()) # stupid trick to make image with all ones, but as large as its # input self._allOnes = vtk.vtkImageThreshold() self._allOnes.ThresholdByLower(0.0) self._allOnes.ThresholdByUpper(0.0) self._allOnes.SetInValue(1.0) self._allOnes.SetOutValue(1.0) self._allOnes.SetInput(self._histogram.GetOutput()) self._stencil = vtk.vtkImageStencil() self._stencil.SetInput(self._allOnes.GetOutput()) # self._stencil.SetStencil(self._pdToImageStencil.GetOutput()) self._stencil.ReverseStencilOff() self._stencil.SetBackgroundValue(0) self._lookupAppend = vtk.vtkImageAppendComponents() self._lookup = vtkdevide.vtkHistogramLookupTable() self._lookup.SetInput1(self._lookupAppend.GetOutput()) self._lookup.SetInput2(self._stencil.GetOutput()) module_utils.create_standard_object_introspection( self, self._viewFrame, self._viewFrame.viewFramePanel, {"Module (self)": self, "vtkHistogram2D": self._histogram, "vtkRenderer": self._renderer}, self._renderer.GetRenderWindow(), ) # add the ECASH buttons module_utils.create_eoca_buttons(self, self._viewFrame, self._viewFrame.viewFramePanel)
def __vtu2mhd__(vtp, spacing=[1.0, 1.0, 1.0]): from math import ceil bounds = [0.0] * 6 vtp.GetBounds(bounds) #print bounds whiteImage = vtk.vtkImageData() whiteImage.SetSpacing(spacing) ## compute dimensions dim = [0.0, 0.0, 0.0] for i in range(3): #print (bounds[i * 2 + 1] - bounds[i * 2])/ spacing[i] dim[i] = ceil((bounds[i * 2 + 1] - bounds[i * 2]) / spacing[i]) print dim whiteImage.SetDimensions(dim) whiteImage.SetExtent(0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1) origin = [0.0, 0.0, 0.0] origin[0] = bounds[0] + spacing[0] / 2 origin[1] = bounds[2] + spacing[1] / 2 origin[2] = bounds[4] + spacing[2] / 2 whiteImage.SetOrigin(origin) if vtk.VTK_MAJOR_VERSION <= 5: whiteImage.SetScalarTypeToUnsignedChar() whiteImage.AllocateScalars() else: whiteImage.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) ## Fill the image with foreground voxels: inval = 255 outval = 0 count = whiteImage.GetNumberOfPoints() for i in range(count): whiteImage.GetPointData().GetScalars().SetTuple1(i, inval) ## Polygonal data --> image stencil: pol2stenc = vtk.vtkPolyDataToImageStencil() if vtk.VTK_MAJOR_VERSION <= 5: pol2stenc.SetInput(vtp) else: pol2stenc.SetInputData(vtp) pol2stenc.SetOutputOrigin(origin) pol2stenc.SetOutputSpacing(spacing) pol2stenc.SetOutputWholeExtent(whiteImage.GetExtent()) pol2stenc.Update() ## Cut the corresponding white image and set the background: imgstenc = vtk.vtkImageStencil() if vtk.VTK_MAJOR_VERSION <= 5: imgstenc.SetInput(whiteImage) imgstenc.SetStencil(pol2stenc.GetOutput()) else: imgstenc.SetInputData(whiteImage) imgstenc.SetStencilConnection(pol2stenc.GetOutputPort()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(outval) imgstenc.Update() return pol2stenc
def make_patterned_polydata( inputContours, fillareastyle=None, fillareaindex=None, fillareacolors=None, fillareaopacity=None, size=None ): if inputContours is None or fillareastyle == "solid": return None if inputContours.GetNumberOfCells() == 0: return None if fillareaindex is None: fillareaindex = 1 if fillareaopacity is None: fillareaopacity = 100 num_pixels = num_pixels_for_size(size) # Create the plane that will be textured with the pattern # The bounds of the plane match the bounds of the input polydata bounds = inputContours.GetBounds() patternPlane = vtk.vtkPlaneSource() patternPlane.SetOrigin(bounds[0], bounds[2], 0.0) patternPlane.SetPoint1(bounds[0], bounds[3], 0.0) patternPlane.SetPoint2(bounds[1], bounds[2], 0.0) # Generate texture coordinates for the plane textureMap = vtk.vtkTextureMapToPlane() textureMap.SetInputConnection(patternPlane.GetOutputPort()) # Create the pattern image of the size of the input polydata # and type defined by fillareaindex xBounds = bounds[1] - bounds[0] yBounds = bounds[3] - bounds[2] if xBounds <= 1 and yBounds <= 1 and size is not None: xBounds *= size[0] yBounds *= size[1] xres, yres = int(xBounds), int(yBounds) xres = int(4.0 * xBounds) yres = int(4.0 * yBounds) # Handle the case when the bounds are less than 1 in physical dimensions patternImage = create_pattern(xres, yres, num_pixels, fillareastyle, fillareaindex, fillareacolors, fillareaopacity) if patternImage is None: return None # Extrude the contour since vtkPolyDataToImageStencil # requires 3D polydata extruder = vtk.vtkLinearExtrusionFilter() extruder.SetInputData(inputContours) extruder.SetScaleFactor(1.0) extruder.SetVector(0, 0, 1) extruder.SetExtrusionTypeToNormalExtrusion() # Create a binary image mask from the extruded polydata pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetTolerance(0) pol2stenc.SetInputConnection(extruder.GetOutputPort()) pol2stenc.SetOutputOrigin(bounds[0], bounds[2], 0.0) pol2stenc.SetOutputSpacing((bounds[1] - bounds[0]) / xres, (bounds[3] - bounds[2]) / yres, 0.0) pol2stenc.SetOutputWholeExtent(patternImage.GetExtent()) # Stencil out the fillarea from the pattern image stenc = vtk.vtkImageStencil() stenc.SetInputData(patternImage) stenc.SetStencilConnection(pol2stenc.GetOutputPort()) stenc.ReverseStencilOff() stenc.SetBackgroundColor(0, 0, 0, 0) stenc.Update() patternImage = stenc.GetOutput() # Create the texture using the stenciled pattern patternTexture = vtk.vtkTexture() patternTexture.SetInputData(patternImage) patternTexture.InterpolateOn() patternTexture.RepeatOn() mapper = vtk.vtkPolyDataMapper() mapper.SetInputConnection(textureMap.GetOutputPort()) actor = vtk.vtkActor() actor.SetMapper(mapper) actor.SetTexture(patternTexture) return actor
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()
def smoothMultipleSegments(self): import vtkSegmentationCorePython as vtkSegmentationCore # Generate merged labelmap of all visible segments segmentationNode = self.scriptedEffect.parameterSetNode().GetSegmentationNode() visibleSegmentIds = vtk.vtkStringArray() segmentationNode.GetDisplayNode().GetVisibleSegmentIDs(visibleSegmentIds) if visibleSegmentIds.GetNumberOfValues() == 0: logging.info("Smoothing operation skipped: there are no visible segments") return mergedImage = vtkSegmentationCore.vtkOrientedImageData() if not segmentationNode.GenerateMergedLabelmapForAllSegments(mergedImage, vtkSegmentationCore.vtkSegmentation.EXTENT_UNION_OF_SEGMENTS_PADDED, None, visibleSegmentIds): logging.error('Failed to apply smoothing: cannot get list of visible segments') return segmentLabelValues = [] # list of [segmentId, labelValue] for i in range(visibleSegmentIds.GetNumberOfValues()): segmentId = visibleSegmentIds.GetValue(i) segmentLabelValues.append([segmentId, i+1]) # Perform smoothing in voxel space ici = vtk.vtkImageChangeInformation() ici.SetInputData(mergedImage) ici.SetOutputSpacing(1, 1, 1) ici.SetOutputOrigin(0, 0, 0) # Convert labelmap to combined polydata # vtkDiscreteFlyingEdges3D cannot be used here, as in the output of that filter, # each labeled region is completely disconnected from neighboring regions, and # for joint smoothing it is essential for the points to move together. convertToPolyData = vtk.vtkDiscreteMarchingCubes() convertToPolyData.SetInputConnection(ici.GetOutputPort()) convertToPolyData.SetNumberOfContours(len(segmentLabelValues)) contourIndex = 0 for segmentId, labelValue in segmentLabelValues: convertToPolyData.SetValue(contourIndex, labelValue) contourIndex += 1 # Low-pass filtering using Taubin's method smoothingFactor = self.scriptedEffect.doubleParameter("JointTaubinSmoothingFactor") smoothingIterations = 100 # according to VTK documentation 10-20 iterations could be enough but we use a higher value to reduce chance of shrinking passBand = pow(10.0, -4.0*smoothingFactor) # gives a nice range of 1-0.0001 from a user input of 0-1 smoother = vtk.vtkWindowedSincPolyDataFilter() smoother.SetInputConnection(convertToPolyData.GetOutputPort()) smoother.SetNumberOfIterations(smoothingIterations) smoother.BoundarySmoothingOff() smoother.FeatureEdgeSmoothingOff() smoother.SetFeatureAngle(90.0) smoother.SetPassBand(passBand) smoother.NonManifoldSmoothingOn() smoother.NormalizeCoordinatesOn() # Extract a label threshold = vtk.vtkThreshold() threshold.SetInputConnection(smoother.GetOutputPort()) # Convert to polydata geometryFilter = vtk.vtkGeometryFilter() geometryFilter.SetInputConnection(threshold.GetOutputPort()) # Convert polydata to stencil polyDataToImageStencil = vtk.vtkPolyDataToImageStencil() polyDataToImageStencil.SetInputConnection(geometryFilter.GetOutputPort()) polyDataToImageStencil.SetOutputSpacing(1,1,1) polyDataToImageStencil.SetOutputOrigin(0,0,0) polyDataToImageStencil.SetOutputWholeExtent(mergedImage.GetExtent()) # Convert stencil to image stencil = vtk.vtkImageStencil() emptyBinaryLabelMap = vtk.vtkImageData() emptyBinaryLabelMap.SetExtent(mergedImage.GetExtent()) emptyBinaryLabelMap.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) vtkSegmentationCore.vtkOrientedImageDataResample.FillImage(emptyBinaryLabelMap, 0) stencil.SetInputData(emptyBinaryLabelMap) stencil.SetStencilConnection(polyDataToImageStencil.GetOutputPort()) stencil.ReverseStencilOn() stencil.SetBackgroundValue(1) # General foreground value is 1 (background value because of reverse stencil) imageToWorldMatrix = vtk.vtkMatrix4x4() mergedImage.GetImageToWorldMatrix(imageToWorldMatrix) for segmentId, labelValue in segmentLabelValues: threshold.ThresholdBetween(labelValue, labelValue) stencil.Update() smoothedBinaryLabelMap = vtkSegmentationCore.vtkOrientedImageData() smoothedBinaryLabelMap.ShallowCopy(stencil.GetOutput()) smoothedBinaryLabelMap.SetImageToWorldMatrix(imageToWorldMatrix) # Write results to segments directly, bypassing masking slicer.vtkSlicerSegmentationsModuleLogic.SetBinaryLabelmapToSegment(smoothedBinaryLabelMap, segmentationNode, segmentId, slicer.vtkSlicerSegmentationsModuleLogic.MODE_REPLACE, smoothedBinaryLabelMap.GetExtent())
# A script to test the stencil filter with a polydata stencil. # Image pipeline 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") sphere = vtk.vtkSphereSource() sphere.SetPhiResolution(12) sphere.SetThetaResolution(12) sphere.SetCenter(102,102,0) sphere.SetRadius(60) triangle = vtk.vtkTriangleFilter() triangle.SetInputConnection(sphere.GetOutputPort()) stripper = vtk.vtkStripper() stripper.SetInputConnection(triangle.GetOutputPort()) dataToStencil = vtk.vtkPolyDataToImageStencil() dataToStencil.SetInputConnection(stripper.GetOutputPort()) dataToStencil.SetOutputSpacing(0.8,0.8,1.5) dataToStencil.SetOutputOrigin(0.0,0.0,0.0) stencil = vtk.vtkImageStencil() stencil.SetInputConnection(reader.GetOutputPort()) stencil.SetStencilConnection(dataToStencil.GetOutputPort()) stencil.ReverseStencilOn() stencil.SetBackgroundValue(500) # test again with a contour reader2 = vtk.vtkPNGReader() reader2.SetDataSpacing(0.8,0.8,1.5) reader2.SetDataOrigin(0.0,0.0,0.0) reader2.SetFileName("" + str(VTK_DATA_ROOT) + "/Data/fullhead15.png") plane = vtk.vtkPlane() plane.SetOrigin(0,0,0)
def compute_topomesh_image(topomesh, img): image_start_time = time() print "<-- Computing topomesh image" polydata_img = np.ones_like(img) for c in list(topomesh.wisps(3)): if len(list(topomesh.borders(3,c))) > 0: polydata_start_time = time() sub_topomesh = cell_topomesh(topomesh,cells=[c]) start_time = time() bounding_box = np.array([[0,polydata_img.shape[0]],[0,polydata_img.shape[1]],[0,polydata_img.shape[2]]]) bounding_box[:,0] = np.floor(sub_topomesh.wisp_property('barycenter',0).values().min(axis=0)/np.array(img.resolution)).astype(int)-1 bounding_box[:,0] = np.maximum(bounding_box[:,0],0) bounding_box[:,1] = np.ceil(sub_topomesh.wisp_property('barycenter',0).values().max(axis=0)/np.array(img.resolution)).astype(int)+1 bounding_box[:,1] = np.minimum(bounding_box[:,1],np.array(img.shape)-1) sub_polydata_img = polydata_img[bounding_box[0,0]:bounding_box[0,1],bounding_box[1,0]:bounding_box[1,1],bounding_box[2,0]:bounding_box[2,1]] #world.add(sub_polydata_img,"topomesh_image",colormap='glasbey',alphamap='constant',bg_id=1,intensity_range=(0,1)) reader = matrix_to_image_reader('sub_polydata_image',sub_polydata_img,sub_polydata_img.dtype) #reader = matrix_to_image_reader('polydata_image',polydata_img,polydata_img.dtype) end_time = time() print " --> Extracting cell sub-image [",end_time-start_time,"s]" start_time = time() topomesh_center = bounding_box[:,0]*np.array(img.resolution) positions = sub_topomesh.wisp_property('barycenter',0) polydata = vtk.vtkPolyData() vtk_points = vtk.vtkPoints() vtk_triangles = vtk.vtkCellArray() for t in sub_topomesh.wisps(2): triangle_points = [] for v in sub_topomesh.borders(2,t,2): p = vtk_points.InsertNextPoint(positions[v]-topomesh_center) triangle_points.append(p) triangle_points = array_dict(triangle_points,list(sub_topomesh.borders(2,t,2))) poly = vtk_triangles.InsertNextCell(3) for v in sub_topomesh.borders(2,t,2): vtk_triangles.InsertCellPoint(triangle_points[v]) polydata.SetPoints(vtk_points) polydata.SetPolys(vtk_triangles) end_time = time() print " --> Creating VTK PolyData [",end_time-start_time,"s]" start_time = time() pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetTolerance(0) pol2stenc.SetOutputOrigin((0,0,0)) #pol2stenc.SetOutputOrigin(tuple(-bounding_box[:,0])) pol2stenc.SetOutputSpacing(img.resolution) SetInput(pol2stenc,polydata) pol2stenc.Update() end_time = time() print " --> Cell ",c," polydata stencil [",end_time-start_time,"s]" start_time = time() imgstenc = vtk.vtkImageStencil() if vtk.VTK_MAJOR_VERSION <= 5: imgstenc.SetInput(reader.GetOutput()) imgstenc.SetStencil(pol2stenc.GetOutput()) else: imgstenc.SetInputData(reader.GetOutput()) imgstenc.SetStencilConnection(pol2stenc.GetOutputPort()) imgstenc.ReverseStencilOn() imgstenc.SetBackgroundValue(c) imgstenc.Update() end_time = time() print " --> Cell ",c," image stencil [",end_time-start_time,"s]" start_time = time() dim = tuple((bounding_box[:,1]-bounding_box[:,0])[::-1]) array = np.ones(dim, img.dtype) export = vtk.vtkImageExport() export.SetInputConnection(imgstenc.GetOutputPort()) export.Export(array) end_time = time() print " --> Exporting image [",end_time-start_time,"s]" start_time = time() array = np.transpose(array,(2,1,0)) polydata_img[bounding_box[0,0]:bounding_box[0,1],bounding_box[1,0]:bounding_box[1,1],bounding_box[2,0]:bounding_box[2,1]] = array end_time = time() print " --> Inserting cell sub-image [",end_time-start_time,"s]" polydata_end_time = time() print "--> Inserting topomesh cell ",c," [",polydata_end_time-polydata_start_time,"s]" image_end_time = time() print "<-- Computing topomesh image [",image_end_time-image_start_time,"s]" return polydata_img
sphere.SetPhiResolution(12) sphere.SetThetaResolution(12) sphere.SetCenter(102, 102, 0) sphere.SetRadius(60) triangle = vtk.vtkTriangleFilter() if vtk.VTK_MAJOR_VERSION <= 5: triangle.SetInput(sphere.GetOutput()) else: triangle.SetInputConnection(sphere.GetOutputPort()) stripper = vtk.vtkStripper() if vtk.VTK_MAJOR_VERSION <= 5: stripper.SetInput(triangle.GetOutput()) else: stripper.SetInputConnection(triangle.GetOutputPort()) dataToStencil = vtk.vtkPolyDataToImageStencil() if vtk.VTK_MAJOR_VERSION <= 5: dataToStencil.SetInput(stripper.GetOutput()) else: dataToStencil.SetInputConnection(stripper.GetOutputPort()) dataToStencil.SetOutputSpacing(0.8, 0.8, 1.5) dataToStencil.SetOutputOrigin(0.0, 0.0, 0.0) stencil = vtk.vtkImageStencil() if vtk.VTK_MAJOR_VERSION <= 5: stencil.SetInput(reader.GetOutput()) stencil.SetStencil(dataToStencil.GetOutput()) else: stencil.SetInputConnection(reader.GetOutputPort()) stencil.SetStencilConnection(dataToStencil.GetOutputPort()) stencil.ReverseStencilOn()
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 clipVolumeWithModel(self, inputVolume, clippingModel, clipOutsideSurface, fillValue, 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()) 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()) return True
def opImplement(self): import vtkMeasure,math; measure = vtkMeasure.measure_factory(self.data); real_width,real_depth,real_height = measure.getPointSize(); scaler = 1.1; width,depth,height = [ real_width * scaler,real_depth* scaler , real_height* scaler ]; xMin,xMax = measure.xSize yMin,yMax = measure.ySize zMin,zMax = measure.zSize #Basic image blankImage = vtk.vtkImageData(); #The size of voxel spacing = [width/VOLUME_SETP,height/VOLUME_SETP,depth/VOLUME_SETP]; #spacing = [0.1,0.1,0.1]; self.resoulation = spacing; #How many voxel on each axis extent = [xMin,xMax,yMin,yMax,zMin,zMax]; extent[0] = 0 extent[1] = int(math.ceil(width/spacing[0] -1 ) ) extent[2] = 0 extent[3] = int(math.ceil(height/spacing[1] -1 ) ) extent[4] = 0 extent[5] = int(math.ceil(depth/spacing[2] -1)) #Where start from first voxel origin = list(self.data.GetCenter()); origin[0] = xMin+spacing[0]/2; origin[1] = yMin+spacing[1]/2; origin[2] = zMin+spacing[2]/2; blankImage.SetSpacing(*spacing) blankImage.SetOrigin(*origin); blankImage.SetExtent(*extent); blankImage.AllocateScalars(vtk.VTK_UNSIGNED_CHAR,1); xd,yd,zd = blankImage.GetDimensions(); #Fill in inside val for x in range(0,xd): for y in range(0,yd): for z in range(0,zd): blankImage.SetScalarComponentFromFloat(x,y,z,0,IMAGEOUT); #PolyData poly2Stenc = vtk.vtkPolyDataToImageStencil(); poly2Stenc.SetInputData(self.data); poly2Stenc.SetInformationInput(blankImage) poly2Stenc.SetTolerance(80.0) poly2Stenc.SetOutputSpacing(spacing) poly2Stenc.SetOutputOrigin(origin) poly2Stenc.Update(); #Mashup polydata and basic iamge imageStenc = vtk.vtkImageStencil(); imageStenc.SetInputData(blankImage); imageStenc.SetStencilConnection(poly2Stenc.GetOutputPort()); imageStenc.ReverseStencilOn(); #Outside value imageStenc.SetBackgroundValue(IMAGEIN); imageStenc.Update(); combined_image = imageStenc.GetOutput() self.preCommand.operation.reset(); return combined_image;
def smoothMultipleSegments(self, maskImage=None, maskExtent=None): import vtkSegmentationCorePython as vtkSegmentationCore self.showStatusMessage(f'Joint smoothing ...') # Generate merged labelmap of all visible segments segmentationNode = self.scriptedEffect.parameterSetNode( ).GetSegmentationNode() visibleSegmentIds = vtk.vtkStringArray() segmentationNode.GetDisplayNode().GetVisibleSegmentIDs( visibleSegmentIds) if visibleSegmentIds.GetNumberOfValues() == 0: logging.info( "Smoothing operation skipped: there are no visible segments") return mergedImage = slicer.vtkOrientedImageData() if not segmentationNode.GenerateMergedLabelmapForAllSegments( mergedImage, vtkSegmentationCore.vtkSegmentation. EXTENT_UNION_OF_SEGMENTS_PADDED, None, visibleSegmentIds): logging.error( 'Failed to apply smoothing: cannot get list of visible segments' ) return segmentLabelValues = [] # list of [segmentId, labelValue] for i in range(visibleSegmentIds.GetNumberOfValues()): segmentId = visibleSegmentIds.GetValue(i) segmentLabelValues.append([segmentId, i + 1]) # Perform smoothing in voxel space ici = vtk.vtkImageChangeInformation() ici.SetInputData(mergedImage) ici.SetOutputSpacing(1, 1, 1) ici.SetOutputOrigin(0, 0, 0) # Convert labelmap to combined polydata # vtkDiscreteFlyingEdges3D cannot be used here, as in the output of that filter, # each labeled region is completely disconnected from neighboring regions, and # for joint smoothing it is essential for the points to move together. convertToPolyData = vtk.vtkDiscreteMarchingCubes() convertToPolyData.SetInputConnection(ici.GetOutputPort()) convertToPolyData.SetNumberOfContours(len(segmentLabelValues)) contourIndex = 0 for segmentId, labelValue in segmentLabelValues: convertToPolyData.SetValue(contourIndex, labelValue) contourIndex += 1 # Low-pass filtering using Taubin's method smoothingFactor = self.scriptedEffect.doubleParameter( "JointTaubinSmoothingFactor") smoothingIterations = 100 # according to VTK documentation 10-20 iterations could be enough but we use a higher value to reduce chance of shrinking passBand = pow( 10.0, -4.0 * smoothingFactor ) # gives a nice range of 1-0.0001 from a user input of 0-1 smoother = vtk.vtkWindowedSincPolyDataFilter() smoother.SetInputConnection(convertToPolyData.GetOutputPort()) smoother.SetNumberOfIterations(smoothingIterations) smoother.BoundarySmoothingOff() smoother.FeatureEdgeSmoothingOff() smoother.SetFeatureAngle(90.0) smoother.SetPassBand(passBand) smoother.NonManifoldSmoothingOn() smoother.NormalizeCoordinatesOn() # Extract a label threshold = vtk.vtkThreshold() threshold.SetInputConnection(smoother.GetOutputPort()) # Convert to polydata geometryFilter = vtk.vtkGeometryFilter() geometryFilter.SetInputConnection(threshold.GetOutputPort()) # Convert polydata to stencil polyDataToImageStencil = vtk.vtkPolyDataToImageStencil() polyDataToImageStencil.SetInputConnection( geometryFilter.GetOutputPort()) polyDataToImageStencil.SetOutputSpacing(1, 1, 1) polyDataToImageStencil.SetOutputOrigin(0, 0, 0) polyDataToImageStencil.SetOutputWholeExtent(mergedImage.GetExtent()) # Convert stencil to image stencil = vtk.vtkImageStencil() emptyBinaryLabelMap = vtk.vtkImageData() emptyBinaryLabelMap.SetExtent(mergedImage.GetExtent()) emptyBinaryLabelMap.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) vtkSegmentationCore.vtkOrientedImageDataResample.FillImage( emptyBinaryLabelMap, 0) stencil.SetInputData(emptyBinaryLabelMap) stencil.SetStencilConnection(polyDataToImageStencil.GetOutputPort()) stencil.ReverseStencilOn() stencil.SetBackgroundValue( 1 ) # General foreground value is 1 (background value because of reverse stencil) imageToWorldMatrix = vtk.vtkMatrix4x4() mergedImage.GetImageToWorldMatrix(imageToWorldMatrix) # TODO: Temporarily setting the overwrite mode to OverwriteVisibleSegments is an approach that should be change once additional # layer control options have been implemented. Users may wish to keep segments on separate layers, and not allow them to be separated/merged automatically. # This effect could leverage those options once they have been implemented. oldOverwriteMode = self.scriptedEffect.parameterSetNode( ).GetOverwriteMode() self.scriptedEffect.parameterSetNode().SetOverwriteMode( slicer.vtkMRMLSegmentEditorNode.OverwriteVisibleSegments) for segmentId, labelValue in segmentLabelValues: threshold.ThresholdBetween(labelValue, labelValue) stencil.Update() smoothedBinaryLabelMap = slicer.vtkOrientedImageData() smoothedBinaryLabelMap.ShallowCopy(stencil.GetOutput()) smoothedBinaryLabelMap.SetImageToWorldMatrix(imageToWorldMatrix) self.scriptedEffect.modifySegmentByLabelmap( segmentationNode, segmentId, smoothedBinaryLabelMap, slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeSet, False) self.scriptedEffect.parameterSetNode().SetOverwriteMode( oldOverwriteMode)
def SimpleITKImageFromVTKTube(tube, SITKReferenceImage, debug=False): """ Input: VTK tube, referenceImage (used for spacing, etc.) Output: SimpleITK image Note: Uses binary output (background 0, foreground 1) """ size = list(SITKReferenceImage.GetSize()) origin = list(SITKReferenceImage.GetOrigin()) spacing = list(SITKReferenceImage.GetSpacing()) ncomp = SITKReferenceImage.GetNumberOfComponentsPerPixel() # convert the SimpleITK image to a numpy array arr = sitk.GetArrayFromImage(SITKReferenceImage).transpose(2, 1, 0).flatten() # send the numpy array to VTK with a vtkImageImport object dataImporter = vtk.vtkImageImport() dataImporter.CopyImportVoidPointer(arr, len(arr)) dataImporter.SetDataScalarTypeToUnsignedChar() dataImporter.SetNumberOfScalarComponents(ncomp) # Set the new VTK image's parameters dataImporter.SetDataExtent(0, size[0] - 1, 0, size[1] - 1, 0, size[2] - 1) dataImporter.SetWholeExtent(0, size[0] - 1, 0, size[1] - 1, 0, size[2] - 1) dataImporter.SetDataOrigin(origin) dataImporter.SetDataSpacing(spacing) dataImporter.Update() VTKReferenceImage = dataImporter.GetOutput() # fill the image with foreground voxels: inval = 1 outval = 0 VTKReferenceImage.GetPointData().GetScalars().Fill(inval) if debug: print("Using polydaya to generate stencil.") pol2stenc = vtk.vtkPolyDataToImageStencil() pol2stenc.SetTolerance(0.5) # points within 0.5 voxels are included pol2stenc.SetInputConnection(tube.GetOutputPort()) pol2stenc.SetOutputOrigin(VTKReferenceImage.GetOrigin()) pol2stenc.SetOutputSpacing(VTKReferenceImage.GetSpacing()) pol2stenc.SetOutputWholeExtent(VTKReferenceImage.GetExtent()) pol2stenc.Update() if debug: print("using stencil to generate image.") imgstenc = vtk.vtkImageStencil() imgstenc.SetInputData(VTKReferenceImage) imgstenc.SetStencilConnection(pol2stenc.GetOutputPort()) imgstenc.ReverseStencilOff() imgstenc.SetBackgroundValue(outval) imgstenc.Update() if debug: print("Generating SimpleITK image.") finalImage = imgstenc.GetOutput() finalArray = finalImage.GetPointData().GetScalars() finalArray = vtk_to_numpy(finalArray).reshape( SITKReferenceImage.GetSize()[::-1]) if debug: print(f"Volume = {finalArray.sum()*sum(spacing):.3f} mm^3") finalImageSITK = sitk.GetImageFromArray(finalArray) finalImageSITK.CopyInformation(SITKReferenceImage) return finalImageSITK