Szükséges fájlok importálása.
import SimpleITK as sitk
import sys
Megadunk egy függvényt, amely minden iterációs lépésben kiértékelődik majd. Így lehetőségünk van például kiírni a konzolra az iterációszámot, valamint az aktuális hasonlósági értéket. Akár a deformált képet is előállíthatnánk és a bázisképre vetíthetnénk, hogy vizuálisan is követni tudjuk a regisztráció menetét. Gyakorlásként oldjuk is meg!
# Print iteration info to console
def command_iteration(method) :
print("{0:3} = {1:10.5f}".format(method.GetOptimizerIteration(), method.GetMetricValue()))
A program parancssori paraméterként várja a fájlneveket. Az első a báziskép, a második a regisztrálandó. Harmadikként az eredmény kép fájlnevét, utolsóként az optimális B-Spline transzformáció paramétereit tartalmazó szöveges fájl nevét adhatjuk át.
A PyCharm környezetben az alábbi módon állíthatunk be rögzített parancssori paramétereket. Ha még nem tettük, akkor futtasuk a programot. Hibaüzenetet fogunk kapni, de a PyCharm létrehoz egy futtatási konfigurációs fájlt a programhoz, amit ígytovább tudunk szerkeszteni a Run / Edit Configurations... menüponttal. A bal oldali panelen a Python programunk legyen kiválasztva. A jobb oldali panelen a Configurations mezőben adjuk meg az értékeket, például: o1.png o2.png o1_o2.png o1_o2_transform.txt
Ha nincs elegendő parancssori paraméter, hibaüzenettel kilépünk.
if len(sys.argv) < 4:
print("Usage: {0} <fixedImageFilter> <movingImageFile> <outputImageFile> <outputTransformFile>".format(sys.argv[0]))
sys.exit(1)
Képek beolvasása a SimpleITK függvényével. A B-Spline transzformációhoz lebegőpontos típusra kell alakítanunk őket.
# Reading images
fixed = sitk.ReadImage(sys.argv[1], sitk.sitkFloat32)
moving = sitk.ReadImage(sys.argv[2], sitk.sitkFloat32)
B-Spline transzformáció kezdeti paramétereinek előállítása csupa 0 értékkel. A transfromDomainMeshSize értéke esetünkben [8, 8] lesz, vagyis minden dimenzió mentén 8 foltot kérünk. Ez a képet 64 foltra osztja fel. A köbös B-Spline esetén egy képen kívüli, a belsőkkel egyező méretű folt-sáv is hozzárendelésre kerül, így 10x10 folt lesz. A 10 folt sarkait 11 ponttal adhatjuk meg egy irányban. Az összes paraméter száma így 11x11x2 = 242 lesz. (Minden folt pont X- és Y-koordinátával rendelkezik.) A B-Spline a belső területeken a közelben található rácspontok elmozdulási vektorainak súlyozott összegével számol.
transfromDomainMeshSize = [8] * moving.GetDimension()
tx = sitk.BSplineTransformInitializer(fixed, transfromDomainMeshSize)
print('Domain mesh size: ', transfromDomainMeshSize)
print("Initial Parameters:")
print(tx.GetParameters())
print(len(tx.GetParameters()))
Regisztrációs műveletsor felépítése. Az R objektum lesz a központi elem. Ehhez a korrelációt állítjuk be hasonlósági mértékként. Optimalizálóként a Limited memory Broyden Fletcher Goldfarb Shannon minimization with simple bounds módszert használjuk, amely alkalmas a nagy paraméterszámú optimalizáló feladat megoldására. A kezdeti transzformáció az előzőleg létrehozott tx lesz. Lineáris interpolációt választunk a transzformáció végrehajtásához. Végül az iterációk figyelésére beállítjuk az előzőleg definiált command_iteration függvényünket.
# Setting up registration pipeline
R = sitk.ImageRegistrationMethod()
R.SetMetricAsCorrelation()
R.SetOptimizerAsLBFGSB(gradientConvergenceTolerance=1e-5,
numberOfIterations=100,
maximumNumberOfCorrections=5,
maximumNumberOfFunctionEvaluations=1000,
costFunctionConvergenceFactor=1e+7)
R.SetInitialTransform(tx, True)
R.SetInterpolator(sitk.sitkLinear)
R.AddCommand(sitk.sitkIterationEvent, lambda: command_iteration(R))
A regisztrációs folyamat indítása.
# Execute registration and print result
outTx = R.Execute(fixed, moving)
Erdmény kiírása a konzolra és a paraméter szövegfájlba.
print("-------")
print(outTx)
print("Optimizer stop condition: {0}".format(R.GetOptimizerStopConditionDescription()))
print(" Iteration: {0}".format(R.GetOptimizerIteration()))
print(" Metric value: {0}".format(R.GetMetricValue()))
# Save transform and transformed result
sitk.WriteTransform(outTx, sys.argv[4])
Regisztrálandó kép újramintavételezése az optimális transzformációval a referenciakép rácsán, és fájlba írása. PNG exportáláshoz a sitkFloat32 típusú képet sitkUInt8 típusúvá kell alakítani!
resampler = sitk.ResampleImageFilter()
resampler.SetReferenceImage(fixed)
resampler.SetInterpolator(sitk.sitkLinear)
resampler.SetDefaultPixelValue(0)
resampler.SetTransform(outTx)
out = resampler.Execute(moving)
# PNG can handle unsigned integer data
outu8 = sitk.Cast(sitk.RescaleIntensity(out), sitk.sitkUInt8)
sitk.WriteImage(outu8, sys.argv[3])