[Insight-users] Re: MultResMIRegistration using CT and US

Luis Ibanez luis.ibanez@kitware.com
Wed, 15 May 2002 10:10:14 -0400


Hi Jon,


A) About starting the registration with an
    initial "offset", this can easily be done
    with the method:

     SetInitialTransformParameters();

This methods receives an itkArray with the set of
values that define the initial transformation applied
to the moving image. This is like serializing the
values that fully define a transform. For the particular
case of the itkAffineTransform, the parameters are arranged
as follows:

1) the matrix is stored line by line in the array
2) the offset of the transform (translation component)
    is put at the end of the array of parameters.

You may see the details on :

Insight/Code/Common/itkAffineTransform.txx: line 578
in the "GetParameters()" method, as well as line 611
in the "SetParameters()" method.





B) About getting feedback from the execution
    of the registration method:

ITK has a mechanism for communicating with other
pieces of software. It is based on the
Command/Observer design pattern. It similar to
the concept of Observers in Java.

You can use this mechanism in order to get
information about the progresion of the registration
method. (and about the state of any ITK filter too)


Here is a brief description of how it
works:


1) There is a hierarchy of ITK "Events"
    that you can find defined in :

    Insight/Code/Common/itkEventObject.h

    in particular after line 132.

2) itkObjects can send these events in
    order to notify others about their
    internal state. For example, every
    ITK filter sends a "StartEvent" when
    it starts excecution. They also send
    "UpdateProgress" events every once in
    a while so you can for example update
    a progress bar in a GUI. (an example
    of this can be seen in:

http://www.itk.org/HTML/GaussianFilter.htm


3) In order to catch this events you can
    setup "Observers" which in ITK have
    been defined following the "Command"
    design pattern.  Observers register
    themselves with an itkObject and declare
    its interest on being notified when a
    particular event happens.  Given that
    events are organized in a hierarchy,
    an observer can register for a particular
    event in the hierarchy and it will be
    notified for this event and all of its
    subclasses. (pretty much as Exceptions
    work in C++ and Java).

4) The Event that you may be interested on
    is the "IterationEvent". This event is
    sent by Optimizers at each iteration.
    The execution of the registration method
    is driven by its optimizer.

5) By writing a customized observer/command
    class and registering with the Registration
    method class you can make sure that a method
    or function that you define will be called
    at each iteration.  In this function you
    may want to query the Registration method
    and for example print data to the standard
    output, write it to a file or update a GUI.

6) For the MultiResolution registration example
    that you are using now, you will see that
    an Observer is defined in the file:

     Insight/Examples/MultiResMiRegistration/Common

     MIMRegistrator.txx

     It is in line: 57

   typename CommandType::Pointer command = CommandType::New();

a callback function is attached to this command in line 58:

   command->SetCallbackFunction( this, &Self::StartNewLevel );

In this particular case, the callback can be a member method
of a class.

There is a variety of Command classes that you may use.

They are defined in:   Insight/Common/itkCommand.h

Some of them execute actions themselves, others are intended
to delegate execution to C++ methods, others allow you to
call plain C functions.


7) In the case of the example, you will find that
    the command is delegating to the C++ method:
    StartNewLevel() implemented in line : 179.

    So, If you want more information about the state
    of the Registration, you can modify this method,
    or create your own customized Command class.

8) Note that because this is the Multiresolution
    Registration method, an Iteration of this class
    corresponds to a full execution of a registration
    for one level of the pyramid.  That may be too
    high level for what you are trying to do now,
    which is figure out good values for the learning
    rates.

9) You may want to go a level lower and get the optimizer
    that is used by the registration method. Plug an
    observer to the "IterationEvent" on this optimizer
    and define a callback that will print the status of
    the optimizer.  You can see examples of this in the
    Testing directory:

    Insight/Testing/Code/Algorithms/itkImageRegistrationTest_*.cxx

a Command helper class is defined in:

    Insight/Testing/Code/Algorithms/itkCommandIterationUpdate.h


10) In order to get the current optimizer from inside the
     MIMRegistrator.txx file you can do something like add
     around line 60 the following code:

    m_Registration->GetOptimizer()->AddObserver(
                                       IterationEvent(),myCommand);

And declare "myCommand" like in the itkCommandIterationUpdate.h used
in Testing.

This combination will print to std::cout the values of the
transform parameter at each iteration of the optimizer.

By following the progression of these values you can figure
out the appropriated values for the LearnigRates.



Please let us know if you encounter any problem,



   Thanks


    Luis


==================================
Jon Harald Kaspersen wrote:
> Hi again Luis,
> 
> Thanks for making things a lot clearer !!
> 
> I have no problem with copying these mails to the user list.
> 
> I have started the iterative procedure to find a set of parameters that 
> suits my data.
> Some additional questions comes to my mind.
> 
> 1. Does the standard output give any information about how much the 
> source data moves between iterations or levels ? I guess that little 
> movement between iterations means that the data is quite close, or a 
> good registration has been found ?
> 
> 2. My data is from the abdomen (in fact from patients with abdominal 
> aortic aneurysms). The CT scan covers a much bigger part of the body 
> than the US. Is there a way to "offset" the US, a sort of a starting 
> point for the iteration ? I could of cause just use the overlapping data 
> regions in the axial direction and cut away the CT data that is not 
> covered by the US.
> 
> Regards
> Jon