In [1]:
%matplotlib inline

2D Registration Example

Most ndreg functions are convinence wrappers around the SimpleITK registration framework. Functions provided by ndreg should work reasonably well with most types of images. More complicated problems should probably be handled by writing your own SimpleITK functions. For a detailed handling of registration within SimpleITK see its official notebooks.

The basic idea behind image registration is that given an input and reference images I and J with domain X, we seek a set parameters p of given coordinate transfom Tp such that a matching function (or metric as ITK calls it) M(I(Tp(X)),J(X)) is minimized. A good example of M is the Mean Square Error. Mathematically it is the L2 norm of the difference between the input and reference image ||I(Tp(X)) - J(X)||.

Linear Registration

Linear Registration includes all registration algorithms in which Tp is spatialy invariant. This means that Tp applies the same function to all voxels in the domain. In ndreg linear registration is handled by the imgAffine. Lets begin with a simple "Hello World" registration. First we'll download two images from ndstore


In [2]:
import matplotlib.pyplot as plt
from ndreg import *
inImg = imgDownload("checkerBig")
refImg = imgDownload("checkerSmall")

Lets's display the input image


In [3]:
imgShow(inImg)


We want to align reference image to the input image. The reference image is a scaled and translated version of the input image.


In [4]:
imgShow(refImg)


Obviously these images don't overlap.


In [5]:
plt.imshow(sitk.GetArrayFromImage(refImg - inImg))


Out[5]:
<matplotlib.image.AxesImage at 0x7f7fc4259f10>

OK now lets register these images. When no optional parameters are specified imgAffine compute affine parameters which can be used to transform the input image into the reference image under MSE matching.


In [6]:
affine = imgAffine(inImg, refImg)
print(affine)


[1.3698699181747709, -0.014549862591642653, -0.011269732049306235, 1.3716329256774848, -0.28444003942134205, -0.27209562767565465]

We can now apply these parameters to the input image using imgApplyAffine.


In [7]:
defInImg = imgApplyAffine(inImg, affine, size=refImg.GetSize())
imgShow(defInImg)


Clearly deformed input image defInImg overlaps the reference image refImg


In [8]:
plt.imshow(sitk.GetArrayFromImage(refImg - defInImg))


Out[8]:
<matplotlib.image.AxesImage at 0x7f7fc659a690>

Nonlinear registation

In nonlinear registration algorithms transform Tp is not spatially invariant. A well known non-linear registation method is the Large Deformation Diffeomorphic Metric Mapping (LDDMM) algorithm. LDDMM computes a smooth invertable mapping between the input (template) and reference (target) images. In ndreg, it is implemented in the imgMetamorphosis function which returns both the transform parameters as a vector field and inverse parameters as invField. We run the registation using the default parameters but limit it to 100 iterations


In [10]:
(field, invField) = imgMetamorphosis(inImg, refImg, iterations=100, verbose=True)


/cis/home/kwame/.local/lib/python2.7/site-packages/ndreg-0.0.1-py2.7.egg/ndreg/metamorphosis  --in /tmp/tmpgUgMeS/in.img --ref /tmp/tmpgUgMeS/ref.img --out /tmp/tmpgUgMeS/out.img --alpha 0.02 --beta 0.05 --field /tmp/tmpgUgMeS/field.vtk --invfield /tmp/tmpgUgMeS/invField.vtk --iterations 100 --scale 1.0 --steps 5 --verbose  --mu 0
	E, E_velocity, E_rate, E_image (E_image %), LearningRate
0.	1036.05, 0.0357762, 0, 1036.01 (65.6301%), 8.593750e-06
1.	913.975, 0.0218348, 0, 913.953 (57.8979%), 9.453125e-06
2.	687.782, 0.0368255, 0, 687.746 (43.5679%), 1.039844e-05
3.	552.372, 0.0302024, 0, 552.342 (34.9902%), 2.859570e-06
4.	243.257, 0.0278379, 0, 243.229 (15.4083%), 3.145527e-06
5.	191.272, 0.0256142, 0, 191.246 (12.1152%), 8.650200e-07
6.	180.405, 0.0249982, 0, 180.38 (11.4268%), 9.515220e-07
7.	134.176, 0.0242637, 0, 134.152 (8.49835%), 5.233371e-07
8.	122.74, 0.0237509, 0, 122.717 (7.77396%), 5.756708e-07
9.	116.753, 0.0233563, 0, 116.73 (7.39471%), 6.332379e-07
10.	113.098, 0.023124, 0, 113.074 (7.16314%), 6.965617e-07
11.	111.144, 0.0228728, 0, 111.121 (7.03939%), 7.662179e-07
12.	105.353, 0.0227959, 0, 105.33 (6.67253%), 4.214198e-07
13.	102.511, 0.0226658, 0, 102.488 (6.49252%), 4.635618e-07
14.	99.4064, 0.0225444, 0, 99.3839 (6.29585%), 5.099180e-07
15.	96.242, 0.0224119, 0, 96.2195 (6.0954%), 5.609098e-07
16.	92.4903, 0.0222729, 0, 92.4681 (5.85774%), 6.170008e-07
17.	88.2906, 0.0221264, 0, 88.2685 (5.59171%), 6.787008e-07
18.	83.666, 0.0219675, 0, 83.6441 (5.29875%), 7.465709e-07
19.	79.4912, 0.021803, 0, 79.4694 (5.0343%), 8.212280e-07
	E, E_velocity, E_rate, E_image (E_image %), LearningRate
20.	78.11, 0.0216276, 0, 78.0884 (4.94681%), 9.033508e-07
21.	73.0635, 0.0215308, 0, 73.0419 (4.62712%), 4.968430e-07
22.	70.2745, 0.0214365, 0, 70.253 (4.45045%), 5.465272e-07
23.	68.4457, 0.0213274, 0, 68.4244 (4.3346%), 6.011800e-07
24.	63.1585, 0.0212718, 0, 63.1372 (3.99967%), 3.306490e-07
25.	61.329, 0.0212076, 0, 61.3078 (3.88378%), 3.637139e-07
26.	59.5987, 0.0211403, 0, 59.5776 (3.77417%), 4.000853e-07
27.	57.8339, 0.0210693, 0, 57.8128 (3.66237%), 4.400938e-07
28.	56.0158, 0.0209944, 0, 55.9948 (3.54721%), 4.841032e-07
29.	54.0822, 0.0209142, 0, 54.0613 (3.42472%), 5.325135e-07
30.	52.0699, 0.0208296, 0, 52.049 (3.29725%), 5.857648e-07
31.	49.9771, 0.020738, 0, 49.9563 (3.16468%), 6.443413e-07
32.	47.8826, 0.0206434, 0, 47.862 (3.032%), 7.087755e-07
33.	45.8674, 0.0205409, 0, 45.8468 (2.90434%), 7.796530e-07
34.	44.61, 0.0204435, 0, 44.5895 (2.82469%), 8.576183e-07
35.	43.4903, 0.020381, 0, 43.4699 (2.75377%), 4.716901e-07
36.	42.7078, 0.0203353, 0, 42.6875 (2.7042%), 5.188591e-07
37.	40.4615, 0.0202961, 0, 40.4412 (2.5619%), 2.853725e-07
38.	39.6718, 0.0202653, 0, 39.6515 (2.51188%), 3.139097e-07
39.	38.8972, 0.0202284, 0, 38.8769 (2.46281%), 3.453007e-07
	E, E_velocity, E_rate, E_image (E_image %), LearningRate
40.	38.0756, 0.020191, 0, 38.0555 (2.41077%), 3.798308e-07
41.	37.1948, 0.0201498, 0, 37.1747 (2.35497%), 4.178139e-07
42.	36.2457, 0.0201068, 0, 36.2256 (2.29485%), 4.595953e-07
43.	35.2247, 0.0200599, 0, 35.2046 (2.23017%), 5.055548e-07
44.	34.1313, 0.0200107, 0, 34.1113 (2.16091%), 5.561103e-07
45.	32.9399, 0.0199581, 0, 32.92 (2.08544%), 6.117213e-07
46.	31.6918, 0.019905, 0, 31.6719 (2.00637%), 6.728934e-07
47.	30.3651, 0.0198455, 0, 30.3453 (1.92234%), 7.401828e-07
48.	29.4515, 0.0197931, 0, 29.4317 (1.86447%), 8.142010e-07
49.	28.5963, 0.0197551, 0, 28.5765 (1.81029%), 4.478106e-07
50.	28.0885, 0.0197292, 0, 28.0687 (1.77812%), 4.925916e-07
51.	27.9972, 0.0196884, 0, 27.9775 (1.77234%), 5.418508e-07
52.	26.0422, 0.019675, 0, 26.0225 (1.6485%), 2.980179e-07
53.	25.3704, 0.019653, 0, 25.3508 (1.60594%), 3.278197e-07
54.	24.7518, 0.0196329, 0, 24.7322 (1.56676%), 3.606017e-07
55.	24.1347, 0.0196102, 0, 24.1151 (1.52766%), 3.966619e-07
56.	23.4398, 0.0195874, 0, 23.4202 (1.48364%), 4.363281e-07
57.	22.7436, 0.019562, 0, 22.7241 (1.43954%), 4.799609e-07
58.	21.9806, 0.019537, 0, 21.9611 (1.39121%), 5.279569e-07
59.	21.258, 0.0195084, 0, 21.2385 (1.34544%), 5.807526e-07
	E, E_velocity, E_rate, E_image (E_image %), LearningRate
60.	20.7053, 0.0194833, 0, 20.6858 (1.31042%), 6.388279e-07
61.	19.9884, 0.0194653, 0, 19.9689 (1.26501%), 3.513553e-07
62.	19.4306, 0.0194516, 0, 19.4112 (1.22968%), 3.864909e-07
63.	18.8919, 0.0194324, 0, 18.8725 (1.19555%), 4.251400e-07
64.	18.3652, 0.0194177, 0, 18.3458 (1.16218%), 4.676540e-07
65.	17.8901, 0.0193949, 0, 17.8707 (1.13209%), 5.144194e-07
66.	17.8091, 0.019383, 0, 17.7897 (1.12696%), 5.658613e-07
67.	16.7333, 0.0193664, 0, 16.7139 (1.05881%), 3.112237e-07
68.	16.2706, 0.0193581, 0, 16.2512 (1.0295%), 3.423461e-07
69.	15.8206, 0.0193443, 0, 15.8012 (1.00099%), 3.765807e-07
70.	15.3894, 0.0193342, 0, 15.3701 (0.973676%), 4.142388e-07
71.	14.9289, 0.0193195, 0, 14.9096 (0.944503%), 4.556626e-07
72.	14.4692, 0.0193085, 0, 14.4499 (0.915383%), 5.012289e-07
73.	14.0592, 0.0192915, 0, 14.0399 (0.889413%), 5.513518e-07
74.	14.0494, 0.0192827, 0, 14.0301 (0.888791%), 6.064870e-07
75.	13.234, 0.0192709, 0, 13.2148 (0.83714%), 3.335678e-07
76.	12.83, 0.0192647, 0, 12.8107 (0.811543%), 3.669246e-07
77.	12.4327, 0.0192553, 0, 12.4135 (0.786379%), 4.036171e-07
78.	12.1197, 0.0192474, 0, 12.1005 (0.76655%), 4.439788e-07
79.	11.8326, 0.0192384, 0, 11.8133 (0.748361%), 4.883767e-07
	E, E_velocity, E_rate, E_image (E_image %), LearningRate
80.	11.3635, 0.0192336, 0, 11.3443 (0.718648%), 2.686072e-07
81.	11.1145, 0.0192287, 0, 11.0953 (0.702875%), 2.954679e-07
82.	10.8692, 0.0192232, 0, 10.85 (0.687336%), 3.250147e-07
83.	10.6094, 0.0192178, 0, 10.5902 (0.670876%), 3.575161e-07
84.	10.3369, 0.019212, 0, 10.3177 (0.653614%), 3.932678e-07
85.	10.0517, 0.0192061, 0, 10.0325 (0.635547%), 4.325945e-07
86.	9.75438, 0.0191997, 0, 9.73518 (0.616712%), 4.758540e-07
87.	9.44409, 0.0191934, 0, 9.4249 (0.597056%), 5.234394e-07
88.	9.12185, 0.0191862, 0, 9.10266 (0.576643%), 5.757833e-07
89.	8.80835, 0.0191803, 0, 8.78917 (0.556784%), 6.333617e-07
90.	8.57757, 0.019171, 0, 8.5584 (0.542165%), 6.966978e-07
91.	8.35656, 0.0191698, 0, 8.33739 (0.528164%), 3.831838e-07
92.	8.15186, 0.0191635, 0, 8.1327 (0.515197%), 4.215022e-07
93.	8.03154, 0.0191618, 0, 8.01237 (0.507575%), 4.636524e-07
94.	7.70055, 0.0191579, 0, 7.68139 (0.486607%), 2.550088e-07
95.	7.57342, 0.0191558, 0, 7.55426 (0.478554%), 2.805097e-07
96.	7.44071, 0.0191532, 0, 7.42156 (0.470147%), 3.085607e-07
97.	7.30234, 0.0191504, 0, 7.28319 (0.461381%), 3.394167e-07
98.	7.15484, 0.0191475, 0, 7.13569 (0.452038%), 3.733584e-07
99.	6.99961, 0.0191444, 0, 6.98046 (0.442204%), 4.106943e-07
E = 6.99961 (0.442204%)
Length = 0.236798
Time = 38.4737s (0.641228m)

Like in the affine example we apply the transform to the image.


In [11]:
defInImg = imgApplyField(inImg, field, size=refImg.GetSize())
imgShow(defInImg)


We then show that the deformed input image overlaps with the reference image


In [12]:
plt.imshow(sitk.GetArrayFromImage(refImg - defInImg))


Out[12]:
<matplotlib.image.AxesImage at 0x7f7fc54a1f50>

In [ ]: