def run(self, inputVolume, outputVolume, imageThreshold, enableScreenshots,
            filterType):
        """
    Run the actual algorithm
    """

        start = time.time()
        #if not self.isValidInputOutputData(inputVolume, outputVolume):
        # slicer.util.errorDisplay('Input volume is the same as output volume. Choose a different output volume.')
        #return False

        logging.info('Processing started')

        # Compute the thresholded output volume using the Threshold Scalar Volume CLI module
        # cliParams = {'InputVolume': inputVolume.GetID(), 'OutputVolume': outputVolume.GetID(), 'ThresholdValue' : imageThreshold, 'ThresholdType' : 'Above'}
        # cliNode = slicer.cli.run(slicer.modules.thresholdscalarvolume, None, cliParams, wait_for_completion=True)

        # Capture screenshot
        if enableScreenshots:
            self.takeScreenshot('SpineSegTest-Start', 'MyScreenshot', -1)

        inputImage = sitkUtils.PullFromSlicer(inputVolume.GetName())
        #
        # TODO: rest of ifs for our filter possibilites
        if filterType == "Gaussian Filter":
            imageFilter = sitk.MeanImageFilter()
            outputImage = imageFilter.Execute(inputImage)
            imageFilter = sitk.ThresholdImageFilter()
            outputImage = imageFilter.Execute(outputImage, 200, 1400, 1)
            imageFilter = sitk.ThresholdMaximumConnectedComponentsImageFilter()
            outputImage = imageFilter.Execute(outputImage)
            sitkUtils.PushToSlicer(outputImage, outputVolume.GetName())
            return True
        elif filterType == "Edge Detection":
            imageFilter = sitk.MeanImageFilter()
            outputImage = imageFilter.Execute(inputImage)
            imageFilter = sitk.ThresholdImageFilter()
            outputImage = imageFilter.Execute(inputImage, 300, 1400, 1)
            imageFilter = sitk.ScalarConnectedComponentImageFilter()
            outputImage = imageFilter.Execute(outputImage)
            sitkUtils.PushToSlicer(outputImage, outputVolume.GetName())
            return True
        elif filterType == "Threshold Image":

            imageFilter = sitk.MeanImageFilter()
            outputImage = imageFilter.Execute(inputImage)
            imageFilter = sitk.BinaryOpeningByReconstructionImageFilter()
            outputImage = imageFilter.Execute(outputImage)
            imageFilter = sitk.ThresholdImageFilter()
            outputImage = imageFilter.Execute(inputImage, 200, 1400, 1)
            #imageFilter = sitk.MaximumEntropyThresholdImageFilter()
            #outputImage = imageFilter.Execute(inputImage)
            sitkUtils.PushToSlicer(outputImage,
                                   outputVolume.GetName(),
                                   overwrite=True)

            end = time.time()
            print(end - start)

        outputImData = outputVolume.GetImageData()
def ImageModelSnapshot(self,
                       dataNode,
                       labelNode,
                       outputDir,
                       IDcurrPatient,
                       ImageFilePath,
                       progress_filename,
                       selLabels=False,
                       levels=False):
    cast1 = vtk.vtkImageCast()
    cast1.SetOutputScalarTypeToInt()
    cast1.SetInputConnection(labelNode.GetImageDataConnection())
    cast1.Update()
    labelNode.SetImageDataConnection(cast1.GetOutputPort())

    cast2 = vtk.vtkImageCast()
    cast2.SetOutputScalarTypeToInt()
    cast2.SetInputConnection(dataNode.GetImageDataConnection())
    cast2.Update()
    dataNode.SetImageDataConnection(cast2.GetOutputPort())

    labelNode.SetOrigin(dataNode.GetOrigin())
    try:
        imageNodeSITK = su.PullFromSlicer(dataNode.GetName())
        labelNodeSITK = su.PullFromSlicer(labelNode.GetName())

        labelArraySITK = sitk.GetArrayFromImage(labelNodeSITK)
        lbound, hbound = squeeze(self, labelArraySITK, labelNode)

        self.cmaj = sitk.CropImageFilter()
        self.cmaj.SetLowerBoundaryCropSize(lbound)
        self.cmaj.SetUpperBoundaryCropSize(hbound)

        zoomLabelNodeSITK = self.cmaj.Execute(labelNodeSITK)
        zoomImageNodeSITK = self.cmaj.Execute(imageNodeSITK)

        zoomLabelNodeName = 'zoomLabelNode' + '_' + IDcurrPatient
        zoomImageNodeName = 'zoomImageNode' + '_' + IDcurrPatient
        su.PushToSlicer(zoomLabelNodeSITK, zoomLabelNodeName)
        su.PushToSlicer(zoomImageNodeSITK, zoomImageNodeName)
        zoomLabelNode = slicer.util.getNode(zoomLabelNodeName)
        zoomImageNode = slicer.util.getNode(zoomImageNodeName)

        zoomLabelNodeArraySITK = sitk.GetArrayFromImage(zoomLabelNodeSITK)
        zoomLabelNodeArraySITK = numpy.where(zoomLabelNodeArraySITK == 0,
                                             numpy.NAN, zoomLabelNodeArraySITK)
        maxZind = find_LargestSlices(self, zoomLabelNodeArraySITK)

        imgOutputDir = str(outputDir)
        modelHandler(ImageFilePath, zoomImageNode, zoomLabelNode, imgOutputDir,
                     IDcurrPatient, maxZind)

        return (maxZind)

    except Exception, e:
        with open(progress_filename, mode='a') as printfile:
            printfile.write('ERROR: ' + str(e) + '\n')
        os.makedirs(os.path.join(outputDir, IDcurrPatient + '_flagged'))
        return (-1, -1, -1)
    def run(self, inputVolume, outputVolume, minValue, maxValue, imageFilter):
        '''
    :param inputVolume: the input image volume
    :param outputVolume: the output image volume
    :param minValue: the min threshold selected by user
    :param maxValue: the max threshold select by user

    Gets the inputVolume name, pulls the image from slicer, adds the filter and threshold
    based on the user defined variables
    '''
        #Get the input info
        inputImage = inputVolume.GetName()
        image = sitkUtils.PullFromSlicer(inputImage)
        outputImage = outputVolume.GetName()

        image = self.resizeImage(image)
        #resampleFilter = SimpleITK.ResampleImageFilter()
        #resampleFilter.SetOutputSpacing((1,1,1))
        #image = resampleFilter.Execute(image)

        #Add the filter to the image
        imgSmooth = self.addFilterToImage(image, imageFilter)

        # Threshold the image with user-set threshold values
        #imgWhiteMatter = SimpleITK.ConnectedThreshold(image1=sitkUtils.PullFromSlicer(outputImage), seedList=[(255,0,0)], lower=minValue, upper=maxValue, replaceValue=1)

        imgWhiteMatter = self.thresholdImage(minValue, maxValue)

        #Rescale and cast imgSmooth to match type of imgWhiteMatter (int)
        imgSmoothInt = SimpleITK.Cast(SimpleITK.RescaleIntensity(imgSmooth),
                                      imgWhiteMatter.GetPixelID())

        #overlay = SimpleITK.LabelMapOverlayImageFilter()
        #overlay.SetOpacity(0.6)
        #overlay = overlay.Execute(imgSmoothInt, imgWhiteMatter)
        #sitkUtils.PushToSlicer(overlay, 'test', 0, True)
        # overlay imgWhiteMatter on imgSmoothInt

        imgWhiteMatterNoHoles = SimpleITK.VotingBinaryHoleFilling(
            image1=imgWhiteMatter,
            radius=((2, 2, 2)),
            majorityThreshold=1,
            backgroundValue=0,
            foregroundValue=1)
        #sitkUtils.PushToSlicer(imgWhiteMatterNoHoles, "imgWhiteMatter", 2, True)

        sitkUtils.PushToSlicer(imgWhiteMatterNoHoles, "imgWhiteMatter", 2,
                               True)
        sitkUtils.PushToSlicer(imgSmoothInt, outputImage, 0, True)

        #node = slicer.util.getNode("imgWhiteMatter")
        #node = node.GetScalarVolumeDisplayNode()
        #node.SetOpacity(0.5)

        print("\n")
def denoising_BayesShrinkAndVIsuShrink(Nom_image):
    image=su.PullFromSlicer(NomDeLImage)
    NumpyImage=sitk.GetArrayFromImage(image)
    # Estimate the average noise standard deviation across color channels.
    sigma_est = estimate_sigma(NumpyImage, multichannel=True, average_sigmas=True)
    # Due to clipping in random_noise, the estimate will be a bit smaller than the
    # specified sigma.
    print(f"Estimated Gaussian noise standard deviation = {sigma_est}")
    im_bayes = denoise_wavelet(NumpyImage, multichannel=True, convert2ycbcr=True, method='BayesShrink', mode='soft',rescale_sigma=True)
    im_visushrink = denoise_wavelet(NumpyImage, multichannel=True, convert2ycbcr=True, method='VisuShrink', mode='soft',sigma=sigma_est, rescale_sigma=True)
    su.PushToSlicer(im_bayes,'image_DenoisWave_level0-'+str(Nlevel))
    su.PushToSlicer(im_visushrink,'image_DenoisWave_level0-'+str(Nlevel))
 def applyITKOtsuFilter(self, volume):
     inputVolume = sitk.Cast(sitkUtils.PullVolumeFromSlicer(volume.GetID()),
                             sitk.sitkInt16)
     self.otsuFilter.SetInsideValue(0)
     self.otsuFilter.SetOutsideValue(1)
     otsuITKVolume = self.otsuFilter.Execute(inputVolume)
     return sitkUtils.PushToSlicer(otsuITKVolume, "otsuITKVolume", 0, True)
    def addFilterToImage(self, inputImage, filterName):
        '''
    :param image, filterName: The image that requires a filter and the filter name
    :return: None, adds the filter and adds to slicer
    '''
        #Check which option the user chose.
        if filterName == "Smoothing Recursive Gaussian":
            imageFilter = SimpleITK.SmoothingRecursiveGaussianImageFilter()
        elif filterName == "Discrete Gaussian":
            imageFilter = SimpleITK.DiscreteGaussianImageFilter()
        elif filterName == "Shot Noise":
            imageFilter = SimpleITK.ShotNoiseImageFilter()
        elif filterName == "Curvature Flow":
            imageFilter = SimpleITK.CurvatureFlowImageFilter()
            imageFilter.SetNumberOfIterations(5)
        else:
            print(
                "ERROR: Filter was not properly set. Using Smoothing Recursive Gaussian."
            )
            imageFilter = SimpleITK.SmoothingRecursiveGaussianImageFilter()

        #Execute the filter on the image
        smoothedImage = imageFilter.Execute(inputImage)

        #Add it to slicer, overwrite the current node
        #True means overwrite the outputName instead of creating a new one
        sitkUtils.PushToSlicer(smoothedImage, "imgSmooth", 0, True)
        return smoothedImage
    def runThreshold(self, masterNode, labelNode):

        masterImage = sitkUtils.PullFromSlicer(masterNode.GetID())

        labelArray = slicer.util.array(labelNode.GetID())
        masterArray = slicer.util.array(masterNode.GetID())

        connectedThresholdIF = SimpleITK.ConnectedThresholdImageFilter()
        connectedThresholdIF.SetLower(mean - (1.5 * std))
        connectedThresholdIF.SetUpper(mean + (1.5 * std))

        print('Centroid:', int(centroidX), int(centroidY))
        connectedThresholdIF.SetSeed([int(centroidX), int(centroidY), maskZ])
        print('starting: connected threshold filter')
        thresholdImage = connectedThresholdIF.Execute(masterImage)

        # take this out for now, as time costly and may be best to close holes in 2D
        '''
    print('starting: fill holes filter')
    fillHoleIF = SimpleITK.GrayscaleFillholeImageFilter()
    connectedImage = fillHoleIF.Execute(thresholdImage)
    '''

        sitkUtils.PushToSlicer(thresholdImage, 'connectedImage')
        #print('save self.connected image')
        '''
 def DeformInColor(LabelVolumeSphere_IRM, distance, Nlabels):
     Add = sitk.AddImageFilter()
     NSpheresTolerance = np.zeros(3)
     image_distance = sitk.BinaryThreshold(LabelVolumeSphere_IRM, 500,
                                           500, 0, 0)
     for i in Nlabels:
         if distance[i] <= 1.0:
             image_distance = Add.Execute(
                 image_distance,
                 sitk.BinaryThreshold(LabelVolumeSphere_IRM, i, i, 6,
                                      0))
             NSpheresTolerance[0] += 1
         elif distance[i] <= 2.0:
             image_distance = Add.Execute(
                 image_distance,
                 sitk.BinaryThreshold(LabelVolumeSphere_IRM, i, i, 13,
                                      0))
             NSpheresTolerance[1] += 1
         else:
             image_distance = Add.Execute(
                 image_distance,
                 sitk.BinaryThreshold(LabelVolumeSphere_IRM, i, i, 14,
                                      0))
             NSpheresTolerance[2] += 1
     su.PushToSlicer(
         image_distance, "Resultat_DisGeo_CT_MRI" + str(date.day) +
         str(date.month) + str(date.year), 2)
     return NSpheresTolerance
Beispiel #9
0
def VolumeIntensityCorrection(volume, logFilePath):
    spacing = volume.GetSpacing()
    origin = volume.GetOrigin()
    ras2ijk = vtk.vtkMatrix4x4()
    ijk2ras = vtk.vtkMatrix4x4()
    volume.GetRASToIJKMatrix(ras2ijk)
    volume.GetIJKToRASMatrix(ijk2ras)

    imgsitk = su.PullFromSlicer(volume.GetName())
    imgsitk_array = sitk.GetArrayFromImage(imgsitk)
    imgsitk_array = imgsitk_array.__sub__(imgsitk_array.min())
    imgsitk = sitk.GetImageFromArray(imgsitk_array)
    outputImageName = volume.GetName() + '_corrected'
    su.PushToSlicer(imgsitk, outputImageName)
    volumeCorrected = slicer.util.getNode(outputImageName)

    volumeCorrected.SetOrigin(origin)
    volumeCorrected.SetSpacing(spacing)
    volumeCorrected.SetRASToIJKMatrix(ras2ijk)
    volumeCorrected.SetIJKToRASMatrix(ijk2ras)

    with open(logFilePath, mode='a') as logfile:
        logfile.write("\tCORRECTED: Image intensity values corrected: " +
                      volumeCorrected.GetName() + '\n')
    return volumeCorrected
  def createHoleFilledVolumeNode(self, ventricleVolume, thresholdValue, samplingFactor, morphologyParameters):
    
    holeFillKernelSize = morphologyParameters[0]
    maskKernelSize = morphologyParameters[1]
    resampleFilter = sitk.ResampleImageFilter()
    ventricleImage = sitk.Cast(sitkUtils.PullFromSlicer(ventricleVolume.GetID()), sitk.sitkInt16)
    
    resampleFilter.SetSize(numpy.array(ventricleImage.GetSize()) / samplingFactor)
    resampleFilter.SetOutputSpacing(numpy.array(ventricleImage.GetSpacing()) * samplingFactor)
    resampleFilter.SetOutputDirection(ventricleImage.GetDirection())
    resampleFilter.SetOutputOrigin(numpy.array(ventricleImage.GetOrigin()))
    resampledImage = resampleFilter.Execute(ventricleImage)
    thresholdFilter = sitk.BinaryThresholdImageFilter()
    thresholdImage = thresholdFilter.Execute(resampledImage, thresholdValue, 10000, 1, 0)

    padFilter = sitk.ConstantPadImageFilter()
    padFilter.SetPadLowerBound(holeFillKernelSize)
    padFilter.SetPadUpperBound(holeFillKernelSize)
    paddedImage = padFilter.Execute(thresholdImage)
    
    dilateFilter = sitk.BinaryDilateImageFilter()
    dilateFilter.SetKernelRadius(holeFillKernelSize)
    dilateFilter.SetBackgroundValue(0)
    dilateFilter.SetForegroundValue(1)
    dilatedImage = dilateFilter.Execute(paddedImage)
    
    erodeFilter = sitk.BinaryErodeImageFilter()
    erodeFilter.SetKernelRadius(holeFillKernelSize)
    erodeFilter.SetBackgroundValue(0)
    erodeFilter.SetForegroundValue(1)
    erodedImage = erodeFilter.Execute(dilatedImage)
    
    fillHoleFilter = sitk.BinaryFillholeImageFilter()
    holefilledImage = fillHoleFilter.Execute(erodedImage)
    dilateFilter = sitk.BinaryDilateImageFilter()
    dilateFilter.SetKernelRadius(maskKernelSize)
    dilateFilter.SetBackgroundValue(0)
    dilateFilter.SetForegroundValue(1)
    dilatedImage = dilateFilter.Execute(holefilledImage)
    subtractFilter = sitk.SubtractImageFilter()
    subtractedImage = subtractFilter.Execute(dilatedImage, holefilledImage)
    holefilledImageNode = sitkUtils.PushToSlicer(holefilledImage, "holefilledImage", 0, False)
    subtractedImageNode = sitkUtils.PushToSlicer(subtractedImage, "subtractedImage", 0, False)
    return holefilledImageNode, subtractedImageNode
 def applyOtsuFilter(volume):
     otsuFilter = sitk.OtsuThresholdImageFilter()
     otsuFilter.SetInsideValue(0)
     otsuFilter.SetOutsideValue(1)
     inputVolume = sitk.Cast(sitkUtils.PullVolumeFromSlicer(volume.GetID()),
                             sitk.sitkInt16)
     outputITKVolume = otsuFilter.Execute(inputVolume)
     outputVolume = sitkUtils.PushToSlicer(outputITKVolume,
                                           "ZFrame_Otsu_Output", 0, True)
     return outputVolume
def addGaussianNoise(inputImageNode, outputImageNodeName, sd, mean):
    
    input  = sitk.Cast(sitkUtils.PullFromSlicer(inputImageNode.GetID()), sitk.sitkUInt16)

    noiseFilter = sitk.AdditiveGaussianNoiseImageFilter()
    noiseFilter.SetDebug(False)
    noiseFilter.SetMean(mean)
    noiseFilter.SetSeed(0)
    noiseFilter.SetStandardDeviation(sd)
    output = noiseFilter.Execute(input)
    sitkUtils.PushToSlicer(output, outputImageNodeName, 0, True)
Beispiel #13
0
    def onApplyZFrameRegistrationButtonClicked(self):
        zFrameTemplateVolume = self.logic.templateVolume
        try:
            if self.zFrameRegistrationClass is OpenSourceZFrameRegistration:
                self.annotationLogic.SetAnnotationLockedUnlocked(
                    self.coverTemplateROI.GetID())
                self.zFrameCroppedVolume = self.logic.createCroppedVolume(
                    zFrameTemplateVolume, self.coverTemplateROI)
                self.zFrameLabelVolume = self.logic.createLabelMapFromCroppedVolume(
                    self.zFrameCroppedVolume, "labelmap")
                self.zFrameMaskedVolume = self.logic.createMaskedVolume(
                    zFrameTemplateVolume,
                    self.zFrameLabelVolume,
                    outputVolumeName="maskedTemplateVolume")
                self.zFrameMaskedVolume.SetName(
                    zFrameTemplateVolume.GetName() + "-label")

                if not self.zFrameRegistrationManualIndexesGroupBox.checked:
                    start, center, end = self.logic.getROIMinCenterMaxSliceNumbers(
                        self.coverTemplateROI)
                    inputVolume = sitk.Cast(
                        sitkUtils.PullVolumeFromSlicer(
                            self.zFrameMaskedVolume.GetID()), sitk.sitkInt16)
                    self.logic.otsuFilter.SetInsideValue(0)
                    self.logic.otsuFilter.SetOutsideValue(1)
                    otsuITKVolume = self.logic.otsuFilter.Execute(inputVolume)
                    otsuOutputVolume = sitkUtils.PushToSlicer(
                        otsuITKVolume, "otsuITKVolume", 0, True)
                    self.logic.dilateMask(otsuOutputVolume)
                    start, end = self.logic.getStartEndWithConnectedComponents(
                        otsuOutputVolume, center)
                    self.zFrameRegistrationStartIndex.value = start
                    self.zFrameRegistrationEndIndex.value = end
                else:
                    start = self.zFrameRegistrationStartIndex.value
                    end = self.zFrameRegistrationEndIndex.value
                self.logic.runZFrameRegistration(self.zFrameMaskedVolume,
                                                 self.zFrameRegistrationClass,
                                                 startSlice=start,
                                                 endSlice=end)
            else:
                self.logic.runZFrameRegistration(zFrameTemplateVolume,
                                                 self.zFrameRegistrationClass)
            self.applyZFrameTransform()

        except AttributeError as exc:
            slicer.util.errorDisplay(
                "An error occurred. For further information click 'Show Details...'",
                windowTitle=self.__class__.__name__,
                detailedText=str(exc.message))
        else:
            self.setBackgroundToVolumeID(zFrameTemplateVolume.GetID())
            self.approveZFrameRegistrationButton.enabled = True
            self.retryZFrameRegistrationButton.enabled = True
def wavelet_denoising(NomDeLImage, Nlevel):
    image=su.PullFromSlicer(NomDeLImage)
    NumpyImage=sitk.GetArrayFromImage(image)
    max_lev = 6       # how many levels of decomposition to draw
    coeffs = pywt.wavedecn(NumpyImage, 'db2', mode='zero', level=max_lev) #voir https://pywavelets.readthedocs.io/en/latest/ref/nd-dwt-and-idwt.html#pywt.wavedecn
    for i in range(Nlevel-max_lev):
        coeffs[(max_lev-i)] = {k: np.zeros_like(v) for k, v in coeffs[(max_lev-i)].items()} #remove highest frequency
        coeffs[-(max_lev-i)] = {k: np.zeros_like(v) for k, v in coeffs[-(max_lev-i)].items()} #remove highest frequency
    matrice_ondelette=pywt.waverecn(coeffs, 'db2') #mode periodic ou zero
    image_ondelette=sitk.GetImageFromArray(matrice_ondelette)
    image_ondelette.SetSpacing(image.GetSpacing())
    image_ondelette.SetDirection(image.GetDirection())
    image_ondelette.SetOrigin(image.GetOrigin())
    su.PushToSlicer(image_ondelette,'image_DenoisWave_level0-'+str(Nlevel))
def denoising_nonlocalmeans2(Nom_image):
    image=su.PullFromSlicer(Nom_image)
    Shrinkfactor=2
    image=sitk.Shrink(image, [Shrinkfactor,Shrinkfactor,Shrinkfactor])
    timeRMR1 = time.time()
    DenoiseFilter_init=sitk.PatchBasedDenoisingImageFilter() #Execute (const Image &image1, double kernelBandwidthSigma, uint32_t patchRadius, 
    #uint32_t numberOfIterations, uint32_t numberOfSamplePatches, double sampleVariance, PatchBasedDenoisingImageFilter::NoiseModelType noiseModel, 
    #double noiseSigma, double noiseModelFidelityWeight, bool alwaysTreatComponentsAsEuclidean, bool kernelBandwidthEstimation, double kernelBandwidthMultiplicationFactor, 
    #uint32_t kernelBandwidthUpdateFrequency, double kernelBandwidthFractionPixelsForEstimation)
    DenoiseFilter_init.SetAlwaysTreatComponentsAsEuclidean(True)
    DenoiseFilter_init.SetKernelBandwidthEstimation(True)
    DenoiseFilter_init.SetKernelBandwidthFractionPixelsForEstimation(0.5) #double KernelBandwidthFractionPixelsForEstimation
    #DenoiseFilter.SetKernelBandwidthMultiplicationFactor() #(double KernelBandwidthMultiplicationFactor)
    #DenoiseFilter.SetKernelBandwidthSigma(400) #(double KernelBandwidthSigma)  #faible voire pas d'influence
    #DenoiseFilter.SetKernelBandwidthUpdateFrequency() #(uint32_t KernelBandwidthUpdateFrequency 1 par defaut)
    DenoiseFilter_init.SetNoiseModel(3) #(NoiseModelType NoiseModel) #NoiseModelType { NOMODEL:0, GAUSSIAN:1, RICIAN:2,  POISSON:3}
    DenoiseFilter_init.SetNoiseModelFidelityWeight(0.05) #(double NoiseModelFidelityWeight entre 0 et 1)# This weight controls the balance between the smoothing and the closeness to the noisy data. 
    #DenoiseFilter.SetNoiseSigma(0.50) #(double NoiseSigma)#usualy 5% of min max of an image ##############pas d'influence  
    #DenoiseFilter.SetNumberOfIterations(1) #(uint32_t NumberOfIterations 1 par defaut)
    #DenoiseFilter.SetNumberOfSamplePatches(200) #(uint32_t NumberOfSamplePatches)#200->100, 41 a 23s mais filtre plus
    DenoiseFilter_init.SetPatchRadius(2) #(uint32_t PatchRadius) # 2->10s 4->41s 6->121s ##############paramétre critique
    #DenoiseFilter.SetSampleVariance(400) #(double SampleVariance) #pas d'influence?
    ImageDenoised_init=DenoiseFilter_init.Execute(image)
    timeRMR2 = time.time()
    TimeForrunFunctionRMR2 = timeRMR2 - timeRMR1
    print(u"La fonction de traitement intiale s'est executée en " + str(TimeForrunFunctionRMR2) +" secondes")
    timeRMR1 = time.time()
    DenoiseFilter=sitk.PatchBasedDenoisingImageFilter() #Execute (const Image &image1, double kernelBandwidthSigma, uint32_t patchRadius, 
    #uint32_t numberOfIterations, uint32_t numberOfSamplePatches, double sampleVariance, PatchBasedDenoisingImageFilter::NoiseModelType noiseModel, 
    #double noiseSigma, double noiseModelFidelityWeight, bool alwaysTreatComponentsAsEuclidean, bool kernelBandwidthEstimation, double kernelBandwidthMultiplicationFactor, 
    #uint32_t kernelBandwidthUpdateFrequency, double kernelBandwidthFractionPixelsForEstimation)
    DenoiseFilter.SetAlwaysTreatComponentsAsEuclidean(True)
    DenoiseFilter.SetKernelBandwidthEstimation(False)
    #DenoiseFilter.SetKernelBandwidthFractionPixelsForEstimation(0.5) #double KernelBandwidthFractionPixelsForEstimation
    #DenoiseFilter.SetKernelBandwidthMultiplicationFactor() #(double KernelBandwidthMultiplicationFactor)
    DenoiseFilter.SetKernelBandwidthSigma(DenoiseFilter_init.GetKernelBandwidthSigma()) #(double KernelBandwidthSigma)  #faible voire pas d'influence
    #DenoiseFilter.SetKernelBandwidthUpdateFrequency() #(uint32_t KernelBandwidthUpdateFrequency 1 par defaut)
    DenoiseFilter.SetNoiseModel(3) #(NoiseModelType NoiseModel) #NoiseModelType { NOMODEL:0, GAUSSIAN:1, RICIAN:2,  POISSON:3}
    DenoiseFilter.SetNoiseModelFidelityWeight(0.05) #(double NoiseModelFidelityWeight entre 0 et 1)# This weight controls the balance between the smoothing and the closeness to the noisy data. 
    DenoiseFilter.SetNoiseSigma(DenoiseFilter_init.GetNoiseSigma()) #(double NoiseSigma)#usualy 5% of min max of an image ##############pas d'influence  
    #DenoiseFilter.SetNumberOfIterations(1) #(uint32_t NumberOfIterations 1 par defaut)
    DenoiseFilter.SetNumberOfSamplePatches(DenoiseFilter_init.GetNumberOfSamplePatches()) #(uint32_t NumberOfSamplePatches)#200->100, 41 a 23s mais filtre plus
    DenoiseFilter.SetPatchRadius(DenoiseFilter_init.GetPatchRadius()*Shrinkfactor) #(uint32_t PatchRadius) # 2->10s 4->41s 6->121s ##############paramétre critique
    DenoiseFilter.SetSampleVariance(DenoiseFilter_init.GetSampleVariance()) #(double SampleVariance) #pas d'influence?
    ImageDenoised=DenoiseFilter.Execute(image)
    timeRMR2 = time.time()
    TimeForrunFunctionRMR2 = timeRMR2 - timeRMR1
    print(u"La fonction de traitement final s'est executée en " + str(TimeForrunFunctionRMR2) +" secondes")
    su.PushToSlicer(ImageDenoised,'ImageDenoisedbyPatchBasedDenoisingImageFilter')
def wavelet_denoising2(NomDeLImage, Nlevel):
    image=su.PullFromSlicer(NomDeLImage)
    NumpyImage=sitk.GetArrayFromImage(image)
    max_lev = 6       # how many levels of decomposition to draw
    coeffs = pywt.wavedecn(NumpyImage, 'db2', mode='zero', level=max_lev) #voir https://pywavelets.readthedocs.io/en/latest/ref/nd-dwt-and-idwt.html#pywt.wavedecn
    for levelR in range (max_lev-Nlevel):
        sigma = (1/0.6745) * maddest( coeffs[max_lev-levelR] )
        uthresh = sigma * np.sqrt( 2*np.log( len( NumpyImage ) ) )
        coeffs[(max_lev-levelR)] = ( pywt.threshold( i, value=uthresh, mode='hard' ) for i in coeffs[(max_lev-levelR)] )
    matrice_ondelette=pywt.waverecn(coeffs, 'db2', mode='per') #mode periodic ou zero
    image_ondelette=sitk.GetImageFromArray(matrice_ondelette)
    image_ondelette.SetSpacing(image.GetSpacing())
    image_ondelette.SetDirection(image.GetDirection())
    image_ondelette.SetOrigin(image.GetOrigin())
    su.PushToSlicer(image_ondelette,'image_DenoisWave_level0-'+str(Nlevel))
def custom_function(imageNode, imageNodeSavename, labelNode,
                    labelNodeSavename):
    imagesitk = su.PullFromSlicer(imageNode.GetName())
    labelsitk = su.PullFromSlicer(labelNode.GetName())

    labelarray = sitk.GetArrayFromImage(labelsitk)
    #min, max = squeeze(labelarray)

    #labelarraycrop = labelarray[ min[0]:max[0], min[1]:max[1], min[2]:max[2] ]:
    for slicez in labelarray:
        if slicez[slicez != 0].size > 0:
            nmin, nmax = squeeze(slicez[None, :, :])
            for rowind, row in enumerate(slicez[:nmax[1]]):
                if (rowind >= nmin[1] + 1) and (row[row != 0].size < 3):
                    prevrow = slicez[rowind - 1]
                    nextrow = slicez[rowind + 1]
                    if (nextrow[nextrow != 0].size > 2):
                        row = rowInterpolator(prevrow, nextrow, row)
                    elif (nextrow[nextrow != 0].size < 3):
                        newidx = rowind
                        while (newidx < (nmax[1])):
                            newidx += 1
                            finalrow = slicez[newidx]
                            if (finalrow[finalrow != 0].size > 2): break
                        slicez[rowind:newidx] = multiRowInterpolator(
                            prevrow, finalrow, slicez, rowind, newidx)

    newlabelsitk = sitk.GetImageFromArray(labelarray)
    newlabelsitk.SetOrigin(labelsitk.GetOrigin())
    newlabelsitk.SetSpacing(labelsitk.GetSpacing())
    newlabelsitk.SetDirection(labelsitk.GetDirection())

    newlabelnodename = labelNodeSavename.replace('.nrrd',
                                                 '') + '_interp_corrected'
    su.PushToSlicer(newlabelsitk, newlabelnodename)
    newlabelNode = slicer.util.getNode(newlabelnodename)

    newlabelNode.LabelMapOn()
    labelMapnodeDisplayNode = slicer.vtkMRMLScalarVolumeDisplayNode()
    slicer.mrmlScene.AddNode(labelMapnodeDisplayNode)
    newlabelNode.SetAndObserveDisplayNodeID(labelMapnodeDisplayNode.GetID())
    labelMapnodeDisplayNode.SetAndObserveColorNodeID(
        'vtkMRMLColorTableNodeFileGenericColors.txt')
    labelMapnodeDisplayNode.SetInputImageDataConnection(
        newlabelNode.GetImageDataConnection())
    labelMapnodeDisplayNode.UpdateImageDataPipeline()

    return imageNode, newlabelNode, newlabelnodename
    def runFindLiver2D(self, masterNode, labelNode):

        labelArray = slicer.util.array(labelNode.GetID())
        connectedArray = slicer.util.array(masterNode.GetID())

        global maskZ
        global centroidX
        global centroidY

        print('find liver 2D:', maskZ, centroidX, centroidY)
        # grow in 2d to everything connected to that point that is segmented

        #regionGrow2D(self, z,x,y, newLabel, eraseLabel, labelArray):
        tempArray = ParLib.Algorithms.connected2D(maskZ, centroidY, centroidX,
                                                  labelArray, connectedArray)
        tempImage = SimpleITK.GetImageFromArray(tempArray)
        sitkUtils.PushToSlicer(tempImage, 'liver')
def extractMaxZSlice(volumeNode, Zind):
    sitkVolumeNode = su.PullFromSlicer(volumeNode.GetName())

    pixelID = sitkVolumeNode.GetPixelIDValue()
    FlipYAxis = sitk.FlipImageFilter()
    FlipYAxis.SetFlipAxes([False, True, False])
    sizeZ = list(sitkVolumeNode.GetSize())
    sizeZ[2] = 0
    indexZ = [0, 0, Zind]
    ExtractorZ = sitk.ExtractImageFilter()
    ExtractorZ.SetSize(sizeZ)
    ExtractorZ.SetIndex(indexZ)

    sitkZSlice = ExtractorZ.Execute(sitkVolumeNode)
    ZSliceName = 'maxz_' + volumeNode.GetName()
    su.PushToSlicer(sitkZSlice, ZSliceName)
    ZSliceNode = slicer.util.getNode(ZSliceName)
    return ZSliceNode
 def creation_LabelAvecVolumeSphereConnu_OTSU(image, label_CT):
     mask_label = sitk.BinaryThreshold(
         label_CT, 1, 200, 1, 0)  #creer un masque sur toute les sphéres
     Otsu = sitk.OtsuThresholdImageFilter()
     labelOtsu = Otsu.Execute(
         image, mask_label, 0, 1, 64, True,
         1)  #otsu sur l'ensemble sde sphéres-> label value=1
     label_CT = sitk.Cast(label_CT, sitk.sitkUInt8)
     labelOtsu = sitk.Cast(labelOtsu, sitk.sitkUInt8)
     label_ideal = sitk.Multiply(
         label_CT, labelOtsu
     )  #multplie par label initiaux pour retrouver leur valeur
     label_ideal = sitk.Cast(
         label_ideal, sitk.sitkUInt8)  #transforme pour format de label
     print(
         "    creation_LabelAvecVolumeSphereConnu: recherche du seuil optimun:ok"
     )
     su.PushToSlicer(label_ideal, "label_ideal", 2)
     return label_ideal
Beispiel #21
0
    def test_LabelObjectStatisticsLogic(self):

        self.delayDisplay("Starting test_LabelObjectStatisticsLogic")

        import SampleData
        sampleDataLogic = SampleData.SampleDataLogic()
        mrHead = sampleDataLogic.downloadMRHead()

        img = sitkUtils.PullFromSlicer(mrHead.GetName())

        labelImg = sitk.OtsuMultipleThresholds(img, 3)

        labelNodeName = "OtsuMultipleThresholdLabelMap"
        sitkUtils.PushToSlicer(labelImg, "OtsuMultipleThresholdLabelMap", 2)

        mrHeadLabel = slicer.util.getNode(labelNodeName)

        logic = LabelObjectStatisticsLogic(mrHead, mrHeadLabel)
        print logic.keys
        print logic.labelStats

        logic.saveStats("test_LabelObjectStatisticsLogic.csv")
Beispiel #22
0
    def thresholdRangeScan(self, inputVolume1, threshold1, threshold2,
                           volumeName):
        #cast = sitk.CastImageFilter()

        inputVolumeName1 = inputVolume1.GetName()
        image1 = sitkUtils.PullFromSlicer(inputVolumeName1)

        #image1Cast = cast.Execute(image1)
        #inputVolumeName2 = inputVolume2.GetName()
        #image2 = sitkUtils.PullFromSlicer(inputVolumeName2)
        #image2Cast = cast.Execute(image2)

        thresholdFilter = sitk.ThresholdImageFilter()
        thresholdFilter.SetLower(threshold1)
        thresholdFilter.SetUpper(threshold2)
        thresholdFilter.SetOutsideValue(0)
        thresholdedImage = thresholdFilter.Execute(image1)
        sitkUtils.PushToSlicer(thresholdedImage, volumeName, True)

        thresholdedVolume = slicer.util.getNode(volumeName)

        return thresholdedVolume
    def runGradient(self, masterNode):

        global mean
        global std

        tempImage = sitkUtils.PullFromSlicer(masterNode.GetID())
        '''
    castIF = SimpleITK.CastImageFilter()
    castIF.SetOutputPixelType(SimpleITK.sitkFloat32)
    masterImage = castIF.Execute(tempImage)
    
    smoothIF = SimpleITK.GradientAnisotropicDiffusionImageFilter()
    spacing = masterImage.GetSpacing()
    min_spacing = numpy.min(numpy.array(spacing))
    smoothIF.SetTimeStep(min_spacing/(math.pow(2, 4)))
    smoothIF.SetNumberOfIterations(10)
    smoothIF.SetConductanceParameter(10)
    smoothImage = smoothIF.Execute(masterImage)

    sitkUtils.PushToSlicer(smoothImage, 'smoothImage')
    print('Done smoothing')
    '''

        smoothArray = SimpleITK.GetArrayFromImage(tempImage)
        gradientArray = SimpleITK.GetArrayFromImage(
            tempImage)  # duplicate to modify this one

        for j in range(1, smoothArray.shape[1] - 2):  # X
            for k in range(1, smoothArray.shape[2] - 2):  # Y
                gradientArray[:, j, k] = numpy.sum(numpy.sum(
                    numpy.abs(smoothArray[:, j - 2:j + 2, k - 2:k + 2] - mean),
                    axis=2),
                                                   axis=1) / 9

        gradientImage = SimpleITK.GetImageFromArray(gradientArray)
        sitkUtils.PushToSlicer(gradientImage, 'gradientImage')
        print('Done sergio gradient')
    def run(self, leftVol, rightVol, enableScreenshots=0):
        """
    Run the actual algorithm
    """
        logging.info('Processing started')

        nodeName = "BlankVolume"
        imageSize = [390, 466, 318]
        voxelType = vtk.VTK_UNSIGNED_CHAR
        imageOrigin = [98, 98, -72]
        imageSpacing = [0.5, 0.5, 0.5]
        imageDirections = [[-1, 0, 0], [0, -1, 0], [0, 0, 1]]
        fillVoxelValue = 255
        # Create an empty image volume, filled with fillVoxelValue
        imageData = vtk.vtkImageData()
        imageData.SetDimensions(imageSize)
        imageData.AllocateScalars(voxelType, 1)
        thresholder = vtk.vtkImageThreshold()
        thresholder.SetInputData(imageData)
        thresholder.SetInValue(fillVoxelValue)
        thresholder.SetOutValue(fillVoxelValue)
        thresholder.Update()
        # Create volume node
        blankVolumeNode = slicer.mrmlScene.AddNewNodeByClass(
            "vtkMRMLScalarVolumeNode", nodeName)
        blankVolumeNode.SetOrigin(imageOrigin)
        blankVolumeNode.SetSpacing(imageSpacing)
        blankVolumeNode.SetIJKToRASDirections(imageDirections)
        blankVolumeNode.SetAndObserveImageData(thresholder.GetOutput())
        blankVolumeNode.CreateDefaultDisplayNodes()
        blankVolumeNode.CreateDefaultStorageNode()
        logging.info('Created empty volume Blank Volume')

        # left right front back bottom top
        leftData = leftVol.GetPolyData().GetPoints().GetBounds()
        rightData = rightVol.GetPolyData().GetPoints().GetBounds()
        leftBound = leftData[0]
        rightBound = rightData[1]
        topBound = max(leftData[5], rightData[5])
        frontBound = min(leftData[2], rightData[2])
        backBound = max(leftData[3], rightData[3])
        midline = (leftBound + rightBound) / 2
        halfway = -(backBound + frontBound) / 1.7
        print(leftBound, rightBound)
        print("Midline:", midline)
        print(frontBound, backBound)
        print("Halfway:", halfway)
        print("Top:", topBound)

        # handleNode.SetAndObservePolyData(handle.GetOutput())
        # handleNode.CreateDefaultDisplayNodes()
        def makeHandle():
            fn = vtk.vtkParametricTorus()
            fn.SetRingRadius((rightBound - leftBound) / 5)
            fn.SetCrossSectionRadius((rightBound - leftBound) / 15)
            #vtk.FlipNormalsOn()
            source = vtk.vtkParametricFunctionSource()
            source.SetParametricFunction(fn)
            source.Update()

            trans = vtk.vtkTransform()
            trans.RotateX(90)
            trans.Translate(midline, topBound + 5, halfway)
            # vtk generate normals
            # communicate with SLACK
            rotate = vtk.vtkTransformPolyDataFilter()
            rotate.SetTransform(trans)
            rotate.SetInputConnection(source.GetOutputPort())
            rotate.Update()

            return rotate.GetOutput()

        handleVol = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelNode',
                                                       "handle")
        handle = makeHandle()
        handleVol.SetAndObservePolyData(handle)
        handleVol.CreateDefaultDisplayNodes()
        handleVol.CreateDefaultStorageNode()

        leftBLM = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLLabelMapVolumeNode', "leftBLM")
        # leftBLM.CreateDefaultDisplayNodes()
        # leftBLM.CreateDefaultStorageNode()

        rightBLM = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLLabelMapVolumeNode', "rightBLM")
        # rightBLM.CreateDefaultDisplayNodes()
        # rightBLM.CreateDefaultStorageNode()

        handleBLM = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLLabelMapVolumeNode', "handleBLM")
        # handleBLM.CreateDefaultDisplayNodes()
        # handleBLM.CreateDefaultStorageNode()

        leftParams = {
            'sampleDistance': 0.1,
            'InputVolume': blankVolumeNode.GetID(),
            'surface': leftVol.GetID(),
            'OutputVolume': leftBLM.GetID()
        }
        process = slicer.cli.run(slicer.modules.modeltolabelmap,
                                 None,
                                 leftParams,
                                 wait_for_completion=True)

        rightParams = {
            'sampleDistance': 0.1,
            'InputVolume': blankVolumeNode.GetID(),
            'surface': rightVol.GetID(),
            'OutputVolume': rightBLM.GetID()
        }
        process = slicer.cli.run(slicer.modules.modeltolabelmap,
                                 None,
                                 rightParams,
                                 wait_for_completion=True)

        # we have leftBLM, rightBLM, and handleBLM; all are binary label maps
        brainBLM = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLLabelMapVolumeNode', "brainBLM")
        # brainBLM.CreateDefaultDisplayNodes()
        # brainBLM.CreateDefaultStorageNode()

        path = slicer.util.tempDirectory("saves")
        leftPath = path + "/left.nrrd"
        rightPath = path + "/right.nrrd"

        slicer.util.saveNode(leftBLM, leftPath)
        slicer.util.saveNode(rightBLM, rightPath)

        left = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(leftBLM.GetName()))
        right = sitk.ReadImage(
            sitkUtils.GetSlicerITKReadWriteAddress(rightBLM.GetName()))

        orFilter = sitk.OrImageFilter()
        brain = orFilter.Execute(right, left)

        dilateFilter = sitk.BinaryDilateImageFilter()
        rad = round((rightBound - leftBound) / 30)
        dilateFilter.SetKernelRadius(rad)
        dilateFilter.SetBackgroundValue(0)
        dilateFilter.SetForegroundValue(255)
        print(dilateFilter.GetKernelType(), dilateFilter.GetKernelRadius())

        brain_dilated = dilateFilter.Execute(brain)

        holesFilter = sitk.BinaryFillholeImageFilter()
        brain_dilated_fixed = holesFilter.Execute(brain_dilated, True, 255)
        #output = orFilter.Execute(intermediate, handle)

        sitkUtils.PushToSlicer(brain_dilated_fixed,
                               "combined sides",
                               compositeView=0,
                               overwrite=False)
        slicer.mrmlScene.RemoveNode(leftBLM)
        slicer.mrmlScene.RemoveNode(rightBLM)
        slicer.mrmlScene.RemoveNode(handleBLM)
        slicer.mrmlScene.RemoveNode(brainBLM)
        slicer.mrmlScene.RemoveNode(blankVolumeNode)

        # Capture screenshot
        if enableScreenshots:
            self.takeScreenshot('MySlicerExtensionTest-Start', 'MyScreenshot',
                                -1)

        logging.info('Processing completed')

        return True
Beispiel #25
0
    def loadResults(self):
        # Remove transform from reference
        self.referenceVolumeNode.SetAndObserveTransformNodeID(None)

        # Load the result node
        if self.resultVolumeNode is not None:
            # Remove result node
            resultName = self.resultVolumeNode.GetName()
            slicer.mrmlScene.RemoveNode(self.resultVolumeNode)

            # Load the new one
            # When loading a 2D image with slicer.util, there is a bug that
            # keeps stacking the output result instead of creating a 2D image
            if self.logic.is2D(
                    self.referenceVolumeNode):  # load using SimpleITK
                resultImage = sitk.ReadImage(self.resPath)
                su.PushToSlicer(resultImage, resultName, overwrite=True)
                self.resultVolumeNode = slicer.util.getNode(resultName)
            else:  # load using slicer.util.loadVolume()
                self.resultVolumeNode = slicer.util.loadVolume(
                    self.resPath, returnNode=True)[1]
            self.resultVolumeNode.SetName(resultName)
            self.resultVolumeSelector.setCurrentNode(self.resultVolumeNode)
            fgVolume = self.resultVolumeNode

        # If a transform was given, copy the result in it and apply it to the floating image
        trsfType = self.getSelectedTransformationType()

        if self.resultTransformNode is not None:
            if trsfType != 'Non-linear':  # linear
                matrix = self.logic.readNiftyRegMatrix(
                    self.resultTransformPath)
                vtkMatrix = self.logic.getVTKMatrixFromNumpyMatrix(matrix)
                self.resultTransformNode.SetMatrixTransformFromParent(
                    vtkMatrix)
            else:  # non-linear
                # Remove result transform node from scene
                resultTransformName = self.resultTransformNode.GetName()
                slicer.mrmlScene.RemoveNode(self.resultTransformNode)

                # Load the generated transform node
                self.displacementFieldPath = self.resultTransformPath
                self.resultTransformNode = self.logic.vectorfieldToDisplacementField(
                    self.resultTransformPath, self.referenceVolumeNode,
                    self.displacementFieldPath)
                self.resultTransformNode.SetName(resultTransformName)
                self.resultTransformSelector.setCurrentNode(
                    self.resultTransformNode)

            # Apply transform to floating if no result volume node was selected
            if self.resultVolumeNode is None:
                self.floatingVolumeNode.SetAndObserveTransformNodeID(
                    self.resultTransformNode.GetID())
                fgVolume = self.floatingVolumeNode

        self.logic.setSlicesBackAndForeground(
            bgVolume=self.referenceVolumeNode,
            fgVolume=fgVolume,
            opacity=0.5,
            colors=True)

        self.logic.centerViews()
Beispiel #26
0
def main(argv):
    inputfile = ''
    outputfile = ''
    bitdepth = ''
    try:
        opts, args = getopt.getopt(argv, "b:hi:o:",
                                   ["bitdepth=", "ifile=", "ofile="])
    except getopt.GetoptError:
        print 'nhdr_create.py -i <inputfile> -o <outputfile> [-bitdpeth <sitkbitdepths>]'
        print 'see https://itk.org/SimpleITKDoxygen/html/namespaceitk_1_1simple.html#ae40bd64640f4014fba1a8a872ab4df98 for the bitdepth info'
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print 'test.py -i <inputfile> -o <outputfile>'
            sys.exit()
        elif opt in ("-i", "--ifile"):
            inputfile = arg
        elif opt in ("-o", "--ofile"):
            outputfile = arg
        elif opt in ("-b", "--bitdepth"):
            bitdepth = arg
            print 'bitdepth found"' + bitdepth + '"'

    infolder, inname = ntpath.split(inputfile)
    d_pos = inname.index('.')
    inname = inname[:d_pos]
    outfolder, outname = ntpath.split(outputfile)
    d_pos = outname.index('.')
    outname = outname[:d_pos]
    print 'Input file is "' + inputfile + '"'
    print 'Node Name is "' + inname + '"'
    print 'Output file is "' + outputfile + '"'
    if bitdepth:
        print 'Changing bitdepth output to "' + bitdepth + '"'

    loadVolume(inputfile)
    scene = slicer.mrmlScene
    volumes = scene.GetNodesByName(inname)
    vol = volumes.GetItemAsObject(volumes.GetNumberOfItems() - 1)
    vol.SetName(inname + 'in')
    inname = inname + 'in'
    outname = outname + '_out'
    #vol = volumes.GetItemAsObject(0)
    # Able to fix image intensity using scale image to right scale, then cast to 16bit.
    #vOut = slicer.modules.volumes.logic().CloneVolumeWithoutImageData(scene,vol,outname)

    #inputImage = sitkUtils.PullFromSlicer('MRHead')
    #filter = sitk.SignedMaurerDistanceMapImageFilter()
    #outputImage = filter.Execute(inputImage)
    #sitkUtils.PushToSlicer(outputImage,'outputImage')
    #from SimpleFilters import SimpleFiltersLogic

    #filter = SimpleFiltersLogic()
    #myFilter = sitk.RescaleIntensityImageFilter()
    #myFilter.SetDebug(False)
    #myFilter.SetNumberOfThreads(8)
    #myFilter.SetOutputMinimum(0.0)
    #myFilter.SetOutputMaximum(65535.0)
    #filter.run(myFilter, vOut, False, slicer.util.getNode(inname))
    #filter.main_queue_running
    #while filter.main_queue_running:
    #    sleep(0.5)
    scene = slicer.mrmlScene
    if not bitdepth:
        print "Not changing bitdepth."
        print "Getting vol from scene for save"
        volumes = scene.GetNodesByName(inname)
    else:
        print "Setting IM Max by bitdepth"
        if bitdepth == "UInt64":
            im_max = 4294967296
        elif bitdepth == "UInt32":
            im_max = 4294967296
        elif bitdepth == "UInt16":
            im_max = 65535
        elif bitdepth == "UInt8":
            im_max = 255
        elif bitdepth == "Int64":
            im_max = 2147483647
        elif bitdepth == "Int32":
            im_max = 2147483647
        elif bitdepth == "Int16":
            im_max = 32767
        elif bitdepth == "Int8":
            im_max = 128
        elif bitdepth == "LabelUInt64":
            im_max = 4294967296
        elif bitdepth == "LabelUInt32":
            im_max = 4294967296
        elif bitdepth == "LabelUInt16":
            im_max = 65535
        elif bitdepth == "LabelUInt8":
            im_max = 255
        else:
            raise NameError('UnsupportedBitDepthSpecified')

        print "Setting up rescale filter"
        myFilter = sitk.RescaleIntensityImageFilter()
        myFilter.SetDebug(False)
        myFilter.SetNumberOfThreads(8)
        # deprecated
        #in_im=sitkUtils.PullFromSlicer(inname)
        in_im = sitkUtils.PullVolumeFromSlicer(inname)

        print "execute rescale"
        out_im = myFilter.Execute(in_im, 0.0, im_max)
        print "Setting up cast filter"
        myFilter = sitk.CastImageFilter()
        myFilter.SetDebug(False)
        myFilter.SetNumberOfThreads(8)
        #sitk.sitkUInt16
        #eval('sitk.sitkUInt16')
        bt = 'sitk.sitk' + bitdepth
        print "Using bitdepth code " + bt + "(" + str(eval(bt)) + ")"
        myFilter.SetOutputPixelType(eval(bt))
        print "execute cast"
        out_im = myFilter.Execute(out_im)
        sitkUtils.PushToSlicer(out_im, outname)
        print "Getting vol from scene for save"
        volumes = scene.GetNodesByName(outname)

    #####
    # example code
    #histoMap =
    #slicer.modules.volumes.logic().CreateAndAddLabelVolume(self.histoVolumeBW,
    #                                                       'Histo_Final_Label_Map')
    #from SimpleFilters import SimpleFiltersLogic
    #filter = SimpleFiltersLogic()
    # subtractimagefilter has params, input input out.
    #filter.run(sitk.SubtractImageFilter(), histoMap, True,
    #           slicer.util.getNode('Histo_Label_Map'),
    #           slicer.util.getNode('Histo_Urethra_Label_Map'))
    #####
    vOut = volumes.GetItemAsObject(volumes.GetNumberOfItems() - 1)
    print "saving node " + outname
    saveNode(vOut, outputfile)
    def recalage(self, inputSelectorCTImage, inputSelectorMaskImg,
                 inputSelectorMRImage, OutputDirectory):
        time1 = time.time()

        ### Fonctions nécessaires pour fonction relacage ci-dessous ###
        def cropImagefctLabel(image, LowerBondingBox, UpperBondingBox):
            crop = sitk.CropImageFilter()
            image_cropper = crop.Execute(image, LowerBondingBox,
                                         UpperBondingBox)
            return image_cropper

        def recalagerigid_Euler3Dtransform(image_ref, image_mobile,
                                           ImageSamplingPercentage, MaskCT,
                                           MaskIRM):
            image_ref = sitk.Cast(
                image_ref, sitk.sitkFloat64)  #convertie l'image en float 64
            image_mobile = sitk.Cast(
                image_mobile, sitk.sitkFloat64)  #convertie l'image en float 64
            R = sitk.ImageRegistrationMethod()
            R.SetMetricAsMattesMutualInformation(64)  #nombre de bin
            R.SetMetricSamplingPercentage(
                float(ImageSamplingPercentage) / 100, sitk.sitkWallClock)
            R.SetMetricSamplingStrategy(R.RANDOM)
            R.SetOptimizerAsRegularStepGradientDescent(
                2.0, 0.01, 1500, 0.5
            )  #R.SetOptimizerAsRegularStepGradientDescent( maxStep, minStep,numberOfIterations,relaxationFactor );
            tx = sitk.CenteredTransformInitializer(image_ref, image_mobile,
                                                   sitk.Euler3DTransform())
            R.SetInitialTransform(tx)
            R.SetOptimizerScalesFromIndexShift()
            R.SetInterpolator(sitk.sitkLinear)
            R.SetMetricFixedMask(MaskCT)
            R.SetMetricMovingMask(MaskIRM)
            #R.AddCommand( sitk.sitkIterationEvent, lambda: command_iteration(R) )
            outTx = R.Execute(image_ref, image_mobile)
            InfMut = R.GetMetricValue()
            print(outTx)
            print("    Recalagerigid_Euler3Dtransform: transformation ok")
            return outTx

        def reechantillonage(image_ref, image_mobile, tranformation):
            resampler = sitk.ResampleImageFilter()
            resampler.SetReferenceImage(image_ref)
            resampler.SetInterpolator(sitk.sitkLinear)
            resampler.SetDefaultPixelValue(0)
            resampler.SetTransform(tranformation)
            ImageRecaler = resampler.Execute(image_mobile)
            return ImageRecaler

        def dilate(image):
            dilateFilter = sitk.BinaryDilateImageFilter()
            dilateFilter.SetKernelRadius(20)
            image_dilated = dilateFilter.Execute(image)
            return image_dilated

        def separate_label(label_template):
            Connected = sitk.ConnectedComponentImageFilter()
            connectedlabel = Connected.Execute(label_template, True)
            Relabel = sitk.RelabelComponentImageFilter()
            connectedlabel = Relabel.Execute(connectedlabel, 10,
                                             True)  # trie par taille
            #su.PushToSlicer(connectedlabel, "connectedlabel", 2)
            return connectedlabel

        def multires_registration(fixed_image, moving_image, initial_transform,
                                  ImageSamplingPercentage):
            registration_method = sitk.ImageRegistrationMethod()
            registration_method.SetMetricAsMattesMutualInformation(
                numberOfHistogramBins=50)
            registration_method.SetMetricSamplingStrategy(
                registration_method.RANDOM)
            registration_method.SetMetricSamplingPercentage(
                float(ImageSamplingPercentage) / 100)
            registration_method.SetInterpolator(sitk.sitkLinear)
            registration_method.SetOptimizerAsGradientDescent(
                learningRate=1.0,
                numberOfIterations=100,
                estimateLearningRate=registration_method.EachIteration)  #Once
            registration_method.SetOptimizerScalesFromPhysicalShift()
            registration_method.SetInitialTransform(initial_transform)
            registration_method.SetShrinkFactorsPerLevel(
                shrinkFactors=[4, 2, 1])
            registration_method.SetSmoothingSigmasPerLevel(
                smoothingSigmas=[2, 1, 0])
            registration_method.SmoothingSigmasAreSpecifiedInPhysicalUnitsOn()

            final_transform = registration_method.Execute(
                fixed_image, moving_image)
            print('Final metric value: {0}'.format(
                registration_method.GetMetricValue()))
            print('Optimizer\'s stopping condition, {0}'.format(
                registration_method.GetOptimizerStopConditionDescription()))
            return final_transform

        ###### Récupération des images et dossier de sauvegarde sélectionnés par l'utilisateur ####
        print("Début de la fonction recalage")
        nom_image = inputSelectorMRImage
        nom_image_ref = inputSelectorCTImage
        nom_template = inputSelectorMaskImg

        ######################importer les images##################
        image_IRM = su.PullVolumeFromSlicer(nom_image)
        image_CT = su.PullVolumeFromSlicer(nom_image_ref)
        label_CT = su.PullVolumeFromSlicer(nom_template)  #dans l'espace CT
        #label_CT_dilated=su.PullVolumeFromSlicer(nom_template2)
        #image_ideal= sitk.Cast(image_ideal, sitk.sitkFloat64) #convertie l'image en float 64
        #print time.ctime()
        print("Importation:ok")
        ###########################vrecalage en 3 étape##################
        image_CT = sitk.Cast(image_CT, sitk.sitkFloat64)
        image_IRM = sitk.Cast(image_IRM, sitk.sitkFloat64)
        ####################recalage primaire de la sommes des moments des images###########
        initial_transform = sitk.CenteredTransformInitializer(
            image_CT, image_IRM, sitk.Euler3DTransform(),
            sitk.CenteredTransformInitializerFilter.MOMENTS)
        #####################recalage multiresolution rigide des images #################################
        medium_transform = multires_registration(image_CT, image_IRM,
                                                 initial_transform, 5)
        #############################recalage multiresolution du centre du phantome moins soumis aux distortions geom#######################
        ####crop sur les 5 plus grosse sphéres#######################
        mask_label = sitk.BinaryThreshold(
            label_CT, 250, 254, 1,
            0)  #creer un masque sur les 5 plus grosse spheres
        stats = sitk.LabelIntensityStatisticsImageFilter()
        stats.Execute(mask_label, image_CT)
        delta = 10  #additionnal voxel to crop volume to avoid border problem
        LowerBondingBox = [
            stats.GetBoundingBox(1)[0] - delta,
            stats.GetBoundingBox(1)[1] - delta,
            stats.GetBoundingBox(1)[2] - delta
        ]
        UpperBondingBox = [
            image_CT.GetSize()[0] -
            (stats.GetBoundingBox(1)[0] + stats.GetBoundingBox(1)[3] + delta),
            image_CT.GetSize()[1] -
            (stats.GetBoundingBox(1)[1] + stats.GetBoundingBox(1)[4] + delta),
            image_CT.GetSize()[2] -
            (stats.GetBoundingBox(1)[2] + stats.GetBoundingBox(1)[5] + delta)
        ]
        image_CT_crop = cropImagefctLabel(image_CT, LowerBondingBox,
                                          UpperBondingBox)
        final_transform = multires_registration(image_CT_crop, image_IRM,
                                                medium_transform, 20)
        ##################reechantillonage############
        image_IRM_reg = reechantillonage(image_CT, image_IRM, final_transform)
        su.PushToSlicer(image_IRM_reg, "verif_image_IRMrecaler", 1)

        time2 = time.time()
        TimeForrunFunction = time2 - time1
        print("\n")
        print(u"La fonction recalage s'est bien executée (temps = " +
              str(TimeForrunFunction) + " secondes)")
Beispiel #28
0
    def test_SimpleITK_SlicerPushPull_Deprecated(self):

        """ Test with deprecated API to ensure backward compatibility """

        """ Download the MRHead node
        """
        import SampleData
        SampleData.downloadSample("MRHead")
        volumeNode1 = slicer.util.getNode('MRHead')
        self.assertEqual(volumeNode1.GetName(), "MRHead")

        """ Verify that pulling SimpleITK image from Slicer and then pushing it
        back creates an identical volume.
        """

        sitkimage = su.PullFromSlicer(volumeNode1.GetName())
        self.assertIsNotNone(sitkimage)

        su.PushToSlicer(sitkimage, 'MRHead', compositeView=0, overwrite=False)
        volumeNode1Copy = slicer.util.getNode('MRHead_1')

        """ Verify that image is not overwritten but a new one is created """
        self.assertEqual(volumeNode1, slicer.util.getNode('MRHead'),
                         'Original volume is changed')
        self.assertNotEqual(volumeNode1, volumeNode1Copy,
                         'Copy of original volume is not created')

        """ Few modification of the image : Direction, Origin """
        sitkimage.SetDirection((-1.0, 1.0, 0.0, 0.0, -1.0, 1.0, 1.0, 0.0, 1.0))
        sitkimage.SetOrigin((100.0, 100.0, 100.0))

        """ Few pixel changed """
        size = sitkimage.GetSize()
        for x in xrange(0,size[0],(int)(size[0]/10)):
            for y in xrange(0,size[1],(int)(size[1]/10)):
                for z in xrange(0,size[2],(int)(size[2]/10)):
                    sitkimage.SetPixel(x,y,z,0L)


        su.PushToSlicer(sitkimage, 'ImageChanged', compositeView=0, overwrite=False)
        volumeNode1Modified = slicer.util.getNode('ImageChanged')
        self.assertNotEqual(volumeNode1.GetMTime(), volumeNode1Modified.GetMTime(),
                            'Error Push Pull: Modify Time are the same')

        """ Test the consistency between sitkimage and volumeNode1Modified
        """
        tmp = volumeNode1Modified.GetOrigin()
        valToCompare = (-tmp[0], -tmp[1], tmp[2])
        self.assertEqual(valToCompare,sitkimage.GetOrigin(),
                         'Modified origin mismatch')

        """ Test push with all parameter combinations """
        for compositeView in xrange(3): # background, foreground, label
            for overwrite in [False, True]:
                su.PushToSlicer(sitkimage, 'volumeNode'+str(compositeView)+str(overwrite),
                                compositeView, overwrite)
                volumeNode = slicer.util.getNode('volumeNode'+str(compositeView)+str(overwrite))

                print("compositeView : %s" %compositeView )
                print("overwrite : %s " %overwrite )

                #Check if it's a label
                if compositeView == 2:
                    self.assertEqual(volumeNode.GetClassName(),'vtkMRMLLabelMapVolumeNode',
                                     'Error Push Pull: Not a label Class Name')
                else:
                    self.assertEqual(volumeNode.GetClassName(), 'vtkMRMLScalarVolumeNode',
                                     'Error Push Pull: Not a back/foreground Class Name')

        slicer.mrmlScene.Clear(0)
 def pushArrayToSlicer(self, array, nodeName='ArrayPushedFromCode', compositeView=0, overWrite=False):
   sitkImage = sitk.GetImageFromArray(array)
   sitkUtils.PushToSlicer(sitkImage, nodeName, compositeView, overWrite)
Beispiel #30
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