[vtkusers] odd vtkImageData interpolation behavior

David Feng dfeng at cs.unc.edu
Fri Jun 20 10:31:04 EDT 2008


David,

I'm not terribly familiar with the inner workings of much of VTK, but 
I'm guessing that somewhere along the line vtkVoxel interpolation is 
used because the z dimension for these data sets is non-zero.  I haven't 
delved any deeper into the code, thought, so I can't be sure.  If I were 
to guess, I'd say that the following lines are related:

  // compute the pixel coordinates and parametric coordinates of point x
  if ( this->ComputeStructuredCoordinates(x, loc, pcoords) == 0 )
    {
    return -1;
    }
  // compute interpolation weights
  this->Voxel->InterpolateFunctions(pcoords,weights);

Looking quickly at the DataDescription variable, a switch statement 
there that goes over the different types (VTK_XZ_PLANE, for example) and 
interpolates with the correct cell type might fix the problem.  
Something like this:

switch (this->DataDescription)
    {
      case VTK_EMPTY:
      default:
        return -1;
        break;
       
      case VTK_SINGLE_POINT: // cellId can only be = 0
        vtkVertex::InterpolationFunctions(pcoords,weights);     
        break;

      case VTK_X_LINE:
      case VTK_Y_LINE:   
      case VTK_Z_LINE:
        vtkLine::InterpolationFunctions(pcoords,weights);
        break;

    
    case VTK_XY_PLANE:     
    case VTK_YZ_PLANE:
    case VTK_XZ_PLANE:
      vtkPixel::InterpolationFunctions(pcoords,weights);
      break;

    case VTK_XYZ_GRID:
     vtkVoxel::InterpolationFunctions(pcoords,weights);
     break;
}

I threw this in there instead of the vtkVoxel interpolation call, and 
this improved the situation a bit, but there were still some apparent 
off-by-one issues on the borders of the interpolated images.  Is there 
someone that usually maintains this file?  If so, s/he can probably fix 
this faster than I can.  If not, I can keep digging.

Thanks,
David

David Gobbi wrote:
> Hi David,
>
> I haven't had time to look at the pertinent sections of vtkImageData.cxx in
> detail, but it certainly sounds like there is a problem.
>
> From my glances at the code, it seems that the cell type should be
> determined from the DataDescription member of vtkImageData, and
> for 2D data, interpolation _should_ be done with vtkPixel cells instead
> of with vtkVoxel cells, i.e. if the code is working the way that it should,
> then your if statements should not be required.  So the question is,
> why is it interpolating with vtkVoxel if the data is 2D?
>
> About the confusion with vtkVoxel having data values at the corners
> instead of at the center (the way that people usually think of voxels),
> that is a VTK-ism and perhaps the name "vtkVoxel" for that cell type
> is misleading.  The "data" in vtkImageData is associated with the
> points in the data, not with the cells, and in most imaging filters
> the cells are ignored completely.
>
>    David
>
>
>
>
> On Thu, Jun 19, 2008 at 3:06 PM, David Feng <dfeng at cs.unc.edu> wrote:
>   
>> I tracked down the problem in vtkImageData's FindCell.  There are actually
>> two:
>>
>> 1 - Even when a dimension is of size 1 (the Y dimension in my case), there
>> is still a voxel cell in that dimension.  The indexing code automatically
>> sets all slice indexing to 0 when it multiplies the z voxel index by
>> (dims[1]-1).  This is fixed with a simple check on the first two dimensions.
>>  If they are of size one, set them to size two.  Obviously it doesn't matter
>> if the dimensions are used in order.
>>
>> 2 - The interpolation weights that a computed before returning from FromCell
>> assume that the dimensions will be used in order.  The values need to be
>> shifted if dimensions are to be ignored.  The shifting is a bit ugly.
>> Both of these problems are fixed by inserting the following code after the
>> InterpolateFunctions function call inside of FindCell, somewhere around line
>> 769 of vtkimagedata.cxx:
>>
>> //
>>  // dimensions are used for cell indexing later.  if a dimension has only
>> one
>>  // voxel, we need to make sure it still has one cell.  Also,
>>  // the coordinate weights need to be shifted to ignore that dimension.
>>  // This is ugly.  The order of these ifs makes a difference.
>>  //
>>
>>  //
>>  // is y trivial?  if so, keep all even blocks of two weights
>>  //
>>  if (dims[1] == 1)
>>   {
>>   dims[1] = 2;
>>   weights[2] = weights[4];
>>   weights[3] = weights[5];
>>   }
>>
>>  //
>>  // is x trivial? if so, keep all even indexed weights
>>  //
>>  if (dims[0] == 1)
>>   {
>>   dims[0] = 2;
>>   weights[1] = weights[2];
>>   weights[2] = weights[4];
>>   weights[3] = weights[6];
>>   }
>>
>> I'll try to make a patch and submit it.
>>
>> David
>>
>> David Feng wrote:
>>     
>>> I was indeed missing something.
>>> I thought that VTK was using cell-centered data, which means that each
>>> voxel contains a single data point at its center.  In fact VTK puts a data
>>> point at every vertex of the voxel.  This means that there is one fewer
>>> voxel in each dimension than there are data points, so the cell indexing was
>>> in fact correct.
>>> I still don't know why my XZ image is not interpolating correctly, though.
>>>
>>> David
>>>
>>> David Feng wrote:
>>>       
>>>> I noticed some odd behavior when interpolating a vtkImageData object.
>>>>  Rather than make a 2D image and rotate it to the XZ plane, I made it a 3D
>>>> image with dimensions (x,1,y).  When I call FindCell simply using the
>>>> world-space pixel coordinates, the interpolated values were not what I
>>>> expected.  Taking a closer look at the function, I noticed the following:
>>>>
>>>> return loc[2] * (dims[0]-1)*(dims[1]-1) +
>>>>         loc[1] * (dims[0]-1) + loc[0];
>>>>
>>>> ...where loc is the interpolated image-space pixel coordinate and dims
>>>> are the dimensions of the image.  The return value is supposed to the 1D
>>>> array index within the image.  With this formula, a pixel location of
>>>> (0,0,5) and (0,0,0) have the same 1D index for an image such as mine (XZ
>>>> instead of XY, with dimensions (x,1,y)).   I haven't looked more closely,
>>>> but indexing into a 3D should actually look like this, if I'm not mistaken:
>>>>
>>>> return loc[2] * dims[0] * dims[1] +
>>>>         loc[1] * dims[0] + loc[0];
>>>>
>>>> I'm not sure why the dimensions are being decremented in the original
>>>> code.  It would seem to make the indexing off by several pixels for each row
>>>> and slice.  When I made the change, I started getting the values I expected.
>>>>  A simple way to test this is to use a vtkProbeFilter to probe an XZ image
>>>> using itself as the input sample points -- without the change, my input is
>>>> different from my output, which should not be the case.   Am I missing
>>>> something?
>>>>
>>>> Thanks,
>>>> David
>>>>
>>>>
>>>>
>>>>         
>>>       
>> _______________________________________________
>> This is the private VTK discussion list.
>> Please keep messages on-topic. Check the FAQ at:
>> http://www.vtk.org/Wiki/VTK_FAQ
>> Follow this link to subscribe/unsubscribe:
>> http://www.vtk.org/mailman/listinfo/vtkusers
>>
>>     





More information about the vtkusers mailing list