[Insight-users] ICP Registration
Luis Ibanez
luis.ibanez at kitware.com
Mon Aug 13 19:00:06 EDT 2007
Hi Zhixi,
1) ICP, as any other registration method requires you to provide
a decent initialization.
The registration will probably not succeed if the two sets
of points are too far apart, or if they are rotated by more
than 10~20 degrees.
The first step that you should consider is to find the translation
that overlap the center of gravity of both point sets. Assuming that
by aligning the centers of gravity the point sets actually get close.
This may not be the case if one of the point sets is a small
subsection of the other pointset, (e.g. if one pointset describes
the surface of the nose, while the other describes the surface of the
entire face.)
Set this translation in the initialization of the Translation.
Second, if you also have an idea of the rough rotation that will
align both datasets, you should also include it in the initialization
of the transform. It doesn't have to be very precise, you can let the
registration method solve a residual rotation of about 10 degrees.
2) In the test that you set up, it seems that the parameters that
control the convergence are not stringent enough. Usually you can
determine this by adding an observer to the optimizer and printing
out the values of the metric. If you find that the optimizer ran
too few iterations, and the metric value is still high, then you
can suspect that the tolerances are too high.
The three tolerance values (interpreted in the context of
ICP registration) are:
valueTolerance = minimum change in the Metric value
gradientTolerance = minimum value in the Metric derivative
epsilonFunction = minimum change in the Transform parameter
This means that
epsilonFunction should correspond to "how precise" do you need
the alignment to be. That is, what is the maximum error in "mm"
that you could accept in the final registration.
valueTolerance : the registration will stop when the change
in value of the Metric, will be smaller than this
tolerance. Since in ICP, your Metric measures the
distance between points, then valueTolerance and
epsilonFunction become conceptually equivalent
gradientTolerance: the registration will stop when the
gradient of the Metric is smaller than this
tolerance.
What you want to do at this point is to reduce the values
of these three tolerances and see how that affects the
number of iterations that the optimizer performs, and
the final value of the Transform.
Note that when you change the values, what you want
to do is to change their order of magnitude. That is,
don't just change
valueTolerance = 1e-4
to
valueTolerance = 0.9e-4
but to
valueTolerance = 1e-8
Note also that the optimizer will stop as soon as
*ANY* of the tolerances passes. Therefore you may
need to tighten the values of *ALL* the three
tolerances before you see any effect.
3) ICP doesn't require the point sets to overlap *BUT*
it requires you to provide a decent initialization,
as described in item (1) above.
Please let us know if you still find any problems
setting up your registration process.
Thanks
Luis
----------
zhixi wrote:
> Hi Luis,
>
> Thanks for your quick reply. I've tried to do more ICP, but it seems like
> the method is giving me incorrect transform parameters. To test the method,
> I made two point sets of 111 points each, basically identical objects
> shifted off in the z direction by 1 voxel (they overlap). The ICP
> registration should give me something like [0, 0, 0, 0, 0, 1]
>
> instead I'm getting this:[-2.7e-9, -9.7e-10, 0.26, 0.27, .55]
>
> these parameters are clearly wrong. Also, If I make the two objects be
> offset such that they do not overlap, the ICP registration gives me 0's for
> the parameters. Is this method only useful for overlapping objects? or are
> there other settings within the code itself that I can tweak to search a
> wider area?
> I ask because my project involves rigidly registering organs from different
> patients. ICP makes sense for my situation, but if it cannot register
> organs that do not overlap in space, then it doesn't do me any good.
>
> Also, Please if you could, explain the convergence criteria in the ICP ex.
> 2:
>
> double gradientTolerance = 1e-4; // convergence criterion
> double valueTolerance = 1e-4; // convergence criterion
> double epsilonFunction = 1e-5; // convergence criterion
>
> what do each of these mean? After playing with different combinations,
> going high and low, varying one at at time, etc, it seems like the
> epsilonFunction is the variable that has the most impact on results.
>
> however, I have not seen a transform parameter after all my tinkering that
> actually looks right.
> Thank you so much for any insight you can provide.
>
> yours,
>
> Zhixi Li
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> Luis Ibanez wrote:
>
>>
>>Hi Zhixi,
>>
>>Yes, you can simply use the transform parameter to initialize
>>the Transform that you will give to the ResampleImageFilter.
>>
>>Note that you should copy also the Center of rotation of the
>>transform, but since here you are planning to reuse the transform
>>object that you employed for the point-based registration, the two
>>lines that you suggested should do the trick:
>>
>>
>> finalTransform->SetParameters( transform->GetParameters() );
>> resample->SetTransform( finalTransform );
>>
>>
>>Please let us know if you find any problems,
>>
>>
>> Thanks,
>>
>>
>> Luis
>>
>>
>>-----------------
>>zhixi wrote:
>>
>>>Hello,
>>>
>>>I am trying to do a rigid registration of two 3D images with ICP.
>>>Following
>>>the ICP ex. 2 in the patented examples folder, I extracted the surface
>>>points of the two images and passed them into the moving and fixed point
>>>containers. Then, using the euler 3d transform and LevenbergMarquatd
>>>optimizer, the ICP algorithm seems to give me 6 parameters for the final
>>>transform in an array form.
>>>
>>>my problem is now the actual resampling of the images.
>>>
>>>my specific question is, can I simply pass the transform parameters into
>>>the
>>>resampler? Will it know what to do with them?
>>>
>>>i.e., with this pathway, where transform->GetParameters() gets me the
>>>transfrom from the ICP.
>>>
>>>
>>>finalTransform->SetParameters( transform->GetParameters() );
>>>
>>>resample->SetTransform( finalTransform );
>>>
>>>
>>>
>>>
>>>
>>>here is my resampling code:
>>>
>>> typedef itk::Image< float, 3 > ImageType_3D;
>>> ImageType_3D::Pointer ITKim_3D1 = ImageType_3D::New();
>>> ImageType_3D::Pointer ITKim_3D2 = ImageType_3D::New();
>>>
>>> Copy_CISImage_to_ITKImage(img3Din1, ITKim_3D1);
>>> Copy_CISImage_to_ITKImage(img3Din2, ITKim_3D2);
>>> typedef itk:: NearestNeighborInterpolateImageFunction <ImageType_3D ,
>>>double> InterpolatorType;
>>> InterpolatorType::Pointer interpolator = InterpolatorType::New();
>>>
>>>
>>> typedef itk::ResampleImageFilter< ImageType_3D, ImageType_3D >
>>>ResampleFilterType;
>>> TransformType::Pointer finalTransform = TransformType::New();
>>>
>>> finalTransform->SetParameters( transform->GetParameters() );
>>>
>>> ResampleFilterType::Pointer resample = ResampleFilterType::New();
>>> resample->SetTransform( finalTransform );
>>> resample->SetInput( ITKim_3D2);
>>> resample->SetSize( ITKim_3D1->GetLargestPossibleRegion().GetSize() );
>>> resample->SetOutputOrigin( ITKim_3D1->GetOrigin() );
>>> resample->SetOutputSpacing( ITKim_3D1->GetSpacing() );
>>> resample->SetDefaultPixelValue( 1 );
>>> resample->SetInterpolator( interpolator );
>>>
>>> resample->Update();
>>> Copy_ITKImage_to_CISImage(resample->GetOutput(), img3Dout );
>>>
>>>
>>>
>>>}
>>>
>>>
>>>Any help is greatly appreciated,
>>>
>>>Zhixi Li
>>
>>_______________________________________________
>>Insight-users mailing list
>>Insight-users at itk.org
>>http://www.itk.org/mailman/listinfo/insight-users
>>
>>
>
>
More information about the Insight-users
mailing list