Skip to content

Commit 8ef0032

Browse files
committed
ENH: Add MutualInformationAffine Python script
1 parent b09b05a commit 8ef0032

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed

src/Core/Transform/MutualInformationAffine/CMakeLists.txt

+7
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,10 @@ add_test(NAME MutualInformationAffineTest
2727
moving.png
2828
output.png)
2929

30+
if(ITK_WRAP_PYTHON)
31+
add_test(NAME MutualInformationAffineTestPython
32+
COMMAND ${PYTHON_EXECUTABLE} Code.py
33+
${CMAKE_CURRENT_BINARY_DIR}/fixed.png
34+
${CMAKE_CURRENT_BINARY_DIR}/moving.png
35+
output.png)
36+
endif()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/usr/bin/env python
2+
3+
# =========================================================================
4+
#
5+
# Copyright NumFOCUS
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0.txt
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
#
19+
# =========================================================================*/
20+
21+
import sys
22+
import numpy as np
23+
24+
import itk
25+
26+
if len(sys.argv) < 4:
27+
raise Exception(f"Usage: {sys.argv[0]} fixed_image moving_image output_image")
28+
29+
# Import images
30+
fixed_image = itk.imread(sys.argv[1], itk.UC)
31+
moving_image = itk.imread(sys.argv[2], itk.UC)
32+
33+
# Preprocess images
34+
fixed_normalized_image = itk.normalize_image_filter(fixed_image)
35+
fixed_smoothed_image = itk.discrete_gaussian_image_filter(
36+
fixed_normalized_image, variance=2.0
37+
)
38+
39+
moving_normalized_image = itk.normalize_image_filter(moving_image)
40+
moving_smoothed_image = itk.discrete_gaussian_image_filter(
41+
moving_normalized_image, variance=2.0
42+
)
43+
44+
# Run gradient ascent
45+
transform = itk.AffineTransform[itk.D, fixed_image.GetImageDimension()].New()
46+
interpolator = itk.LinearInterpolateImageFunction[type(fixed_image), itk.D].New()
47+
48+
metric = itk.MutualInformationImageToImageMetric[
49+
type(fixed_image), type(moving_image)
50+
].New()
51+
52+
metric.SetNumberOfSpatialSamples(100)
53+
metric.SetFixedImageStandardDeviation(5.0)
54+
metric.SetMovingImageStandardDeviation(5.0)
55+
56+
metric.ReinitializeSeed(121212)
57+
58+
optimizer = itk.GradientDescentOptimizer.New()
59+
60+
optimizer.SetLearningRate(1.0)
61+
optimizer.SetNumberOfIterations(200)
62+
optimizer.MaximizeOff()
63+
64+
# Set scales so that the optimizer can take
65+
# large steps along translation parameters,
66+
# moderate steps along rotational parameters, and
67+
# small steps along scale parameters
68+
optimizer.SetScales([100, 0.5, 0.5, 100, 0.001, 0.001])
69+
70+
registrar = itk.ImageRegistrationMethod[type(fixed_image), type(moving_image)].New()
71+
registrar.SetFixedImage(fixed_smoothed_image)
72+
registrar.SetMovingImage(moving_smoothed_image)
73+
registrar.SetTransform(transform)
74+
registrar.SetInterpolator(interpolator)
75+
registrar.SetMetric(metric)
76+
registrar.SetOptimizer(optimizer)
77+
78+
registrar.SetFixedImageRegion(fixed_image.GetBufferedRegion())
79+
registrar.SetInitialTransformParameters(transform.GetParameters())
80+
81+
registrar.Update()
82+
83+
# Print final results
84+
print(f"Its: {optimizer.GetCurrentIteration()}")
85+
print(f"Final Value: {optimizer.GetValue()}")
86+
print(f"Final Position: {list(registrar.GetLastTransformParameters())}")
87+
88+
# Resample and write out image
89+
ResampleFilterType = itk.ResampleImageFilter[type(fixed_image), type(fixed_image)]
90+
resample = ResampleFilterType.New(
91+
Transform=transform,
92+
Input=moving_image,
93+
Size=fixed_image.GetLargestPossibleRegion().GetSize(),
94+
OutputOrigin=fixed_image.GetOrigin(),
95+
OutputSpacing=fixed_image.GetSpacing(),
96+
OutputDirection=fixed_image.GetDirection(),
97+
DefaultPixelValue=100,
98+
)
99+
100+
resample.Update()
101+
102+
itk.imwrite(resample.GetOutput(), sys.argv[3])

src/Core/Transform/MutualInformationAffine/Documentation.rst

+5
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ C++
6161
.. literalinclude:: Code.cxx
6262
:lines: 18-
6363

64+
Python
65+
...
66+
67+
.. literalinclude:: Code.py
68+
:lines: 21-
6469

6570
Classes demonstrated
6671
--------------------

0 commit comments

Comments
 (0)