Skip to content

Commit 448db3f

Browse files
committed
BUG: Fixed MutualInformationAffine cxx and baseline test parameters
1 parent 23b8382 commit 448db3f

18 files changed

+1526
-1667
lines changed

requirements.txt

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
async-generator==1.10
2+
atomicwrites==1.4.0
3+
backcall==0.2.0
4+
brotlipy==0.7.0
5+
certifi==2020.12.5
6+
colorama==0.4.4
7+
colorcet==2.0.2
8+
cycler==0.10.0
9+
decorator==4.4.2
10+
defusedxml==0.6.0
11+
entrypoints==0.3
12+
imageio==2.9.0
13+
iniconfig==1.1.1
14+
ipydatawidgets==4.2.0
15+
ipykernel==5.4.3
16+
ipympl==0.6.2
17+
ipython==7.19.0
18+
ipython-genutils==0.2.0
19+
ipywidgets==7.6.3
20+
itk==5.2rc2
21+
itk-boneenhancement==0.4.0
22+
itk-bonemorphometry==1.2.0
23+
itk-core==5.2rc2
24+
itk-filtering==5.2rc2
25+
itk-hasi==0.1.1
26+
itk-io==5.2rc2
27+
itk-meshtopolydata==0.6.3
28+
itk-numerics==5.2rc2
29+
itk-registration==5.2rc2
30+
itk-segmentation==5.2rc2
31+
itkwidgets==0.32.0
32+
jedi==0.18.0
33+
Jinja2==2.11.2
34+
json5==0.9.5
35+
jupyter-client==6.1.11
36+
jupyter-core==4.7.0
37+
jupyterlab==2.2.6
38+
jupyterlab-widgets==1.0.0
39+
kiwisolver==1.3.1
40+
MarkupSafe==1.1.1
41+
matplotlib==3.3.3
42+
mistune==0.8.4
43+
numpy==1.19.5
44+
param==1.10.1
45+
parso==0.8.1
46+
pickleshare==0.7.5
47+
Pillow==8.1.0
48+
pluggy==0.13.1
49+
prompt-toolkit==3.0.10
50+
py==1.10.0
51+
pyct==0.4.8
52+
Pygments==2.7.4
53+
pyparsing==2.4.7
54+
pytest==6.2.1
55+
python-dateutil==2.8.1
56+
pyzmq==20.0.0
57+
six==1.15.0
58+
testpath==0.4.4
59+
toml==0.10.2
60+
tornado==6.1
61+
traitlets==5.0.5
62+
traittypes==0.2.1
63+
wcwidth==0.2.5
64+
webencodings==0.5.1
65+
widgetsnbextension==3.5.1
66+
wincertstore==0.2
67+
zstandard==0.15.1

src/Core/Transform/CMakeLists.txt

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,13 @@ compare_to_baseline(EXAMPLE_NAME GlobalRegistrationTwoImagesAffine
2929
output
3030
)
3131

32-
# TODO revisit input/baseline images and example paramters
33-
# before reenabling
34-
#add_example(MutualInformationAffine)
35-
#compare_to_baseline(EXAMPLE_NAME MutualInformationAffine
36-
# BASELINE_PREFIX
37-
# fixed
38-
# moving
39-
# output # TODO Previous test runs may override the baseline image which is not useful
40-
# )
32+
add_example(MutualInformationAffine)
33+
compare_to_baseline(EXAMPLE_NAME MutualInformationAffine
34+
BASELINE_PREFIX
35+
fixed
36+
moving
37+
OutputBaseline
38+
)
4139

4240
add_example(GlobalRegistrationTwoImagesBSpline)
4341
compare_to_baseline(EXAMPLE_NAME GlobalRegistrationTwoImagesBSpline

src/Core/Transform/MutualInformationAffine/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,8 @@ install(FILES Code.cxx CMakeLists.txt
2222

2323
enable_testing()
2424
add_test(NAME MutualInformationAffineTest
25-
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MutualInformationAffine)
25+
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MutualInformationAffine
26+
fixed.png
27+
moving.png
28+
output.png)
2629

src/Core/Transform/MutualInformationAffine/Code.cxx

Lines changed: 42 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -34,41 +34,24 @@ using PixelType = unsigned char;
3434

3535
using ImageType = itk::Image<PixelType, Dimension>;
3636

37-
static void
38-
CreateEllipseImage(ImageType::Pointer image);
39-
static void
40-
CreateCircleImage(ImageType::Pointer image);
41-
4237
int
43-
main(int itkNotUsed(argc), char * itkNotUsed(argv)[])
38+
main(int argc, char * argv[])
4439
{
45-
/*ImageType::Pointer fixedImage = ImageType::New();
46-
CreateCircleImage(fixedImage);
47-
ImageType::Pointer movingImage = ImageType::New();
48-
CreateEllipseImage(movingImage);
49-
*/
50-
51-
// Write the two synthetic inputs
52-
using WriterType = itk::ImageFileWriter<ImageType>;
53-
54-
/*
55-
WriterType::Pointer fixedWriter = WriterType::New();
56-
fixedWriter->SetFileName("fixed.png");
57-
fixedWriter->SetInput(fixedImage);
58-
fixedWriter->Update();
59-
60-
WriterType::Pointer movingWriter = WriterType::New();
61-
movingWriter->SetFileName("moving.png");
62-
movingWriter->SetInput(movingImage);
63-
movingWriter->Update();*/
64-
6540
using ReaderType = itk::ImageFileReader<ImageType>;
41+
42+
if (argc < 4)
43+
{
44+
std::cout << "Usage: " << argv[0] << " imageFile1 imageFile2 outputFile" << std::endl;
45+
return EXIT_FAILURE;
46+
}
6647
ReaderType::Pointer fixedReader = ReaderType::New();
67-
fixedReader->SetFileName("apple.jpg");
48+
fixedReader->SetFileName(argv[1]);
49+
fixedReader->Update();
6850
ImageType::Pointer fixedImage = fixedReader->GetOutput();
6951

7052
ReaderType::Pointer movingReader = ReaderType::New();
71-
movingReader->SetFileName("orange.jpg");
53+
movingReader->SetFileName(argv[2]);
54+
movingReader->Update();
7255
ImageType::Pointer movingImage = movingReader->GetOutput();
7356

7457
// We use floats internally
@@ -124,8 +107,8 @@ main(int itkNotUsed(argc), char * itkNotUsed(argv)[])
124107
// which have been normalized to a mean of zero and unit variance. We
125108
// will follow this empirical rule in this example.
126109

127-
metric->SetFixedImageStandardDeviation(0.4);
128-
metric->SetMovingImageStandardDeviation(0.4);
110+
metric->SetFixedImageStandardDeviation(5.0);
111+
metric->SetMovingImageStandardDeviation(5.0);
129112

130113
registration->SetFixedImage(fixedSmoother->GetOutput());
131114
registration->SetMovingImage(movingSmoother->GetOutput());
@@ -183,11 +166,8 @@ main(int itkNotUsed(argc), char * itkNotUsed(argv)[])
183166

184167
metric->SetNumberOfSpatialSamples(numberOfSamples);
185168

186-
// optimizer->SetLearningRate( 15.0 ); //"All the sampled point mapped to outside of the moving image"
187-
// optimizer->SetLearningRate( 1.0 );
188-
optimizer->SetLearningRate(0.1);
189-
optimizer->SetNumberOfIterations(1000);
190-
optimizer->MaximizeOn(); // We want to maximize mutual information (the default of the optimizer is to minimize)
169+
// For consistent results when regression testing.
170+
metric->ReinitializeSeed(121212);
191171

192172
// Note that large values of the learning rate will make the optimizer
193173
// unstable. Small values, on the other hand, may result in the optimizer
@@ -204,6 +184,30 @@ main(int itkNotUsed(argc), char * itkNotUsed(argv)[])
204184
// optimizer step length is proportional to the Metric values themselves.
205185
// Metrics with large values will require you to use smaller values for the
206186
// learning rate in order to maintain a similar optimizer behavior.
187+
optimizer->SetLearningRate(1.0);
188+
189+
// Note that the only stop condition for the v3 GradientDescentOptimizer class
190+
// is that the maximum number of iterations is reached.
191+
// For the option to exit early on convergence use GradientDescentOptimizerv4
192+
// with an accompanying v4 metric class.
193+
optimizer->SetNumberOfIterations(200);
194+
optimizer->MaximizeOn(); // We want to maximize mutual information (the default of the optimizer is to minimize)
195+
196+
auto scales = optimizer->GetScales();
197+
198+
// Let optimizer take
199+
// large steps along translation parameters,
200+
// moderate steps along rotational parameters,
201+
// and small steps along scale parameters
202+
scales.SetSize(6);
203+
scales.SetElement(0, 100);
204+
scales.SetElement(1, 0.5);
205+
scales.SetElement(2, 0.5);
206+
scales.SetElement(3, 100);
207+
scales.SetElement(4, 0.0001);
208+
scales.SetElement(5, 0.0001);
209+
210+
optimizer->SetScales(scales);
207211

208212
try
209213
{
@@ -251,107 +255,12 @@ main(int itkNotUsed(argc), char * itkNotUsed(argv)[])
251255
resample->SetOutputDirection(fixedImage->GetDirection());
252256
resample->SetDefaultPixelValue(100);
253257

258+
using WriterType = itk::ImageFileWriter<ImageType>;
259+
254260
WriterType::Pointer writer = WriterType::New();
255-
writer->SetFileName("output.png");
261+
writer->SetFileName(argv[3]);
256262
writer->SetInput(resample->GetOutput());
257263
writer->Update();
258264

259265
return EXIT_SUCCESS;
260266
}
261-
262-
263-
void
264-
CreateEllipseImage(ImageType::Pointer image)
265-
{
266-
using EllipseType = itk::EllipseSpatialObject<Dimension>;
267-
268-
using SpatialObjectToImageFilterType = itk::SpatialObjectToImageFilter<EllipseType, ImageType>;
269-
270-
SpatialObjectToImageFilterType::Pointer imageFilter = SpatialObjectToImageFilterType::New();
271-
272-
ImageType::SizeType size;
273-
size[0] = 100;
274-
size[1] = 100;
275-
276-
imageFilter->SetSize(size);
277-
278-
ImageType::SpacingType spacing;
279-
spacing.Fill(1);
280-
imageFilter->SetSpacing(spacing);
281-
282-
EllipseType::Pointer ellipse = EllipseType::New();
283-
EllipseType::ArrayType radiusArray;
284-
radiusArray[0] = 10;
285-
radiusArray[1] = 20;
286-
ellipse->SetRadiusInObjectSpace(radiusArray);
287-
288-
using TransformType = EllipseType::TransformType;
289-
TransformType::Pointer transform = TransformType::New();
290-
transform->SetIdentity();
291-
292-
TransformType::OutputVectorType translation;
293-
translation[0] = 65;
294-
translation[1] = 45;
295-
transform->Translate(translation, false);
296-
297-
ellipse->SetObjectToParentTransform(transform);
298-
299-
imageFilter->SetInput(ellipse);
300-
301-
ellipse->SetDefaultInsideValue(255);
302-
ellipse->SetDefaultOutsideValue(0);
303-
imageFilter->SetUseObjectValue(true);
304-
imageFilter->SetOutsideValue(0);
305-
306-
imageFilter->Update();
307-
308-
image->Graft(imageFilter->GetOutput());
309-
}
310-
311-
void
312-
CreateCircleImage(ImageType::Pointer image)
313-
{
314-
using EllipseType = itk::EllipseSpatialObject<Dimension>;
315-
316-
using SpatialObjectToImageFilterType = itk::SpatialObjectToImageFilter<EllipseType, ImageType>;
317-
318-
SpatialObjectToImageFilterType::Pointer imageFilter = SpatialObjectToImageFilterType::New();
319-
320-
ImageType::SizeType size;
321-
size[0] = 100;
322-
size[1] = 100;
323-
324-
imageFilter->SetSize(size);
325-
326-
ImageType::SpacingType spacing;
327-
spacing.Fill(1);
328-
imageFilter->SetSpacing(spacing);
329-
330-
EllipseType::Pointer ellipse = EllipseType::New();
331-
EllipseType::ArrayType radiusArray;
332-
radiusArray[0] = 10;
333-
radiusArray[1] = 10;
334-
ellipse->SetRadiusInObjectSpace(radiusArray);
335-
336-
using TransformType = EllipseType::TransformType;
337-
TransformType::Pointer transform = TransformType::New();
338-
transform->SetIdentity();
339-
340-
TransformType::OutputVectorType translation;
341-
translation[0] = 50;
342-
translation[1] = 50;
343-
transform->Translate(translation, false);
344-
345-
ellipse->SetObjectToParentTransform(transform);
346-
347-
imageFilter->SetInput(ellipse);
348-
349-
ellipse->SetDefaultInsideValue(255);
350-
ellipse->SetDefaultOutsideValue(0);
351-
imageFilter->SetUseObjectValue(true);
352-
imageFilter->SetOutsideValue(0);
353-
354-
imageFilter->Update();
355-
356-
image->Graft(imageFilter->GetOutput());
357-
}

src/Core/Transform/MutualInformationAffine/Documentation.rst

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Mutual Information Affine
44
.. index::
55
single: AffineTransform
66
single: MutualInformationImageToImageMetric
7+
single: GradientDescentOptimizer
78

89
Synopsis
910
--------
@@ -25,20 +26,21 @@ Results
2526

2627
moving.png
2728

28-
.. figure:: output.png
29+
.. figure:: OutputBaseline.png
2930
:scale: 70%
30-
:alt: output.png
31+
:alt: OutputBaseline.png
3132

32-
output.png
33+
OutputBaseline.png
3334

3435
Output::
3536

36-
Optimizer stop condition: GradientDescentOptimizer: Maximum number of iterations (1000) exceeded.
37-
Final Parameters: [2.03502150081667, 0.4815329593844025, -0.524998748481682, 0.5494736862921054, 0.016827072908497744, -0.018211282766070345]
37+
Optimizer stop condition: GradientDescentOptimizer: Maximum number of iterations (200) exceeded.
38+
Final Parameters: [1.0028069041777101, -0.009647107048100798, -0.010717116855425006, 1.0029040091646872, 13.26279335943067, 12.226979744206531]
39+
3840
Result =
39-
Iterations = 1000
40-
Metric value = -0.000162484
41-
Numb. Samples = 100
41+
Iterations = 200
42+
Metric value = 0.000971698
43+
Numb. Samples = 567
4244

4345
Code
4446
----
@@ -49,8 +51,16 @@ C++
4951
.. literalinclude:: Code.cxx
5052
:lines: 18-
5153

54+
55+
Binder
56+
------
57+
.. image:: https://mybinder.org/badge_logo.svg
58+
:target: https://mybinder.org/v2/gh/InsightSoftwareConsortium/ITKExamples/master?filepath=src%2FCore%2FTransform%2FMutualInformationAffine%2FMutualInformationAffine.ipynb
59+
60+
5261
Classes demonstrated
5362
--------------------
5463

5564
.. breathelink:: itk::AffineTransform
5665
.. breathelink:: itk::MutualInformationImageToImageMetric
66+
.. breathelink:: itk::GradientDescentOptimizer

0 commit comments

Comments
 (0)