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
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)
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
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")
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
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()
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)")
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)
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