Utilisation élémentaire d'ITK apprise avec Python

Notification

J'ai écrit cet article comme mémo de mon étude. La source de référence est ce cahier. https://github.com/KitwareMedical/2019-03-13-KRSCourseInBiomedicalImageAnalysisAndVisualization

ITK Une bibliothèque indispensable pour le traitement d'images dans le domaine biomédical, spécialisée dans la technologie de visualisation d'images. Il est utilisé dans Slicer et ImageJ.

environnement

Google Colab (Lancez n'importe quel notebook.)

Exemple de données

Commencez par télécharger les exemples de données depuis GitHub à l'aide de subversion.

!sudo apt install subversion
#Obtenez les données
#Inclus dans l'URL Github/tree/Maître/Remplacer par le coffre
!svn checkout https://github.com/KitwareMedical/2019-03-13-KRSCourseInBiomedicalImageAnalysisAndVisualization/trunk/data

Installation ITK

#Installez ITK
!pip install itk

Image Filtering

Quoi apprendre ici

Le terme filtre est largement utilisé dans trois types:

Il existe trois types de régions d'image dans ITK.

--BufferedRegion: zone de pixels stockée en mémoire --LargestPossibleRegion: Zone maximale possible de l'image --RequestedRegion: Région demandée par un seul chemin de traitement pendant le streaming (BufferedRegion et LargestPossibleRegion sont identiques ou plus grands que RequestedRegion)

Essayer.

import numpy as np
import itk
import matplotlib.pyplot as plt

#Pratiquez le filtrage spatial avec Pacman
fileName = 'data/PacMan.png'
reader = itk.ImageFileReader.New(FileName=fileName)
#Essayez d'utiliser un filtre gaussien
smoother = itk.RecursiveGaussianImageFilter.New(Input=reader.GetOutput())

print("reader's Output: %s" % reader.GetOutput())
print("smoother's Output: %s" % smoother.GetOutput())

#Mettre à jour pour générer des résultats de traitement()N'oublie pas.
smoother.Update()

print("reader's Output: %s" % reader.GetOutput())
print("smoother's Output: %s" % smoother.GetOutput())

image = reader.GetOutput()#Confirmation de l'original
plt.subplot(1,2,1),plt.title("original"),plt.imshow(itk.GetArrayFromImage(image))
smoothed = smoother.GetOutput()#Après le lissage
plt.subplot(1,2,2),plt.title("smoothing"),plt.imshow(itk.GetArrayFromImage(smoothed))

filtering1.png

Si vous avez mis à jour avec un objet pipeline (bien que vous l'ayez déjà fait), le résultat du traitement sera le dernier

smoother.Update()
#Cependant, si vous modifiez le processus, vous devez à nouveau mettre à jour.
smoother.SetSigma(10.0)
smoother.Update()
plt.imshow(itk.GetArrayFromImage(smoothed))

filtering2.png

De plus, je ne pense pas qu'il y en ait beaucoup, mais si vous apportez des modifications au lecteur au milieu, n'oubliez pas de mettre à jour le lecteur.

# reader.Modified()
#Vous pouvez essayer différents filtres.
# https://itk.org/Doxygen/html/group__IntensityImageFilters.html
fileName = 'data/PacMan.png'
reader = itk.ImageFileReader.New(FileName=fileName)
smoother = itk.MedianImageFilter.New(Input=reader.GetOutput())#Par exemple, médiane
smoother.SetRadius(5)
smoother.Update()
plt.imshow(itk.GetArrayFromImage(smoother.GetOutput()))

filtering3.png

Supplément

#Placez StreamingImageFilter à la fin du pipeline pour diffuser le pipeline.
#Smoother génère une sortie plusieurs fois pour chaque division de diffusion en continu de la zone d'image.
#Le lecteur ne peut pas être diffusé, donc la sortie n'est générée qu'une seule fois.
streamer = itk.StreamingImageFilter.New(Input=smoother.GetOutput())
streamer.SetNumberOfStreamDivisions(4)
reader.Modified()
streamer.Update()
#Il vous suffit de spécifier l'écriture avec l'extension
writer = itk.ImageFileWriter.New(Input=smoother.GetOutput())
writer.SetFileName('my_output.mha')
writer.SetNumberOfStreamDivisions(4)
writer.Update()

Image Segmentation

Quoi apprendre ici

Types de segmentation disponibles dans ITK

Ici, nous allons présenter un exemple de traitement pour Region Growing et Level Set.

Region growing

L'approche de base de l'algorithme d'expansion de région consiste à démarrer l'expansion à partir de la région de départ (généralement un ou plusieurs pixels) qui est considérée comme étant à l'intérieur de l'objet segmenté. Les pixels adjacents à cette zone d'objet segmentée sont évalués pour déterminer s'ils doivent être considérés comme faisant partie de l'objet. S'ils sont segmentés, ils sont ajoutés à la zone et le processus se poursuit tant que de nouveaux pixels sont ajoutés à la zone. L'algorithme d'expansion de région est le critère utilisé pour déterminer si une région contient des pixels, le type de connexion utilisé pour déterminer les voisins et le processus (ou processus) utilisé pour rechercher les pixels voisins. Stratégie) dépend de.

Ici, la méthode suivante est utilisée comme exemple.

Tout d'abord, vérifiez comment utiliser "Confidence Connected". ConfidenceConnected est une méthode permettant de déterminer les limites supérieure et inférieure de la limite de la zone, de trouver l'écart type par rapport aux valeurs entre elles et de définir la plage autorisée de cet écart type (comme l'effet de levier. SD * Multiplicateur).

# BrainProtonDensitySlice.Utiliser png
# 'unsigned char'La raison du chargement avec est d'afficher la méthode de conversion de données plus tard.
input_image = itk.imread('data/BrainProtonDensitySlice.png', itk.ctype('unsigned char'))
# View the input image
plt.imshow(itk.GetArrayFromImage(input_image))

せぐ1.png

Vérifiez comment utiliser la classe "ConfidenceConnectedImageFilter". Si vous ne savez pas comment l'utiliser, recherchez-le.

confidence_connected = itk.ConfidenceConnectedImageFilter.New(input_image)
#Vérifiez comment utiliser en utilisant la fonction d'aide de python
help(confidence_connected)
#Définir arbitrairement le paramètre de filtre connecté à la confiance
confidence_connected.SetMultiplier(2.3)#Tolérance, ± SD dans cet exemple*2.3
confidence_connected.SetNumberOfIterations(5)
confidence_connected.SetInitialNeighborhoodRadius(3)
confidence_connected.SetReplaceValue(255)

Si vous ne savez pas comment utiliser une fonction, recherchez-la.

# *Multiplier*?
confidence_connected.SetMultiplier?

Définissez le point de départ "point de départ" de l'expansion de la zone. Notez que l'origine de l'objet ITK Image se trouve en bas à gauche des coordonnées de l'image. (NumPy est en haut à gauche)

# Set the seed points
confidence_connected.SetSeed([100, 110])
#Exécuter et visualiser
confidence_connected.Update()
plt.imshow(itk.GetArrayFromImage(confidence_connected))

セグ2.png

#Essayez d'améliorer le résultat du traitement. Appliquez un filtre médian à l'image d'origine.
median_filtered_image = itk.median_image_filter(input_image, radius=1)
#Mettez à nouveau les paramètres à jour. Entrez l'image après le filtre médian.
confidence_connected_image = itk.confidence_connected_image_filter(median_filtered_image,
                                                                   seed=[100,110],
                                                                   replace_value=255,
                                                                   multiplier=3.0,
                                                                   number_of_iterations=5,
                                                                   initial_neighborhood_radius=3)
plt.imshow(itk.GetArrayFromImage(confidence_connected_image))

せぐ3.png

Ensuite, comparons les trois processus lumineux de la région. ConnectedThresholdImageFilter vs ConfidenceConnectedmageFilter vs IsolatedConnectedImageFilter

# ConnectedThresholdImageFilter vs ConfidenceConnectedmageFilter vs IsolatedConnectedImageFilter
input_image = itk.imread('data/BrainProtonDensitySlice.png', itk.ctype('unsigned char'))
connected_threshold = itk.ConnectedThresholdImageFilter.New(input_image)
connected_threshold.SetLower(190)
connected_threshold.SetUpper(255)
connected_threshold.SetReplaceValue( 255 )
connected_threshold.SetSeed( [100, 110] );
connected_threshold.Update()

confidence_connected = itk.ConfidenceConnectedImageFilter.New(input_image)
confidence_connected.SetMultiplier(2.3)
confidence_connected.SetSeed( [100, 110] );
confidence_connected.AddSeed( [80, 126] );
confidence_connected.SetNumberOfIterations(5)
confidence_connected.SetInitialNeighborhoodRadius(3)
confidence_connected.SetReplaceValue(255)
confidence_connected.Update()

isolated_connected = itk.IsolatedConnectedImageFilter.New(input_image)
isolated_connected.SetSeed1([98, 112])
isolated_connected.SetSeed2([98, 136])
isolated_connected.SetUpperValueLimit( 245 )
isolated_connected.FindUpperThresholdOff();
isolated_connected.Update()

plt.subplot(131)
plt.title("ConnectedThreshold")
plt.imshow(itk.GetArrayFromImage(connected_threshold))
plt.subplot(132)
plt.title("ConfidenceConnected")
plt.imshow(itk.GetArrayFromImage(confidence_connected))
plt.subplot(133)
plt.title("IsolatedConnected")
plt.imshow(itk.GetArrayFromImage(isolated_connected))
plt.tight_layout()
plt.show()

segu1.png

Fast Marching Segmentation(LevelSet) Ensuite, essayez la segmentation Fast Marching de la méthode LevelSet. Si la zone cible de segmentation est une structure simple, un algorithme d'expansion rapide appelé marche rapide peut être utilisé. Simplifiez l'image avec un filtre spatial avant d'essayer.

#Découvrez les types de données d'image que le filtre de lissage peut gérer
itk.CurvatureAnisotropicDiffusionImageFilter.GetTypes()

#Comment convertir des données d'image dans un type de données pris en charge
Dimension = input_image.GetImageDimension()
FloatImageType = itk.Image[itk.ctype('float'), Dimension]
caster = itk.CastImageFilter[input_image, FloatImageType].New()
caster.SetInput(input_image)

#Appliquez un filtre lissant.
smoothed_image = itk.curvature_anisotropic_diffusion_image_filter(caster, 
                                                                  time_step=0.125, 
                                                                  number_of_iterations=5,
                                                                  conductance_parameter=3.0)

plt.imshow(itk.GetArrayFromImage(smoothed_image))

せぐ4.png

#Exécuter le filtre de détection de bord tel quel
gradient = itk.gradient_magnitude_recursive_gaussian_image_filter(smoothed_image, sigma=1.0)
plt.imshow(itk.GetArrayFromImage(gradient))

せぐ5.png

#Continuer à exécuter le filtre sigmoïde

basin_minimum = 2.25
border_minimum = 3.75

alpha = - (border_minimum - basin_minimum) / 3.0
beta = (border_minimum + basin_minimum) / 2.0

sigmoid = itk.sigmoid_image_filter(gradient, output_minimum=0.0, output_maximum=1.0, alpha=alpha, beta=beta)
plt.imshow(itk.GetArrayFromImage(sigmoid))

せぐ66.png

#Marche à grande vitesse
fast_marching = itk.FastMarchingImageFilter.New(sigmoid)

seed_value = 0.0
NodeType = itk.LevelSetNode[itk.ctype('float'), Dimension]
node = NodeType()
node.SetIndex([100,110])
node.SetValue(seed_value)

NodeContainerType = itk.VectorContainer[itk.ctype('unsigned int'), NodeType]
nodes = NodeContainerType.New()
nodes.Initialize()
nodes.InsertElement(0, node)

fast_marching_image = itk.fast_marching_image_filter(sigmoid, trial_points=nodes, stopping_value=80)
plt.imshow(itk.GetArrayFromImage(fast_marching_image))

segu7.png

Binarisez l'image.

time_threshold = 100 #Définir le seuil
thresholded_image = itk.binary_threshold_image_filter(fast_marching_image,
                                                      lower_threshold = 0,
                                                      upper_threshold=time_threshold,
                                                      outside_value=0,
                                                      inside_value=255)
plt.imshow(itk.GetArrayFromImage(thresholded_image))

segu8.png

À partir de là, essayez le jeu de niveaux de détection de forme. La vitesse de traitement est améliorée, mais la courbure n'est pas bonne. Le pipeline ressemble à ceci: shape-detection-pipeline.png

Commencez par créer une image équilibrée dans la partie inférieure de la figure.

#L'image binaire est la matière blanche.Utiliser png
binary_mask = itk.imread('data/WhiteMatter.png', itk.ctype('float'))

smoothed_image = itk.smoothing_recursive_gaussian_image_filter(binary_mask)

#Traitement des gradations
rescaler = itk.IntensityWindowingImageFilter[FloatImageType,FloatImageType].New(smoothed_image)
rescaler.SetWindowMinimum(0)
rescaler.SetWindowMaximum(255)
#Inverser le niveau d'entrée pour avoir une valeur négative en interne
rescaler.SetOutputMinimum(5.0)
rescaler.SetOutputMaximum(-5.0)

rescaler.Update()
plt.imshow(itk.GetArrayFromImage(rescaler))

segu9.png

Ensuite, créez l'image de fonction dans la figure.

#Pré-traiter en utilisant l'image chargée dans la procédure ci-dessus
gradient = itk.gradient_magnitude_recursive_gaussian_image_filter(caster, sigma=1.0)

basin_minimum = 1
border_minimum = 5.0

alpha = - (border_minimum - basin_minimum) / 3.0
beta = (border_minimum + basin_minimum) / 2.0

#Image caractéristique dans la figure
sigmoid = itk.sigmoid_image_filter(gradient, output_minimum=0.0, output_maximum=1.0, alpha=alpha, beta=beta)
plt.imshow(itk.GetArrayFromImage(sigmoid))

segu11.png

#shape_detection_level_Exécuter le traitement de l'ensemble
shape_detection_image = itk.shape_detection_level_set_image_filter(rescaler,
                                                                   feature_image=sigmoid,
                                                                   maximum_r_m_s_error=0.001,
                                                                   number_of_iterations=100,
                                                                   propagation_scaling=1.0,
                                                                   curvature_scaling=2.0)
#Binarisation
thresholded_image = itk.binary_threshold_image_filter(shape_detection_image,
                                                      lower_threshold=-1e7,
                                                      # Cut at the zero set
                                                      upper_threshold=0.0,
                                                      outside_value=0,
                                                      inside_value=255)
plt.imshow(itk.GetArrayFromImage(thresholded_image))

segu12.png

Introduisons quelques paramètres liés aux conditions de courbure et de propagation du jeu de niveaux dans le jeu de niveaux de détection de forme. Min Basin Min Boundary Propagation Scaling Curvature Scaling Number of Iterations

def explore_shape_detection_image_parameters(basin_minimum, boundary_minimum, propagation_scaling,
                                             curvature_scaling, number_of_iterations):

    input_image = itk.imread('data/BrainProtonDensitySlice.png', itk.ctype('unsigned char'))

    # Prepare the initial level set image
    binary_mask = itk.imread('data/WhiteMatter.png', itk.ctype('float'))

    smoothed_image = itk.smoothing_recursive_gaussian_image_filter(binary_mask)

    Dimension = input_image.GetImageDimension()
    FloatImageType = itk.Image[itk.ctype('float'), Dimension]
    caster = itk.CastImageFilter[input_image, FloatImageType].New()
    caster.SetInput(input_image)

    # Prepare the speed image
    gradient = itk.gradient_magnitude_recursive_gaussian_image_filter(caster, sigma=1.0)

    alpha = - (boundary_minimum - basin_minimum) / 3.0
    beta = (boundary_minimum + basin_minimum) / 2.0

    sigmoid = itk.sigmoid_image_filter(gradient, output_minimum=0.0, output_maximum=1.0, alpha=alpha, beta=beta)

    rescaler = itk.IntensityWindowingImageFilter[FloatImageType,FloatImageType].New(smoothed_image)
    rescaler.SetWindowMinimum(0)
    rescaler.SetWindowMaximum(255)
    # Invert the input level set to have negative values inside
    rescaler.SetOutputMinimum(5.0)
    rescaler.SetOutputMaximum(-5.0)

    rescaler.Update()
    
    shape_detection_image = itk.shape_detection_level_set_image_filter(rescaler,
                                                                       feature_image=sigmoid,
                                                                       maximum_r_m_s_error=0.001,
                                                                       number_of_iterations=number_of_iterations,
                                                                       propagation_scaling=propagation_scaling,
                                                                       curvature_scaling=curvature_scaling)

    thresholded_image = itk.binary_threshold_image_filter(shape_detection_image,
                                                          lower_threshold=-1e7,
                                                          # Cut at the zero set
                                                          upper_threshold=0.0,
                                                          outside_value=0,
                                                          inside_value=255)
    plt.imshow(itk.GetArrayFromImage(thresholded_image))
    plt.title(str(basin_minimum)+"-"+str(boundary_minimum)+"-"+str(propagation_scaling)+"-"+str(curvature_scaling)+"-"+str(number_of_iterations))
    plt.show()
    return

explore_shape_detection_image_parameters(basin_minimum=1, boundary_minimum=5., 
                                         propagation_scaling=1., curvature_scaling=2., number_of_iterations=100)
explore_shape_detection_image_parameters(basin_minimum=1, boundary_minimum=5., 
                                         propagation_scaling=1., curvature_scaling=2., number_of_iterations=500)
explore_shape_detection_image_parameters(basin_minimum=1, boundary_minimum=5., 
                                         propagation_scaling=1., curvature_scaling=4., number_of_iterations=100)
explore_shape_detection_image_parameters(basin_minimum=1, boundary_minimum=20., 
                                         propagation_scaling=1., curvature_scaling=1., number_of_iterations=100)

segu14.png segu15.png segu16.png segu17.png

Image Registration

Quoi apprendre ici

#Les données cibles sont-elles calibrées dans le même espace géométrique avant l'alignement? Si vous avez besoin d'un rééchantillonnage, faites-le.
#Je me demande si je vais le faire avec un échantillon IJ. travail futur
# https://imagej.nih.gov/ij/images/
# https://imagej.nih.gov/ij/images/pet-series/
# https://imagej.nih.gov/ij/images/ct-scan.zip
#Charger les données à utiliser (image de référence)
PixelType = itk.ctype('float')
fixedImage = itk.imread('data/BrainProtonDensitySliceBorder20.png', PixelType)
plt.imshow(itk.array_view_from_image(fixedImage))

regi1.png

#Image déplacée
movingImage = itk.imread('data/BrainProtonDensitySliceShifted13x17y.png', PixelType)
plt.imshow(itk.array_view_from_image(movingImage))

regi2.png

#Rassemblez les informations nécessaires à la conversion
#Nombre de dimensions
Dimension = fixedImage.GetImageDimension()
#Type d'image
FixedImageType = type(fixedImage)
MovingImageType = type(movingImage)
#Type de données à convertir
TransformType = itk.TranslationTransform[itk.D, Dimension]
#Initialisation de la soucoupe
initialTransform = TransformType.New()
#Définissez une fonction qui optimise pour minimiser les erreurs d'alignement
optimizer = itk.RegularStepGradientDescentOptimizerv4.New(
        LearningRate=4,
        MinimumStepLength=0.001,
        RelaxationFactor=0.5,
        NumberOfIterations=200)
#Définir l'algorithme d'alignement (erreur quadratique moyenne)
metric = itk.MeanSquaresImageToImageMetricv4[
    FixedImageType, MovingImageType].New()
#Initialiser l'objet d'alignement
registration = itk.ImageRegistrationMethodv4.New(FixedImage=fixedImage,
        MovingImage=movingImage,
        Metric=metric,
        Optimizer=optimizer,
        InitialTransform=initialTransform)
#Paramètres d'alignement
#Type de conversion d'image en mouvement
movingInitialTransform = TransformType.New()
initialParameters = movingInitialTransform.GetParameters()
initialParameters[0] = 0 #x
initialParameters[1] = 0 #y
movingInitialTransform.SetParameters(initialParameters)
registration.SetMovingInitialTransform(movingInitialTransform)
#Type de conversion des critères
identityTransform = TransformType.New()
identityTransform.SetIdentity()
registration.SetFixedInitialTransform(identityTransform)

registration.SetNumberOfLevels(1) # number of multi-resolution levels
registration.SetSmoothingSigmasPerLevel([0]) #Niveau de lissage
registration.SetShrinkFactorsPerLevel([1]) #Niveau de rétrécissement
#Mettez à jour les paramètres d'alignement et confirmez
registration.Update()
#Obtenez le résultat du processus de conversion
transform = registration.GetTransform()
finalParameters = transform.GetParameters()
#Distance de déplacement
translationAlongX = finalParameters.GetElement(0)
translationAlongY = finalParameters.GetElement(1)
#Nombre de répétitions
numberOfIterations = optimizer.GetCurrentIteration()
#Précision de la méthode (plus petite est meilleure)
bestValue = optimizer.GetValue()

print("Result = ")
print(" Translation X = " + str(translationAlongX))
print(" Translation Y = " + str(translationAlongY))
print(" Iterations    = " + str(numberOfIterations))
print(" Metric value  = " + str(bestValue))

#Composition d'image
CompositeTransformType = itk.CompositeTransform[itk.D, Dimension]
outputCompositeTransform = CompositeTransformType.New()
outputCompositeTransform.AddTransform(movingInitialTransform)
outputCompositeTransform.AddTransform(registration.GetModifiableTransform())
#Rééchantillonnage
resampler = itk.ResampleImageFilter.New(Input=movingImage,
        Transform=outputCompositeTransform,
        UseReferenceImage=True,
        ReferenceImage=fixedImage)
#Affichage des résultats
resampler.SetDefaultPixelValue(100)

OutputPixelType = itk.ctype('unsigned char')
OutputImageType = itk.Image[OutputPixelType, Dimension]

resampler.Update()

result = resampler.GetOutput()
plt.subplot(1,2,1)
plt.title("registered")
plt.imshow(itk.array_view_from_image(result))
plt.subplot(1,2,2)
plt.title("moving_org")
plt.imshow(itk.array_view_from_image(movingImage))

regi3.png

Voyons le désalignement par la différence

difference = itk.SubtractImageFilter.New(Input1=fixedImage,
        Input2=resampler)
resampler.SetDefaultPixelValue(1)

difference.Update()
plt.title("difference")
plt.imshow(itk.array_view_from_image(difference.GetOutput()))

regi4.png

#Mauvais alignement avant et après l'enregistrement
resampler.SetTransform(identityTransform)
difference.Update()
plt.imshow(itk.array_view_from_image(difference.GetOutput()))

regi5.png

Ensuite, différents types d'images (multimodales) sont alignés. Mattes MutualInformation, qui est souvent utilisé pour l'alignement dans les cas multimodaux, est utilisé. Utilisez une transformation rigide.

#Image de référence
t1_image = itk.imread('data/DzZ_T1.nrrd', itk.F)
print("Pixel spacing:", t1_image.GetSpacing())
plt.imshow(itk.array_view_from_image(t1_image))

regi6.png

#Rotation de l'image améliorée T2
t2_image = itk.imread('data/DzZ_T2.nrrd', itk.F)
print("Pixel spacing:", t2_image.GetSpacing())
plt.imshow(itk.array_view_from_image(t2_image))

regi7.png

#Supplément: obtenir la direction
pyDirM=itk.GetArrayFromVnlMatrix(t2_image.GetDirection().GetVnlMatrix().as_matrix())
print("Direction matrix:\n", pyDirM)

L'alignement est effectué en utilisant la corrélation par Mattes Mutual Information, qui est souvent utilisée pour l'alignement dans les cas multimodaux.

T1ImageType = type(t1_image)
T2ImageType = type(t2_image)
assert T1ImageType==T2ImageType, "Images must have the same pixel type!"

#Initialiser le type de conversion en tant que conversion de corps rigide
TransformTypeR = itk.Rigid2DTransform[itk.D]
initialTransform = TransformTypeR.New()

MetricType = itk.MattesMutualInformationImageToImageMetricv4[
        T1ImageType, T2ImageType]
metric = MetricType.New()

scales = itk.OptimizerParameters[itk.D](initialTransform.GetNumberOfParameters())
translation_scale = 1.0 / 1000
scales.SetElement(0, 1.0)
scales.SetElement(1, translation_scale)
scales.SetElement(2, translation_scale)

#Il peut estimer automatiquement l'échelle, mais il ne semble pas fonctionner avec Mattes Mutual Information.
#ScalesEstimatorType = itk.RegistrationParameterScalesFromPhysicalShift[MetricType]
#scalesEstimator = ScalesEstimatorType.New(Metric=metric)

optimizer = itk.RegularStepGradientDescentOptimizerv4.New(
        Scales=scales,
        #ScalesEstimator=scalesEstimator,
        #LearningRate=1.0,
        MinimumStepLength=0.001,
        # RelaxationFactor=0.8,
        NumberOfIterations=300)

registration = itk.ImageRegistrationMethodv4.New(FixedImage=t1_image,
        MovingImage=t2_image,
        Metric=metric,
        MetricSamplingPercentage=0.1, # 10%
        Optimizer=optimizer,
        InitialTransform=initialTransform)

initialParameters = initialTransform.GetParameters()
#Réglage du décalage
initialParameters[0] = 0.0 # rotation in radians
initialParameters[1] = -40.0 # x translation in millimeters
initialParameters[2] = +30.0 # y translation in millimeters

initialTransform.SetParameters(initialParameters)

resampler = itk.ResampleImageFilter.New(Input=t2_image,
        Transform=initialTransform,
        UseReferenceImage=True,
        ReferenceImage=t1_image)
resampler.SetDefaultPixelValue(0)
resampler.Update()

plt.subplot(131)
plt.imshow(itk.GetArrayFromImage(resampler.GetOutput()))
plt.subplot(132)
plt.imshow(itk.GetArrayFromImage(t1_image))

regi8.png

C'est assez bizarre. Peut-être que je devrais ajuster les paramètres. N'ayez pas peur de le répéter une fois de plus en utilisant l'image alignée.

registration.SetMovingInitialTransform(initialTransform)

Dimension = t1_image.GetImageDimension()
identityTransform = TransformTypeR.New()
identityTransform.SetIdentity()
registration.SetFixedInitialTransform(identityTransform)

registration.SetNumberOfLevels(1)
registration.SetSmoothingSigmasPerLevel([0])
registration.SetShrinkFactorsPerLevel([1])

try:
    registration.Update()
except RuntimeError as exc:
    print("Exception ocurred:\n", exc, "\n\n")
finally:
    print("Registration finished")
    
CompositeTransformType = itk.CompositeTransform[itk.D, Dimension]
outputCompositeTransform = CompositeTransformType.New()
outputCompositeTransform.AddTransform(registration.GetTransform())
outputCompositeTransform.AddTransform(initialTransform)
    
resamplerResult = itk.ResampleImageFilter.New(Input=t2_image,
        Transform=outputCompositeTransform,
        UseReferenceImage=True,
        ReferenceImage=t1_image)
resamplerResult.SetDefaultPixelValue(0)
resamplerResult.Update()
# final position of T2 image when resampled into T1 image's pixel grid
plt.imshow(itk.GetArrayFromImage(resamplerResult.GetOutput()))

regi9.png

Produit des informations d'alignement.

transform = registration.GetTransform()
finalParameters = transform.GetParameters()
rotationInRadians = finalParameters.GetElement(0)
translationAlongX = finalParameters.GetElement(1)
translationAlongY = finalParameters.GetElement(2)
rotationInDegrees = rotationInRadians * 360 / 3.141592 # radian to degree
numberOfIterations = optimizer.GetCurrentIteration()

bestValue = optimizer.GetValue()

print("Result = ")
print(" Rotation degr = " + str(rotationInDegrees))
print(" Translation X = " + str(translationAlongX))
print(" Translation Y = " + str(translationAlongY))
print(" Rotation rad. = " + str(rotationInRadians))
print(" Iterations    = " + str(numberOfIterations))
print(" Metric value  = " + str(bestValue))

Regardons la différence.

difference = itk.AddImageFilter.New(Input1=t1_image,
        Input2=resamplerResult)
difference.Update()
plt.imshow(itk.GetArrayFromImage(difference.GetOutput()))

regi10.png

c'est tout.

Reference

Recommended Posts

Utilisation élémentaire d'ITK apprise avec Python
Refactoring appris avec Python (Basic)
Classe Python pour apprendre avec la chimioinfomatique
Ce que j'ai appris en Python
Code de caractère appris en Python
Fonctions Python apprises avec la chimioinfomatique
J'ai essayé d'étudier le processus avec Python
Lors de l'examen de l'utilisation de la mémoire dans Python 3
Utilisation d'opérateurs non logiques de ou en python
Quadtree en Python --2
Python en optimisation
CURL en Python
Géocodage en python
SendKeys en Python
Méta-analyse en Python
Unittest en Python
Époque en Python
Discord en Python
Allemand en Python
DCI en Python
tri rapide en python
nCr en python
N-Gram en Python
Programmation avec Python
Plink en Python
Constante en Python
FizzBuzz en Python
Sqlite en Python
Étape AIC en Python
LINE-Bot [0] en Python
CSV en Python
Assemblage inversé avec Python
Réflexion en Python
Constante en Python
nCr en Python.
format en python
Scons en Python 3
Puyopuyo en python
python dans virtualenv
PPAP en Python
Quad-tree en Python
Réflexion en Python
Chimie avec Python
Hashable en Python
DirectLiNGAM en Python
LiNGAM en Python
Aplatir en Python
Aplatir en python
Variables Python et types de données appris avec la chimio-automatique
Distribution de probabilité de niveau 2 du test statistique apprise en Python ②
Une doublure qui rend l'utilisation du cœur du CPU 1 à 100% en Python
Du dessin de fichier au graphique en Python. Élémentaire élémentaire
Analyse de survie apprise avec Python 2 - Estimation Kaplan-Meier
Distribution de probabilité de test statistique de niveau 2 apprise en Python
TensorFlow: exécuter des données apprises en Python sur Android
Liste triée en Python
AtCoder # 36 quotidien avec Python
Texte de cluster en Python
AtCoder # 2 tous les jours avec Python