def showTextureOnModel(self, modelNode, textureImageNode): modelDisplayNode = modelNode.GetDisplayNode() modelDisplayNode.SetBackfaceCulling(0) textureImageFlipVert = vtk.vtkImageFlip() textureImageFlipVert.SetFilteredAxis(1) textureImageFlipVert.SetInputConnection(textureImageNode.GetImageDataConnection()) modelDisplayNode.SetTextureImageDataConnection(textureImageFlipVert.GetOutputPort())
def showTextureOnModel(self, modelNode, textureImageNode): modelDisplayNode=modelNode.GetDisplayNode() # Get model display node modelDisplayNode.SetBackfaceCulling(0) # In computer graphics, back-face culling determines whether a polygon of a graphical object is visible. textureImageFlipVert=vtk.vtkImageFlip() # vtkImageFlip will reflect the data along the filtered axis. textureImageFlipVert.SetFilteredAxis(1) # Specify which axis will be flipped. This must be an integer between 0 (for x) and 2 (for z). Initial value is 0. textureImageFlipVert.SetInputConnection(textureImageNode.GetImageDataConnection()) # Set the connection for the given input port index. Each input port of a filter has a specific purpose. A port may have zero or more connections and the required number is specified by each filter. Setting the connection with this method removes all other connections from the port. modelDisplayNode.SetTextureImageDataConnection(textureImageFlipVert.GetOutputPort()) # Set and observe the texture image data port.
def ConvertTextureToPointAttribute(modelNode, textureImageNode): polyData=modelNode.GetPolyData() textureImageFlipVert=vtk.vtkImageFlip() textureImageFlipVert.SetFilteredAxis(1) textureImageFlipVert.SetInputConnection(textureImageNode.GetImageDataConnection()) textureImageFlipVert.Update() textureImageData=textureImageFlipVert.GetOutput() pointData=polyData.GetPointData() tcoords=pointData.GetTCoords() numOfPoints=pointData.GetNumberOfTuples() assert numOfPoints==tcoords.GetNumberOfTuples(), "Number of texture coordinates does not equal number of points" textureSamplingPointsUv=vtk.vtkPoints() textureSamplingPointsUv.SetNumberOfPoints(numOfPoints) for pointIndex in xrange(numOfPoints): uv=tcoords.GetTuple2(pointIndex) textureSamplingPointsUv.SetPoint(pointIndex, uv[0], uv[1], 0) textureSamplingPointDataUv=vtk.vtkPolyData() uvToXyz=vtk.vtkTransform() textureImageDataSpacingSpacing=textureImageData.GetSpacing() textureImageDataSpacingOrigin=textureImageData.GetOrigin() textureImageDataSpacingDimensions=textureImageData.GetDimensions() uvToXyz.Scale(textureImageDataSpacingDimensions[0]/textureImageDataSpacingSpacing[0], textureImageDataSpacingDimensions[1]/textureImageDataSpacingSpacing[1], 1) uvToXyz.Translate(textureImageDataSpacingOrigin) textureSamplingPointDataUv.SetPoints(textureSamplingPointsUv) transformPolyDataToXyz=vtk.vtkTransformPolyDataFilter() transformPolyDataToXyz.SetInputData(textureSamplingPointDataUv) transformPolyDataToXyz.SetTransform(uvToXyz) probeFilter=vtk.vtkProbeFilter() probeFilter.SetInputConnection(transformPolyDataToXyz.GetOutputPort()) probeFilter.SetSourceData(textureImageData) probeFilter.Update() rgbPoints=probeFilter.GetOutput().GetPointData().GetArray('ImageScalars') colorArrayRed=vtk.vtkDoubleArray() colorArrayRed.SetName('ColorRed') colorArrayRed.SetNumberOfTuples(numOfPoints) colorArrayGreen=vtk.vtkDoubleArray() colorArrayGreen.SetName('ColorGreen') colorArrayGreen.SetNumberOfTuples(numOfPoints) colorArrayBlue=vtk.vtkDoubleArray() colorArrayBlue.SetName('ColorBlue') colorArrayBlue.SetNumberOfTuples(numOfPoints) for pointIndex in xrange(numOfPoints): rgb=rgbPoints.GetTuple3(pointIndex) colorArrayRed.SetValue(pointIndex,rgb[0]) colorArrayGreen.SetValue(pointIndex,rgb[1]) colorArrayBlue.SetValue(pointIndex,rgb[2]) colorArrayRed.Modified() colorArrayGreen.Modified() colorArrayBlue.Modified() pointData.AddArray(colorArrayRed) pointData.AddArray(colorArrayGreen) pointData.AddArray(colorArrayBlue) pointData.Modified() polyData.Modified()
def convertTextureToPointAttribute(self, modelNode, textureImageNode, colorAsVector): polyData = modelNode.GetPolyData() textureImageFlipVert = vtk.vtkImageFlip() textureImageFlipVert.SetFilteredAxis(1) textureImageFlipVert.SetInputConnection( textureImageNode.GetImageDataConnection()) textureImageFlipVert.Update() textureImageData = textureImageFlipVert.GetOutput() pointData = polyData.GetPointData() tcoords = pointData.GetTCoords() numOfPoints = pointData.GetNumberOfTuples() assert numOfPoints == tcoords.GetNumberOfTuples( ), "Number of texture coordinates does not equal number of points" textureSamplingPointsUv = vtk.vtkPoints() textureSamplingPointsUv.SetNumberOfPoints(numOfPoints) for pointIndex in range(numOfPoints): uv = tcoords.GetTuple2(pointIndex) textureSamplingPointsUv.SetPoint(pointIndex, uv[0], uv[1], 0) textureSamplingPointDataUv = vtk.vtkPolyData() uvToXyz = vtk.vtkTransform() textureImageDataSpacingSpacing = textureImageData.GetSpacing() textureImageDataSpacingOrigin = textureImageData.GetOrigin() textureImageDataSpacingDimensions = textureImageData.GetDimensions() uvToXyz.Scale( textureImageDataSpacingDimensions[0] / textureImageDataSpacingSpacing[0], textureImageDataSpacingDimensions[1] / textureImageDataSpacingSpacing[1], 1) uvToXyz.Translate(textureImageDataSpacingOrigin) textureSamplingPointDataUv.SetPoints(textureSamplingPointsUv) transformPolyDataToXyz = vtk.vtkTransformPolyDataFilter() transformPolyDataToXyz.SetInputData(textureSamplingPointDataUv) transformPolyDataToXyz.SetTransform(uvToXyz) probeFilter = vtk.vtkProbeFilter() probeFilter.SetInputConnection(transformPolyDataToXyz.GetOutputPort()) probeFilter.SetSourceData(textureImageData) probeFilter.Update() rgbPoints = probeFilter.GetOutput().GetPointData().GetArray( 'ImageScalars') if colorAsVector: colorArray = vtk.vtkDoubleArray() colorArray.SetName('Color') colorArray.SetNumberOfComponents(3) colorArray.SetNumberOfTuples(numOfPoints) for pointIndex in range(numOfPoints): rgb = rgbPoints.GetTuple3(pointIndex) colorArray.SetTuple3(pointIndex, rgb[0] / 255., rgb[1] / 255., rgb[2] / 255.) colorArray.Modified() pointData.AddArray(colorArray) else: colorArrayRed = vtk.vtkDoubleArray() colorArrayRed.SetName('ColorRed') colorArrayRed.SetNumberOfTuples(numOfPoints) colorArrayGreen = vtk.vtkDoubleArray() colorArrayGreen.SetName('ColorGreen') colorArrayGreen.SetNumberOfTuples(numOfPoints) colorArrayBlue = vtk.vtkDoubleArray() colorArrayBlue.SetName('ColorBlue') colorArrayBlue.SetNumberOfTuples(numOfPoints) for pointIndex in range(numOfPoints): rgb = rgbPoints.GetTuple3(pointIndex) colorArrayRed.SetValue(pointIndex, rgb[0]) colorArrayGreen.SetValue(pointIndex, rgb[1]) colorArrayBlue.SetValue(pointIndex, rgb[2]) colorArrayRed.Modified() colorArrayGreen.Modified() colorArrayBlue.Modified() pointData.AddArray(colorArrayRed) pointData.AddArray(colorArrayGreen) pointData.AddArray(colorArrayBlue) pointData.Modified() polyData.Modified()
def onCompute(self): slicer.app.processEvents() import time # Show the status bar self.progressBar.show() # Initilize various parameters self.bone_labels = np.fromstring(self.lineedit.text, dtype=int, sep=',') # Check to see if self.bone_labels is set to negative on and if so set to the default labels if self.bone_labels[0] == -1: # Use the minimum and maximum of the Ref_Bone_Slider (which is based on the minimum and maximum label in the first image) self.bone_labels = range(int(self.Ref_Bone_Slider.minimum), int(self.Ref_Bone_Slider.maximum) + 1) self.max_bone_label = np.max(self.bone_labels) # Find all the files in the input folder self.files = os.listdir(self.directory_path) # Sort the files to be in order now self.files.sort(key=self.alphanum_key) if self.num_files > len(self.files): self.num_files = len(self.files) # Initilize a list of file indicies if self.num_files == -1: self.file_list = range(0, len(self.files)) else: self.file_list = range(0, int(self.num_files)) # Initilize Python list to hold all of the polydata # One index for each bone label (ranges from 1 to 9) polydata_list = [] for i in range(0, self.max_bone_label + 1): polydata_list.append([]) # Load all of the images from the input folder images_list = [] for curr_file in self.file_list: # Update the status bar self.progressBar.setValue( float(curr_file) / len(self.file_list) * 100 / 10) # Use 10% of the status bar for loading the images slicer.app.processEvents() slicer.util.showStatusMessage("Loading Images...") if self.files[curr_file][-3:] == 'nii': print(str('Running file number ' + str(curr_file))) # Load the nifti (.nii) or analyze image (.img/.hdr) using SimpleITK filename = os.path.join(self.directory_path, self.files[curr_file]) image = self.load_image(filename) # It's upside-down when loaded, so add a flip filter if self.flip_image_vertically.checked == True: imflip = vtk.vtkImageFlip() try: imflip.SetInputData(image.GetOutput()) except: imflip.SetInputData(image) imflip.SetFilteredAxis(1) imflip.Update() image = imflip.GetOutput() # If the images are flipped left/right so use a flip filter if self.flip_image_horizontally.checked == True: imflip = vtk.vtkImageFlip() try: imflip.SetInputData(image.GetOutput()) except: imflip.SetInputData(image) imflip.SetFilteredAxis(0) imflip.Update() image = imflip.GetOutput() # Append the loaded image to the images_list images_list.append(image) # Temporarily push the image to Slicer (to have the correct class type for the model maker Slicer module) if self.debug_show_images.checked == True: image = sitk.ReadImage(filename) sitkUtils.PushToSlicer(image, str(curr_file), 0, overwrite=True) node = slicer.util.getNode(str(curr_file)) # If there is a non .nii file in the folder the images_list will be shorter than file_list # Redefine the file_list here self.file_list = range(0, len(images_list)) iter = 0 # For status bar # Extract the surface from each image (i.e. the polydata) for label in self.bone_labels: for curr_file in self.file_list: # Update the status bar (start at 10%) self.progressBar.setValue( 10 + float(iter) / (len(self.bone_labels) * len(self.file_list)) * 100 / 5) # Use 20% of the bar for this slicer.app.processEvents() iter = iter + 1 slicer.util.showStatusMessage("Extracting Surfaces...") polydata = self.Extract_Surface(images_list[curr_file], label) polydata_list[label].append(polydata) # Create model node ("Extract_Shapes") and add to scene if self.show_extracted_shapes.checked == True: Extract_Shapes = slicer.vtkMRMLModelNode() Extract_Shapes.SetAndObservePolyData(polydata) modelDisplay = slicer.vtkMRMLModelDisplayNode() modelDisplay.SetSliceIntersectionVisibility( True) # Show in slice view modelDisplay.SetVisibility(True) # Show in 3D view slicer.mrmlScene.AddNode(modelDisplay) Extract_Shapes.SetAndObserveDisplayNodeID( modelDisplay.GetID()) slicer.mrmlScene.AddNode(Extract_Shapes) # Save each registered bone separately? if self.Save_Extracted_Bones_Separately.checked == True: for label in self.bone_labels: for i in range(0, len(self.file_list)): path = os.path.join( self.output_directory_path, 'Bone_' + str(label) + '_position_' + str(i) + '.ply') plyWriter = vtk.vtkPLYWriter() plyWriter.SetFileName(path) plyWriter.SetInputData(polydata_list[label][i]) plyWriter.Write() print('Saved: ' + path) # If this is set to true, stop the computation after extracting and smoothing the bones if self.Skip_Registration.checked == True: # Set the status bar to 100% self.progressBar.setValue(100) slicer.app.processEvents() slicer.util.showStatusMessage("Skipping Registration Step...") # Hide the status bar self.progressBar.hide() # Reset the status message on bottom of 3D Slicer slicer.util.showStatusMessage(" ") return 0 # Update the status bar (start at 30%) self.progressBar.setValue(30 + 20) # Use 20% of the bar for this slicer.app.processEvents() slicer.util.showStatusMessage("Calculating Reference Shapes...") # Don't use the mean shapes # Use the bone shapes from volunteer 1 instead of the mean shape for each bone # Initialize a Python list to hold the reference shapes reference_shapes = [] # One index for each bone label (ranges from 1 to 9) for i in range(0, self.max_bone_label + 1): reference_shapes.append([]) # Get the bone shapes from the first volunteer and save them for label in self.bone_labels: reference_shapes[label].append(polydata_list[label][0]) ######### Register the reference shape to each bone position ######### iter_bar = 0 # For status bar for label in self.bone_labels: for i in range(0, len(self.file_list)): # Update the status bar (start at 50%) self.progressBar.setValue( 50 + float(iter_bar) / (len(self.bone_labels) * len(self.file_list)) * 100 / 5) # Use 20% of the bar for this slicer.app.processEvents() iter_bar = iter_bar + 1 slicer.util.showStatusMessage( "Registering Reference Shapes...") transformedSource = self.IterativeClosestPoint( target=polydata_list[label][i], source=reference_shapes[label][0]) # Replace the surface of file i and label with the registered reference shape for that particular bone polydata_list[label][i] = transformedSource iter_bar = 0 # For status bar ######### Register the reference bone (usually the radius for the wrist) for all the volunteers together ######### for label in self.bone_labels: for i in range(0, len(self.file_list)): # !! IMPORTANT !! Register the reference bone last (or else the bones afterwards will not register correctly) # Skip the reference label for now (register after all the other bones are registered) if label != self.ref_label: # Update the status bar (start at 70%) self.progressBar.setValue( 70 + float(iter_bar) / (len(self.bone_labels) * len(self.file_list)) * 100 / 5) # Use 20% of the bar for this slicer.app.processEvents() iter_bar = iter_bar + 1 slicer.util.showStatusMessage( "Registering Radius Together...") polydata_list[label][i] = self.IterativeClosestPoint( target=polydata_list[self.ref_label][0], source=polydata_list[self.ref_label][i], reference=polydata_list[label][i]) # Now register the reference label bones together for i in range(0, len(self.file_list)): polydata_list[self.ref_label][i] = self.IterativeClosestPoint( target=polydata_list[self.ref_label][0], source=polydata_list[self.ref_label][i], reference=polydata_list[self.ref_label][i]) ######### Save the output ######### # Should the reference bone be remove (i.e. not saved) in the final PLY surface file? if self.Remove_Ref_Bone.checked == True: index = np.argwhere(self.bone_labels == self.ref_label) self.bone_labels = np.delete(self.bone_labels, index) # Combine the surfaces of the wrist for each person and save as a .PLY file for i in range(0, len(self.file_list)): temp_combine_list = [] # Update the status bar (start at 90%) self.progressBar.setValue(90 + float(i) / len(self.file_list) * 100 / 10) # Use 10% of the bar for this slicer.app.processEvents() iter_bar = iter_bar + 1 slicer.util.showStatusMessage("Saving Output Surfaces...") total_points = [0] # Get all the bones in a Python list for volunteer 'i' for label in self.bone_labels: temp_combine_list.append(polydata_list[label][i]) # Print the number of surface points for this bone num_points = polydata_list[label][i].GetNumberOfPoints() print("Bone " + str(label) + " points: " + str(num_points)) total_points.append(total_points[-1] + num_points) print("Total Cumulative Points" + str(total_points)) # Combined the surfaces in the list into a single polydata surface combined_polydata = self.Combine_Surfaces(temp_combine_list) # Create model node ("ICP_Result") and add to scene if self.show_registered_shapes.checked == True: ICP_Result = slicer.vtkMRMLModelNode() ICP_Result.SetAndObservePolyData(combined_polydata) modelDisplay = slicer.vtkMRMLModelDisplayNode() modelDisplay.SetSliceIntersectionVisibility( True) # Show in slice view modelDisplay.SetVisibility(True) # Show in 3D view slicer.mrmlScene.AddNode(modelDisplay) ICP_Result.SetAndObserveDisplayNodeID(modelDisplay.GetID()) slicer.mrmlScene.AddNode(ICP_Result) # Write the combined polydata surface to a .PLY file plyWriter = vtk.vtkPLYWriter() path = os.path.join(self.output_directory_path, str(self.files[i][:-4]) + '_combined.ply') plyWriter.SetFileName(path) plyWriter.SetInputData(combined_polydata) plyWriter.Write() print('Saved: ' + path) # Save each registered bone separately as well? if self.Save_Registered_Bones_Separately.checked == True: for label in self.bone_labels: path = os.path.join( self.output_directory_path, 'Position_' + str(i) + '_bone_' + str(label) + '.ply') plyWriter.SetFileName(path) plyWriter.SetInputData(polydata_list[label][i]) plyWriter.Write() print('Saved: ' + path) # Set the status bar to 100% self.progressBar.setValue(100) # Hide the status bar self.progressBar.hide() # Reset the status message on bottom of 3D Slicer slicer.util.showStatusMessage(" ") return 0