示例#1
0
 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())
示例#2
0
 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())
示例#3
0
 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.
示例#4
0
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()
示例#5
0
    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()
示例#6
0
    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