[Insight-users] Mattes MI & 1+1 ES optimizer = overlap exception
Christos Panagiotou
C.Panagiotou at cs.ucl.ac.uk
Mon, 03 May 2004 14:25:04 +0100
Dear Luis
i updated the one + one es optimizer from the cvs... thanks for letting
me know about the oneplusone optimizer example (ImageRegistration11.cxx)
i try to test the optimizer and the mattes metric on a registration of
one 256x256x55 mri volume against a 18x128x31 pet volume...
Mattes histogram metric
1.
well i choose the translation scale to be the diagonial of the biggest
volume in mm. So my spacing of the MRI volume is 1.0x1.0x1.5 ->
1.0 / sqrt( 256^2 + 256^2 + (256*1.5)^2) * 10
-- you have pointed out that i need to multiply by the *magic factor* 10.
2.
according to the itk guide the number of spatial samples in the metric
should be 1 - 20 % of the pixels (pixels of both images? or the largest?)
lets say 256*256*55 = 3604480 where 10% is 360448 spatial samples
3.
number of bins = 50 (default )
4.
1+1 ES optimizer
initialization of m_Optimizer->SetNormalVariateGenerator(m_Generator);
where m_Generator->Initialize(12345);
Epsilon : i ve tried 0.000001 - 1.0
Initial search radius: i ve tried 10 - 30
GrowthFactor: 1.05 - 1.30
ShrinkFactor: 0.80 - 0.98
I have modified the MultiResMIRegistration application so i can pass the
optimizer values through a .txt file ( i ve modified actually
SimpleAppInputParser.txx, .h mainly, default was for gradient descent
optimizer as described in the itk guide) so i can pass the 4 parameters
of the 1+1 optimizer (epsilon, initial radius, shrink , growth). I tell
you this so i can remind you that
the MultiResMiRegistration CENTERS the volumes before the registration.
So some overlap definately exists.
Let me post some results:
./MultiResMIRegistration input_mriAdult_pet_1plus1ES.txt
Parsing input ...
Fixed image filename: mr_adult.mha
Big Endian: 0
Image Size: [256, 256, 55]
Image Spacing: [1, 1, 1.5]Moving image filename: pet1.mha
Big Endian: 0
Image Size: [128, 128, 31]
Image Spacing: [1, 1, 1]Permute order: [0, 1, 2]Flip axes: [0, 0,
0]Number of levels: 1
Fixed image shrink factors: [1, 1, 1]Moving image shrink factors: [1, 1,
1]Number of iterations: [4000]Initial Search Radius: 15
Epsilon: 1e-06
Growth Factor: 1.3
Shrink Factor: 0.7
Translation scale: 371.32
PGM directory: pettopd
Preprocess the images ...
Register the images ...
--- Starting level 0
No. Iterations: 4000
Caught an exception:
itk::ExceptionObject (0x8cb3800)
Location: "Unknown"
File:
/usr/local/include/InsightToolkit/Algorithms/itkMattesMutualInformationImageToImageMetric.txx
Line: 546
Description: itk::ERROR:
MattesMutualInformationImageToImageMetric(0x8cb0410): Too many samples
map outside moving image buffer: 50703 / 360448
even if i dramaticaly change the parameters i get the same ration exactly
Initial Search Radius: 40
Epsilon: 0.001
Growth Factor: 1.7
Shrink Factor: 0.3
Translation scale: 371.32
It seems somehow that something is not initialized well as the system
does not produce and ouput from the execute method... (no
m_Optimizer->GetValue() is returned)
the algorithm throws the exception immediately...
well i dont know whats wrong....
i know that this post is already long enough... i ll just paste the
modified <MIMRegistrator.txx>
/*=========================================================================
Program: Insight Segmentation & Registration Toolkit
Module: $RCSfile: MIMRegistrator.txx,v $
Language: C++
Date: $Date: 2002/10/01 01:36:06 $
Version: $Revision: 1.3 $
Copyright (c) 2002 Insight Consortium. All rights reserved.
See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _MIMRegistrator_txx
#define _MIMRegistrator_txx
#include "MIMRegistrator.h"
#include "itkCommand.h"
namespace itk
{
template <typename TFixedImage, typename TMovingImage>
MIMRegistrator<TFixedImage,TMovingImage>
::MIMRegistrator()
{
// Images need to be set from the outside
m_FixedImage = NULL;
m_MovingImage = NULL;
// Set up internal registrator with default components
m_Transform = TransformType::New();
m_Optimizer = OptimizerType::New();
m_Metric = MetricType::New();
m_Interpolator = InterpolatorType::New();
m_FixedImagePyramid = FixedImagePyramidType::New();
m_MovingImagePyramid = MovingImagePyramidType::New();
m_Registration = RegistrationType::New();
CommandIterationUpdate::Pointer m_Observer;
m_Observer = CommandIterationUpdate::New();
m_Generator = OptimizerNormalGeneratorType::New();
m_Generator->Initialize(12345);
m_Registration->SetTransform( m_Transform );
m_Registration->SetOptimizer( m_Optimizer );
m_Registration->SetMetric( m_Metric );
m_Registration->SetInterpolator( m_Interpolator );
m_Registration->SetFixedImagePyramid( m_FixedImagePyramid );
m_Registration->SetMovingImagePyramid( m_MovingImagePyramid );
m_Optimizer->AddObserver(IterationEvent(), m_Observer );
m_AffineTransform = AffineTransformType::New();
// Setup an registration observer
typedef SimpleMemberCommand<Self> CommandType;
typename CommandType::Pointer command = CommandType::New();
command->SetCallbackFunction( this, &Self::StartNewLevel );
m_Tag = m_Registration->AddObserver( IterationEvent(), command );
// Default parameters
m_NumberOfLevels = 1;
m_TranslationScale = 1.0;
m_MovingImageStandardDeviation = 0.4;
m_FixedImageStandardDeviation = 0.4;
m_NumberOfSpatialSamples = 50;
m_FixedImageShrinkFactors.Fill( 1 );
m_MovingImageShrinkFactors.Fill( 1 );
m_NumberOfIterations = UnsignedIntArray(1);
//Set elements of the array to the specified value
m_NumberOfIterations.Fill( 1000 );
m_InitialParameters = ParametersType(m_Transform->GetParameters());
}
template <typename TFixedImage, typename TMovingImage>
MIMRegistrator<TFixedImage,TMovingImage>
::~MIMRegistrator()
{
m_Registration->RemoveObserver( m_Tag );
}
template <typename TFixedImage, typename TMovingImage>
void
MIMRegistrator<TFixedImage,TMovingImage>
::Execute()
{
// Setup the optimizer
typename OptimizerType::ScalesType scales(
m_Transform->GetNumberOfParameters() );
scales.Fill(1.0);
for ( int j = 9; j < 12; j++ )
{
scales[j] = m_TranslationScale;
}
m_Optimizer->SetScales( scales );
m_Optimizer->MaximizeOn();
m_Optimizer->Initialize(15); // Initial search radius
m_Optimizer->SetEpsilon(m_Epsilon);
m_Optimizer->SetGrowthFactor(m_GrowthFactor);
m_Optimizer->SetShrinkFactor(m_ShrinkFactor);
m_Optimizer->SetNormalVariateGenerator(m_Generator);
m_Metric->SetNumberOfHistogramBins( 50 );
m_Metric->SetNumberOfSpatialSamples( 360448 );
// Setup the image pyramids
m_FixedImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
m_FixedImagePyramid->SetStartingShrinkFactors(
m_FixedImageShrinkFactors.GetDataPointer() );
m_MovingImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
m_MovingImagePyramid->SetStartingShrinkFactors(
m_MovingImageShrinkFactors.GetDataPointer() );
// Setup the registrator
m_Registration->SetFixedImage( m_FixedImage );
m_Registration->SetMovingImage( m_MovingImage );
m_Registration->SetNumberOfLevels( m_NumberOfLevels );
m_Registration->SetInitialTransformParameters(
m_Transform->GetParameters() );
m_Registration->SetFixedImageRegion( m_FixedImage->GetBufferedRegion() );
try
{
m_Registration->StartRegistration();
}
catch( itk::ExceptionObject & err )
{
std::cout << "Caught an exception: " << std::endl;
std::cout << err << std::endl;
throw err;
}
}
template <typename TFixedImage, typename TMovingImage>
const
typename MIMRegistrator<TFixedImage,TMovingImage>
::ParametersType &
MIMRegistrator<TFixedImage,TMovingImage>
::GetTransformParameters()
{
return m_Registration->GetLastTransformParameters();
}
template <typename TFixedImage, typename TMovingImage>
typename MIMRegistrator<TFixedImage,TMovingImage>
::AffineTransformPointer
MIMRegistrator<TFixedImage,TMovingImage>
::GetAffineTransform()
{
m_Transform->SetParameters(
m_Registration->GetLastTransformParameters() );
m_AffineTransform->SetMatrix( m_Transform->GetMatrix() );
m_AffineTransform->SetOffset( m_Transform->GetOffset() );
return m_AffineTransform;
}
template <typename TFixedImage, typename TMovingImage>
void
MIMRegistrator<TFixedImage,TMovingImage>
::StartNewLevel()
{
std::cout << "--- Starting level " << m_Registration->GetCurrentLevel()
<< std::endl;
unsigned int level = m_Registration->GetCurrentLevel();
if ( m_NumberOfIterations.Size() >= level + 1 )
{
m_Optimizer->SetMaximumIteration( m_NumberOfIterations[level] );
}
std::cout << " No. Iterations: "
<< m_NumberOfIterations[level]
<< std::endl;
}
} // namespace itk
#endif
i apologise once again for the length of the post, but i would like to
see this working someday :)
thanks for your patience
christos