Bounding box of vtkImageData

While trying to find out why vtkProbeFilter often fails when probing a single-slice 3D volume with a line, I’ve found that vtkProbeFilter returns early because it finds that the line’s bounding box does not intersect the volume’s bounding box.

Digging deeper, it turned out that no intersection was found because vtkImageData::ComputeBounds returned 0 thickness if the volume had a single slice** (see code here). So, unless the line endpoints were slightly off, on two sides of a plane centered on the origin, the filter did not consider the line to be inside the image.

I’ve found in a previous discussion about this topic that for vtkImageData “The bounds go from the center of the first voxel to the center of the last voxel. So the code in vtkImageData.cxx is correct.”.

  • Is this really always the case? Anything that is beyond the center of edge voxels are cut off everywhere?
  • If not, then how do we know if a filter operates on the entire image data or just inside the bounds returned by vtkImageData? For example, I don’t think that vtkImageReslice cuts off half of all the edge voxels, but vtkProbeFilter seems to ignore anything outside the bounds.

It may be difficult to change image bounding box behavior now, but at least it should be very clearly documented what is the intended behavior and why. Using that information, we could decide if a particular filter works correctly or must be fixed.

For example, based on the specification, it should be clear how to make probing work on single-slice volumes: fix vtkImageData::GetBounds() (to return the full image region), fix vtkProbeFilter (to use full image region and not the bounds returned by vtkImageData), improve vtkProbeFilter (to use tolerance value in bounding box intersection check), or we should implement workarounds case by case at application level.

@dgobbi @ken-martin

2 Likes

In VTK, the bounds of any data set extend to the outermost sample points of that data set. Image data is no different, it’s been this way ever since the image ComputeBounds() code was first written a quarter century ago.

It wasn’t until 2005 that vtkImageReslice started to extrapolate beyond these bounds to provide its current behavior. There are, of course, specific boundary conditions that define how the extrapolation is performed.

As for vtkProbeFilter, it only does interpolation, not extrapolation, and it does its interpolation using the vtkDataSet cell-based interpolation methods so it isn’t even aware that it is probing an image.

It would be very nice to have a probe filter specifically for probing images, that would use the same vtkImageInterpolator classes that vtkImageReslice uses. Then people could probe images with higher-order interpolation (e.g. cubic spline) and they could handle the boundary conditions however they like. I’ve been considering writing a filter like this for years, but I’ve never had a project that required it.

Just to chime in: We rely on the current behavior of vtkImageData::ComputeBounds in our application, and I’m sure there are others doing the same.

So yes, tread carefully if you’re changing anything in these parts please :slight_smile:

@dgobbi Thanks a lot for the detailed explanation.

This definition of “bounds” is simple and it is always easy to compute, but quite misleading, as in many cases it coincides with actual bounding box of the data set but not always (for example for images and higher-order cells the actual bounding box can be larger).

I understand that it could be hard to change definition of bounds now (and computing points bounds is simple, while computing real bounds can be costly), so I don’t think it would be a good idea to change it, but at least this should be clearly documented so that users and developers do not incorrectly assume that a data set is always contained within its bounds. I’ll send a merge request with proposed API documentation update.

OK, this answers the main question: probe filter should be rewritten to work correctly for images. That new probe filter (and most imaging filters) does not use vtkImageData::GetBounds(), so it is fine that GetBounds() does not return the data set’s actual bounding box.

Yes, of course everyone “relies” on the current implementation in the sense that we could not change it without risking breaking many things. However, to get real boundaries of your image, you don’t use image “bounds” as is, but add half voxels to the bounds here and there.

I’ve been using VTK extensively for image processing and visualization for more than 10 years, but still have not realized this GetBounds behavior and its consequences. Most probably there are a couple of bugs in VTK (similar to the one in vtkProbeFilter) that is caused by this, but of course it is easier to fix them one by one than change image GetBounds behavior globally.

2 Likes