[Insight-users] Re: MRI registration example : How to change components

Luis Ibanez luis.ibanez@kitware.com
Wed, 24 Apr 2002 14:59:02 -0400


Hi Simon,

What you are doing is probably the best exercise
to get familiar with the registration framework.

That is, once you succed using a combination of
components, exchange the components and adjust
the parameters for the new combination.

For the MultResMIRegistration example you will
find a ReadMe.pdf (and ReadMe.doc) file with the
sources. Both the example and the document were
nicely developed by Lydia Ng @ Insightful.

The ReadMe.pdf describes line by line the
parameters that you should provide to the
executable. (an example parameter file was just
posted to the list too).

For example you mention the problem of aligning
the axis of the images prior to the registration
stage. That can be done using the parameter file
in lines 9 and line 10.

Line 9 specifies which axis of the moving image
corresponds to the 0,1,2 axis of the fixed image.
That will allow to easily correct for one image
being acquired in axial slices while the other is
in coronal slices.

Line 10 allows to flip (mirror) along one axis.
That has to be used with care because you are
actually exchanging the left kidney with the
right kidney of your patient... Make sure that
you have a good justification for flipping the
image and also make sure that you have the means
for flipping it back once the registration is done.

About the scaling the translation parameters with
respect to the rotation (and shearing) ones: This
is a very important parameter (as Lydia pointed out
recently).  The rule of thumb is to start with it
as large as the largest dimension of the image in
millimeters (or the metric unit that you use for
the spacing), not in pixels.

So for example an image of size 256x256x64 with
voxels spacing: 0.6 x 0.6 x 3 mm , the actual
physical dimensions of the image are:

     153.6 x 153.5 x 192 mm

So a good scaling parameter could be 200. Note that
in the parameters file this is provided as "200"
for convinience, but in the code (if you actually
write it in your C++ code) the value is 1/200.

The whole point is to make the translation parameter
homogeneous in range with the rotation parameters.
Rotations will be products of sin() and cos() so in
general they will be in the range [-1:1].  In a
typical image you may want to expect that the worst
case translation (miss-registration) will be about
half the size of the image. Scaling tranlations by
a factor that is about the maximum physical dimension
of the image will put all the registration parameters
in the [-1:1] range.

--

About exchanging the component of the registration
this is relatively easy to do. You may notice that
the itk::RegistrationMethod class has the following
methods:

   SetTransform()
   SetOptimizer()
   SetMetric()
   SetInterpolator()

and in ITK you find a hierarchy for each one of them.

For optimizers you may choose among the "single valued"
optimizers, those for which the cost function returns only
one "double" value:
http://public.kitware.com/Insight/Web/Doxygen/html/classitk_1_1SingleValuedNonLinearOptimizer.html

For Transform you may choose any of the transforms:

- AffineTransform
- ScaleTransform
- Rigid3DTransform
- TranslationTransform

Just note that you have to provide the initial parameters
and that each transform will map its internal parameters in
a particular way into the Array<> of parameters.

For Metrics you may choose any of the following:
- MutualInformation
- NormalizedCorrelation
- PatterIntensity
- MeanSquares (differences)
http://public.kitware.com/Insight/Web/Doxygen/html/classitk_1_1ImageToImageMetric.html
and you may probably add your own ... !
(we will be happy to get new metrics contributed by users !)

For interpolators the choices are:
- NearestNeighborInterpolator
- LinearInterpolator
- BSplineInterpolator

This last choice is particularly sensitive becase the interpolator
is executed for *every* pixel in the image (except for MutualInformation
where a stochastic sampling is used..) that is, the total registration
time is directly proportional to the computation time of the interpolator...

Examples of different combinations of components are available
in the Testing directory. Please take a look at the files in
Insight/Testing/Code/Algorithms:


   itkImageRegistrationMethodTest_*.cxx


Each one of them exercise a particular combination of components.
By comparing any two of these examples you will see how the
different components are combined.


Please let us know if you encounter any difficulty mixing
the components or tunning their parameters.



Thanks


Luis




===============================================================

Simon Warfield wrote:
> Hi Luis,
> 
>   I have played around a little with the MultiResMI implementation, and have
> been able to register a data set.  As an exercise for me, I thought I would
> try to work out how to replace the rigid transform with an affine transform.
> 
> After peering through several classes it is still not completely clear to me.
>   Can you explain a little more how the transform and optimizer classes can be
> used for this ?  
> 
>   The example assumes the input images are in the same orientation.  Often
> this isn't the case, but frequently the orientation of data is recorded in
> the scanner generated header.  Does ITK have a capability for encoding the
> origin and orientation of data ?  I wonder if this is in the metaimage file
> format.  The metaimage class wasn't immediately obvious on a first glance.
> Is there a .pdf document describing it in more detail ?
> 
> In the rigid case, the learning rate for translation and rotation needs to
> be different and this is achieved by 'scaling'.  Do you have any idea how to 
> choose appropriate 'scaling' parameters for the extra affine parameters ?
> 
> By the way, thanks for your detailed email of 9 April to the list, on the
> operation of this example. It was a masterpiece of clarity.
> 
> 
>