[Elastix] 2D/3D registration memory issue

M.Staring at lumc.nl M.Staring at lumc.nl
Mon Jul 2 14:35:46 CEST 2012

Hi Vivien,

Yes, NormalizedGradientCorrelation as a metric could be used more generically indeed, also for nD-nD registration. It would require some recoding though, since the current code is only suitable for 2D-3D. Maybe we should add some documentation to the header file explaining this.

I am ok with the temporary solution. Could you document in your fix that this is a bit of a hack and what would be needed to implement a better solution?

Thanks for your efforts, Marius

-----Original Message-----
From: Vivien Delmon [mailto:vivien.delmon at creatis.insa-lyon.fr] 
Sent: maandag 2 juli 2012 13:30
To: Staring, M. (LKEB)
Cc: elastix at bigr.nl
Subject: Re: [Elastix] 2D/3D registration memory issue

On 07/02/2012 11:49 AM, M.Staring at lumc.nl wrote:
> Hi Vivien,
> The NormalizedGradientCorrelationImageToImageMetric was indeed developed for 2D/3D registration only. See the elx*.hxx file, the function BeforeRegistration(), where this is checked. I don't think more checks are needed.

I missed it. The itk file seemed generic.

> The unchecked dynamic cast is indeed a bug. Would you care to implement a check for the correct type?

I will add this check.

> ---
> The advanced image to image metric indeed does not respect the boolean m_ComputeGradient in case the interpolator is not a B-spline. The reason for this was that the B-spline interpolators have a function to compute the derivative, and the other interpolators don't, so for non B-spline interpolators we needed to compute a gradient image serving as the moving image derivative dM/dx during registration.
> So, what we have is:
> 1) SetComputeGradient (true), which calls the ComputeGradient function, which can be overloaded in derived classes. ITK implements a Gaussian derivative.
> 2) SetComputeGradient (false)
> 	a) Interpolator is B-spline, no gradient image computed
> 	b) Interpolator is not B-spline, a central difference derivative is 
> computed
> However, for 2D/3D registration the NormalizedGradientCorrelationImageToImageMetric does not use the GradientImage, and its interpolator is always the ray-casting one.
> What we could do to fix this situation is to implement an else if case 2c:
> 	c) Interpolator is ray cast, no gradient image is computed also.
> I think however, this would be a temporary solution. I can imagine other (2D-3D or nD-nD) metrics that use the ray cast interpolator but also the gradient image.

I will implement the temporary solution

> So, what if we change the CheckForBSplineInterpolator() function from AdvancedImageToImageMetric to never compute a gradient image. Then we overload the ComputeGradient function in AdvancedImageToImageMetric to implement a central difference derivative (I think we did not want to use the Gaussian derivative model from the ITK anyway, since it introduces blurring). This way whenever the Boolean ComputeGradient is false, nothing is computed. The only problem we then still have is that the linear interpolator does not have gradients. (The nearest neighbour interpolator does not have a good definition of derivatives anyway.) This could then be solved by setting SetComputeGradient (true) for the linear interpolator, which can be done in its elx file, BeforeRegistration().
> How does that sound? Am I missing something?

This solution is the one I was thinking of.

> Regards, Marius
> -----Original Message-----
> From: elastix-bounces at bigr.nl [mailto:elastix-bounces at bigr.nl] On 
> Behalf Of Vivien Delmon
> Sent: dinsdag 26 juni 2012 15:43
> To: elastix at bigr.nl
> Subject: Re: [Elastix] 2D/3D registration memory issue
> On 06/22/2012 09:43 AM, M.Staring at lumc.nl wrote:
>> Hi,
>> Should we then not just use the ITK version Get/SetComputeGradient, and overload the ComputeGradient function? This is done for example in the kappa statistics metric.
>> My 2c, Marius
> Hi,
> The NormalizedGradientCorrelationImageToImageMetric written in elastix seems to be 2D/3D only since it cast the interpolator into a RayCastInterpolator without checking if the dynamic cast return null.
>    85   /** Resampling for 3D->2D */
>    86   this->m_TransformMovingImageFilter->SetTransform(
>    87     dynamic_cast<RayCastInterpolatorType *>(
>    88     const_cast<  InterpolatorType *>( ( this->GetInterpolator() ) )
> )->GetTransform() );
> What I propose is :
> - test for RayCastInterpolator in the constructor to set a boolean to 
> know if we are in 2D/3D mode
> - protect the resampling to SetTransform only in 2D/3D mode
> - To prevent gradient computation we have two different options :
> 1) A test in AdvancedImageToImageMetric as for BSplines
> 2) SetComputeGradient( true ); and overload the ComputeGradient function with an empty function.
> I don't really like the second solution which set ComputeGradient to true and then does not compute it. But if I set it to false the AdvancedImageToImageMetric will compute it. I don't understand why the AdvancedImageToImageMetric does not overload ComputeGradient allowing sub class to decide if they want it or not. In fact there is no more way to tell elastix not to compute the gradient image :
> SetComputeGradient (true) = compute with the itk way 
> SetComputeGradient (false) = compute with the elastix way
>> -----Original Message-----
>> From: elastix-bounces at bigr.nl [mailto:elastix-bounces at bigr.nl] On 
>> Behalf Of Stefan Klein
>> Sent: donderdag 21 juni 2012 23:01
>> To: elastix at bigr.nl
>> Subject: Re: [Elastix] 2D/3D registration memory issue
>> Hi Vivien,
>> That's a bit silly indeed. It should be possible for inheriting Metrics to turn this off. In a similar way as we set in the constructor of each metric whether the metric will use an ImageSampler or not.
>> It propose you add a private boolean member variable m_PrecomputeGradientImage for that, with a Set/Get function. (in the AdvancedImageToImageMetric). Then by default we can leave it true, since most metrics require it (and anyway it is only done when the interpolator is not a bsplineinterpolator), but the 2d/3d metrics can turn it off in their constructor.
>> Note that the ITK also already defines a similar method Get/SetComputeGradient, because the ITK ImageToImageMetric provides a similar "service" to compute a gradient image for you (but it does that with gaussian derivatives).
>> Kind regards,
>> Stefan
>> On 21-6-2012 15:53, Vivien Delmon wrote:
>>> Hi all,
>>> I am trying to register a set of projections coming from a CBCT 
>>> whith a CT using the parameter files of your wiki (Par0013). When I 
>>> use multiple images the memory consuption become a problem. I 
>>> investigated to find what is consuming so much memory and it seems 
>>> to come from the gradient computation on the moving image which is 
>>> computed once for every fixed image in :
>>> AdvancedImageToImageMetric<TFixedImage,TMovingImage>
>>> ::CheckForBSplineInterpolator (void)
>>> I don't understand why this gradient is needed for 2D/3D 
>>> registration and even if it is needed, is there a way to compute it only once ?
> --
> Vivien Delmon
> PhD student at CREATIS, Lyon
> Supported by ANRT and ELEKTA
> http://www.creatis.insa-lyon.fr/rio
> A: Because it messes up the order in which people normally read text.
> Q: Why is top-posting such a bad thing?
> A: Top-posting.
> Q: What is the most annoying thing in e-mail?
> _______________________________________________
> Elastix mailing list
> Elastix at bigr.nl
> http://lists.bigr.nl/cgi-bin/mailman/listinfo/elastix

Vivien Delmon
PhD student at CREATIS, Lyon
Supported by ANRT and ELEKTA

Bibliothèque logicielle :
On retrouve parfois le terme librairie issu du faux ami anglais library.
Librairie se traduisant bookshop en anglais c'est donc un abus de langage et une erreur. (Wikipedia)

More information about the Elastix mailing list