[Insight-developers] Image functions and interpolators

Lydia Ng lng@insightful.com
Thu, 3 May 2001 14:23:29 -0700


Time has come to do a refactor of ImageFunction's
in general and interpolators in particular.

After discussion with Luis this is the design plan.

There are now two base classes ImageFunction
and ContinousImageFunction.

ImageFunction provide interface Evaluate(IndexType&)
and ContinousImageFunction provide interface
Evaluate(PointType&). Both are templated on the 
input image type.

Image interpolators will then be subclasses of 
ContinousImageFunction.

In registration, we are typically dealing with
geometric points which take into account image
spacing and origin. 
Instead of limiting interpolator to physical 
image we allow spacing and origin to be optionally
set via SetImageSpacing() and SetImageOrigin()
methods in ConstinousImageFunction.

The other issue is efficiency.
In registration, interpolator is called many thousand
of times. 

The design decision is to separate bounds checking
from the evaluation. Typically usage in

while( points to process )
{
  if( interpolator->IsInsideBuffer(point) )
    {
    value = interpolator->Evaluate(point);
    }
  else
   {
    // do something else
    // set to default value etc...
   }
}

In applications, where you know a prior that the point
is within the buffer the checking step can be skipped.
Useful if you have a sequence of things to do at
each point.

Caveats:
Like iterators, both form of ImageFunction may not
operate correctly in a multithreading situation as it
keeps some state information about the size of the image
buffer to facilitate bounds checking. Similar to iterator,
we expect that a new instance of ImageFunction should be
used in each thread.

The buffer information each start position and end
position in geometric coord are computed only at
SetInputImage(ptr). If the image buffer size changes,
SetInputImage has to be evoked again to keep internal
buffer state information.

This is probably not an issue if the interpolator is
created, use and deleted say within ThreadedGenerateData
where the buffer remains the same size.

The other option is to make use of the modification
time - but that is a big performance hit if we
need to check each time we want to interpolate a value.

Comment? Suggestions?

Lydia