[Insight-developers] updating tests to deal with pixel-centered coordinates

Michel Audette michel.audette at kitware.com
Fri May 29 17:14:42 EDT 2009


Dear gents,

I've updated, but have not committed itkWarpImageFilterTest.cxx to account
for new behaviour related to pixel-centered coordinates.

There were two types of mismatch that were causing failures, related to a
comparison between the pixel value returned by the output Iterator outIter
(spanning a larger image than the input iterator), and the value returned by
. These tests have a pattern, evaluated with an analytical function
Evaluate() part of an ImagePattern helper class, that is first evaluated at
inputIndex, prior to some expansion characterized by a variable factors[].
This expansion also involves padding the outer edge with some padValue (=4
in this case), if (m_Interpolator->IsInsideBuffer( point ) ) returns false
in itkWarpImageFilter.txx, in testing the output Image. If inside, the pixel
is assigned a value m_Interpolator->Evaluate( point ), which is an
interpolation as usual for "fully inside" pixels, but works out to
nearest-neighbour for the half-pixel outer band that now can now occur.

For example, a 64x64 image scales by (2,3) to a 128x192 image, where
(0-63,0-63) map to (0-127,0-191). Here, (127,y) coincides with (63.5,y/3),
so m_Interpolator->IsInsideBuffer( point ) correctly returns false: it is
outside the tolerated outer half-pixel band. (x,191) coincides with (x/2,
63.67) is also out. These 2 types of points get a padValue asssigned to
them.
(x,190) is seen as inside by this test, but is beyond (x,189) that maps to
(x/2,63) in the input image: it is in the outer half-band. It should get the
same intensity value as (x,189).
The first type of mismatch was due to inconsistencies between the IsInside()
used in itkWarpImageFilterTest.cxx, and (m_Interpolator->IsInsideBuffer(
point ) ) in itkWarpImageFilter.txx: the two methods could not agree on a
point being inside the image. The logic had to be consistent in assigning a
padValue to a pixel, which involves tweaking the validSize logic, as well as
passing the validSize parameter to pattern.Evaluate(). The 2nd type of
mismatch involves a point that is on that half-pixel band, which involves
determining a clampSize parameter, outside of which the intensity value is
clamped at that value, and passing that parameter to pattern.Evaluate as
well.

Unless this is done (i.e.: Evaluate() modified to handle these areas
explicitly), I don't see a way of reconciling the differences between 2 sets
of regression values, given the inconsistencies in inside-ness, as well as
the nearest-neighbour behaviour of the interpolator in the outer half-pixel
band. See code snippet below.

    {
    validSize[j] = size[j] * factors[j];

    //Consider as inside anything < 1/2 pixel of (size[j]-1)*factors[j]
    //(0-63) map to (0,126), with 127 exactly at 1/2 pixel, therefore
    //edged out; or to (0,190), with 190 just beyond 189 by 1/3 pixel;
    //or to (0,253), with 254 exactly at 1/2 pixel, therefore out
    //also; or (0, 317), with 317 at 2/5 pixel beyond 315. And so on.

    decrementForScaling[j] =   factors[j] / 2 ;

    validSize[j] -= decrementForScaling[j];

    //This part of logic determines what is inside, but in outer
    //1/2 pixel band, which has to be clamped to that nearest outer
    //pixel scaled by factor: (0,63) maps to (0,190) as inside, but
    //pixel 190 is outside of (0,189), and must be clamped to it.
    //If factor is 2 or less, this decrement has no effect.

    clampSizeDecrement[j]  =  (factors[j] - 1 - decrementForScaling[j]) ;

    if (clampSizeDecrement[j] < 0)
      {
      clampSizeDecrement[j] = 0;
      }
    clampSize[j]= validSize[j] - clampSizeDecrement[j];
    }



    double Evaluate( const IndexType& index , const SizeType& size,
                     const SizeType& clampSize, const PixelType& padValue)
    {
    double accum = offset;
    for( int j = 0; j < VDimension; j++ )
      {
#ifdef ITK_USE_CENTERED_PIXEL_COORDINATES_CONSISTENTLY
         if ( index[j] < size[j] )
           {
           if ( index[j] >= clampSize[j] )
             {
             //Interpolators behave this way in half-pixel band at image
perimeter
             accum += coeff[j] * (double) (clampSize[j]-1);
             }
           else
             {
             accum += coeff[j] * (double) index[j];
             }
           }
         else
           {
           accum = padValue;
           break;
           }
#else
         accum += coeff[j] * (double) index[j];

#endif
      }

    return accum;
      }

 This fix was tested with itkWarpImageFilterTest with factors {2,3}, {2,4}
and {2,5}, all successfully. If no one objects, I'll check this test, as
well as fix the other tests in that spirit.

Cheers,

Michel

-- 
Michel Audette, Ph.D.
R & D Engineer,
Kitware Inc.,
Chapel Hill, N.C.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.itk.org/mailman/private/insight-developers/attachments/20090529/10cc477b/attachment.htm>


More information about the Insight-developers mailing list