[Insight-users] rigid2D registration fails to rotate images
Luis Ibanez
luis.ibanez at kitware.com
Thu Mar 18 12:13:55 EDT 2010
Hi Darren,
Your approach sounds reasonable,
and it should provide an unsupervised mechanism for registering the images.
What seems to be missing from your code is a re-initialization of the
optimizer. That's where you may be now carrying a left-over state from
previous registrations.
If you want to be 100% sure, would simply put the for-loop outside of the
creation of all the registration classes. That is, move the instantiation of the
Metric, Optimizer, Interpolator and Transform, all inside of the for-loop body.
In that way you guarantee that they are all fresh.
Regards,
Luis
----------------------------------------------------------------------------------------------------------
On Tue, Mar 9, 2010 at 8:01 PM, Darren Weber
<darren.weber.lists at gmail.com> wrote:
>
> Hi Luis et al.,
> In this loop (see below), is it necessary to "reset" the registration method
> (optimizer or anything else)? Could there be any "hang-over" from previous
> calls in the loop?
> TIA,
> Darren
>
>
> On Tue, Mar 9, 2010 at 3:07 PM, Darren Weber <darren.weber.lists at gmail.com>
> wrote:
>>
>> FYI, here's a snip from the "rotation loop" (see ImageRegistration6.cxx
>> for the rest):
>>
>>
>> // The registration fails when the angle of rotation is large, so we
>> need a
>> // loop to evaluate a range of angles to find one that will work well.
>> double angleInDegrees[] = { 0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0,
>> 70.0, 80.0, 90.0, 100.0, 110.0, 120.0, 130.0, 140.0, 150.0, 160.0, 170.0,
>> 180.0 };
>> double angleInRadians, bestAngleInRadians;
>> unsigned int bestIterations = 0;
>> TransformType::Pointer rigid2DFinalTransform = TransformType::New();
>> OptimizerType::MeasureType bestMetric = 0.0;
>> for( unsigned int i = 0; i < 19; i++ )
>> {
>> angleInRadians = angleInDegrees[i] * vnl_math::pi / 180.0;
>> std::cout
>> << std::endl
>> << "Loop " << i << ", trying:" << std::endl
>> << "angleInDegrees = " << angleInDegrees[i] << " degrees " <<
>> std::endl
>> << "angleInRadians = " << angleInRadians << std::endl
>> << std::endl;
>> initializer->InitializeTransform();
>> rigid2DTransform->SetAngle( angleInRadians );
>> registration->SetInitialTransformParameters(
>> rigid2DTransform->GetParameters() );
>> try
>> {
>> registration->StartRegistration();
>> if( VERBOSE )
>> {
>> std::cout << std::endl
>> << optim << std::endl
>> << std::endl;
>> }
>> }
>> catch( itk::ExceptionObject & err )
>> {
>> std::cerr << "ExceptionObject caught !" << std::endl;
>> std::cerr << err << std::endl;
>> return EXIT_FAILURE;
>> }
>> // Check the metric and store the best angle
>> if( i == 0 )
>> bestMetric = optim->GetValue();
>> if( bestMetric > optim->GetValue() )
>> {
>> bestMetric = optim->GetValue();
>> bestIterations = optim->GetCurrentIteration();
>> bestAngleInRadians = angleInRadians;
>> // ** Set the final rigid2DTransform **
>> rigid2DFinalTransform->SetParameters(
>> registration->GetLastTransformParameters() );
>> rigid2DFinalTransform->SetFixedParameters(
>> rigid2DTransform->GetFixedParameters() );
>> }
>> std::cout
>> << std::endl
>> << "After loop " << i << ", metrics are:" << std::endl
>> << "angleInDegrees = " << angleInDegrees[i] << " degrees " <<
>> std::endl
>> << "angleInRadians = " << angleInRadians << std::endl
>> << "bestMetric = " << bestMetric << std::endl
>> << "currentMetric = " << optim->GetValue() << std::endl
>> << std::endl;
>> }
>>
>>
>> Best,
>> Darren
>>
>>
>>
>>
>>
>>
>> On Mon, Mar 8, 2010 at 11:14 AM, Darren Weber
>> <darren.weber.lists at gmail.com> wrote:
>>>
>>> Hi Luis et al.,
>>> Thanks for considering this and offering suggestions.
>>> There are thousands of images to register. It's possible to manually
>>> note approximate initialization values for the rotation of all the images.
>>> However, it may be easier (perhaps not quicker) to create a "rotation loop"
>>> that:
>>> (a) sets a rotation value between 0 to pi (stepping 15 degrees),
>>> (b) calls the registration method, then
>>> (c) checks the metric for the lowest value (for mean sq metric) to
>>> identify and store the rotation that provides the "best" registration.
>>> The extra "rotation" loop means running the registration N times (say 13
>>> times for 0:15:180 [in Octave syntax]) and there may be a final run with the
>>> "best" rotation value.
>>> Is this reasonable? Is there are better way to do this?
>>> As a novice with optimization, I'm surprised that some kind of quick
>>> estimate for the full range of rotations is not built into the optimization
>>> routine or the registration method.
>>> Take care,
>>> Darren
>>>
>>>
>>>
>>> On Sat, Mar 6, 2010 at 3:58 PM, Luis Ibanez <luis.ibanez at kitware.com>
>>> wrote:
>>>>
>>>> Darren,
>>>>
>>>>
>>>> Thanks for posting all the source code and images that
>>>> reproduce the problem that you are observing.
>>>>
>>>>
>>>> As Richard pointed out, the registration process must be
>>>> initialized properly.
>>>>
>>>>
>>>> It is very unlikely that an optimization process will manage
>>>> to register two images that are 140 degrees off, as the ones
>>>> that you kindly posted.
>>>>
>>>>
>>>> So you should:
>>>>
>>>> 1) Initialize the Transform with an angle close to 140 degrees.
>>>>
>>>> 2) Use the Rigid2DTransform instead of the
>>>> CenteredRigid2DTransform (this later one is deprecated)
>>>>
>>>> 3) Remove all the Change image filters that you have in your
>>>> code. They shouldn't be necessary.
>>>>
>>>>
>>>> Please find attached a simplified variation of the example:
>>>>
>>>> Insight/Examples/Registration/
>>>> ImageRegistration6.cxx
>>>>
>>>> With this attached .cxx file,
>>>> I manage to register your two images with the following output:
>>>>
>>>> Angle (radians) 2.45657
>>>> Angle (degrees) 140.751
>>>> Translation X = 1.67046
>>>> Translation Y = -0.480926
>>>> Iterations = 92
>>>> Metric value = 6.19969e+07
>>>>
>>>>
>>>> I ran it with the following set of command line arguments:
>>>>
>>>> ImageRegistration6
>>>>
>>>> section0004_w1.tif section0005_w1.tif 150.0 output.tiff
>>>>
>>>>
>>>> Where "150.0" is the initial angle to set in the Transform.
>>>>
>>>>
>>>> Please give it a try at this attached code and let us
>>>> know if you find any problems.
>>>>
>>>>
>>>> Thanks
>>>>
>>>>
>>>> Luis
>>>>
>>>>
>>>>
>>>> --------------------------------------------------------------------------------------
>>>> On Fri, Mar 5, 2010 at 7:56 PM, Richard Beare <richard.beare at gmail.com>
>>>> wrote:
>>>> > Good initialization is essential for all registration, with the
>>>> > rotation component often the most critical. If the rotation is greater
>>>> > than 15 degrees then you're probably going to have trouble.
>>>> >
>>>> > If you're trying to build an automated process rather than a one off,
>>>> > then here are some options.
>>>> >
>>>> > Moments based initialization as a first step. This is good if the
>>>> > scene is reasonably simple, or you have masks defining the regions of
>>>> > interest. You can check how similar the major moments are. If they are
>>>> > sufficiently dissimilar then the initialization is likely to be
>>>> > accurate along the major axis, but potentially flipped. In this case
>>>> > you need to try both options and select the one that gives the best
>>>> > resulting cost. If the moments are similar then the initialization
>>>> > will be unreliable and sensitive to small changes, so you need to try
>>>> > a series of angles covering the entire 360 degrees and select the best
>>>> > result as defined by your cost metric.
>>>> >
>>>> > On Sat, Mar 6, 2010 at 11:45 AM, Darren Weber
>>>> > <darren.weber.lists at gmail.com> wrote:
>>>> >>
>>>> >> I've got a couple of images that clearly need nearly 180 degree
>>>> >> rotation for
>>>> >> registration, see:
>>>> >> ftp://anonymous@ftp.buckinstitute.org/dweber/section0004_w1.tif
>>>> >> ftp://anonymous@ftp.buckinstitute.org/dweber/section0005_w1.tif
>>>> >> The registration fails to rotate the images into alignment. I'm
>>>> >> using:
>>>> >> // Registration components
>>>> >> #include "itkImageRegistrationMethod.h"
>>>> >> #include "itkMeanSquaresImageToImageMetric.h"
>>>> >> #include "itkLinearInterpolateImageFunction.h"
>>>> >> #include "itkRegularStepGradientDescentOptimizer.h"
>>>> >> // Transforms
>>>> >> #include "itkCenteredRigid2DTransform.h"
>>>> >> #include "itkCenteredTransformInitializer.h"
>>>> >>
>>>> >> What can I do about it? Have I selected the wrong transform for
>>>> >> rotations?
>>>> >> I've prepared a package of my test program and data for download
>>>> >> here:
>>>> >>
>>>> >> ftp://anonymous@ftp.buckinstitute.org/dweber/itkRegistrationTest.tar.gz
>>>> >> The program is built against ITK 3.16 (and it uses Boost).
>>>> >> TIA,
>>>> >> Darren
>>>> >>
>>>> >> _____________________________________
>>>> >> Powered by www.kitware.com
>>>> >>
>>>> >> Visit other Kitware open-source projects at
>>>> >> http://www.kitware.com/opensource/opensource.html
>>>> >>
>>>> >> Kitware offers ITK Training Courses, for more information visit:
>>>> >> http://www.kitware.com/products/protraining.html
>>>> >>
>>>> >> Please keep messages on-topic and check the ITK FAQ at:
>>>> >> http://www.itk.org/Wiki/ITK_FAQ
>>>> >>
>>>> >> Follow this link to subscribe/unsubscribe:
>>>> >> http://www.itk.org/mailman/listinfo/insight-users
>>>> >>
>>>> >>
>>>> > _____________________________________
>>>> > Powered by www.kitware.com
>>>> >
>>>> > Visit other Kitware open-source projects at
>>>> > http://www.kitware.com/opensource/opensource.html
>>>> >
>>>> > Kitware offers ITK Training Courses, for more information visit:
>>>> > http://www.kitware.com/products/protraining.html
>>>> >
>>>> > Please keep messages on-topic and check the ITK FAQ at:
>>>> > http://www.itk.org/Wiki/ITK_FAQ
>>>> >
>>>> > Follow this link to subscribe/unsubscribe:
>>>> > http://www.itk.org/mailman/listinfo/insight-users
>>>> >
>>>
>>
>
>
More information about the Insight-users
mailing list