You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
379 lines
13 KiB
C
379 lines
13 KiB
C
3 weeks ago
|
/*=========================================================================
|
||
|
|
||
|
Program: Visualization Toolkit
|
||
|
Module: vtkAbstractImageInterpolator.h
|
||
|
|
||
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
||
|
All rights reserved.
|
||
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
||
|
|
||
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
||
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||
|
PURPOSE. See the above copyright notice for more information.
|
||
|
|
||
|
=========================================================================*/
|
||
|
/**
|
||
|
* @class vtkAbstractImageInterpolator
|
||
|
* @brief interpolate data values from images
|
||
|
*
|
||
|
* vtkAbstractImageInterpolator provides an abstract interface for
|
||
|
* interpolating image data. You specify the data set you want to
|
||
|
* interpolate values from, then call Interpolate(x,y,z) to interpolate
|
||
|
* the data.
|
||
|
* @par Thanks:
|
||
|
* Thanks to David Gobbi at the Seaman Family MR Centre and Dept. of Clinical
|
||
|
* Neurosciences, Foothills Medical Centre, Calgary, for providing this class.
|
||
|
* @sa
|
||
|
* vtkImageReslice vtkImageInterpolator vtkImageSincInterpolator
|
||
|
*/
|
||
|
|
||
|
#ifndef vtkAbstractImageInterpolator_h
|
||
|
#define vtkAbstractImageInterpolator_h
|
||
|
|
||
|
#include "vtkImagingCoreModule.h" // For export macro
|
||
|
#include "vtkObject.h"
|
||
|
|
||
|
#define VTK_IMAGE_BORDER_CLAMP 0
|
||
|
#define VTK_IMAGE_BORDER_REPEAT 1
|
||
|
#define VTK_IMAGE_BORDER_MIRROR 2
|
||
|
|
||
|
class vtkDataObject;
|
||
|
class vtkImageData;
|
||
|
class vtkDataArray;
|
||
|
struct vtkInterpolationInfo;
|
||
|
struct vtkInterpolationWeights;
|
||
|
|
||
|
class VTKIMAGINGCORE_EXPORT vtkAbstractImageInterpolator : public vtkObject
|
||
|
{
|
||
|
public:
|
||
|
vtkTypeMacro(vtkAbstractImageInterpolator, vtkObject);
|
||
|
void PrintSelf(ostream& os, vtkIndent indent) override;
|
||
|
|
||
|
/**
|
||
|
* Initialize the interpolator with the data that you wish to interpolate.
|
||
|
*/
|
||
|
virtual void Initialize(vtkDataObject* data);
|
||
|
|
||
|
/**
|
||
|
* Release any data stored by the interpolator.
|
||
|
*/
|
||
|
virtual void ReleaseData();
|
||
|
|
||
|
/**
|
||
|
* Copy the interpolator. It is possible to duplicate an interpolator
|
||
|
* by calling NewInstance() followed by DeepCopy().
|
||
|
*/
|
||
|
void DeepCopy(vtkAbstractImageInterpolator* obj);
|
||
|
|
||
|
/**
|
||
|
* Update the interpolator. If the interpolator has been modified by
|
||
|
* a Set method since Initialize() was called, you must call this method
|
||
|
* to update the interpolator before you can use it.
|
||
|
*/
|
||
|
void Update();
|
||
|
|
||
|
/**
|
||
|
* Get the result of interpolating the specified component of the input
|
||
|
* data, which should be set to zero if there is only one component.
|
||
|
* If the point is not within the bounds of the data set, then OutValue
|
||
|
* will be returned. This method is primarily meant for use by the
|
||
|
* wrapper languages.
|
||
|
*/
|
||
|
double Interpolate(double x, double y, double z, int component);
|
||
|
|
||
|
/**
|
||
|
* Sample the input data. This is an inline method that calls the
|
||
|
* function that performs the appropriate interpolation for the
|
||
|
* data type. If the point is not within the bounds of the data set,
|
||
|
* then the return value is false, and each component will be set to
|
||
|
* the OutValue.
|
||
|
*/
|
||
|
bool Interpolate(const double point[3], double* value);
|
||
|
|
||
|
/**
|
||
|
* The value to return when the point is out of bounds.
|
||
|
*/
|
||
|
void SetOutValue(double outValue);
|
||
|
double GetOutValue() { return this->OutValue; }
|
||
|
|
||
|
/**
|
||
|
* The tolerance to apply when checking whether a point is out of bounds.
|
||
|
* This is a fractional distance relative to the voxel size, so a tolerance
|
||
|
* of 1 expands the bounds by one voxel.
|
||
|
*/
|
||
|
void SetTolerance(double tol);
|
||
|
double GetTolerance() { return this->Tolerance; }
|
||
|
|
||
|
/**
|
||
|
* This method specifies which component of the input will be interpolated,
|
||
|
* or if ComponentCount is also set, it specifies the first component.
|
||
|
* When the interpolation is performed, it will be clamped to the number
|
||
|
* of available components.
|
||
|
*/
|
||
|
void SetComponentOffset(int offset);
|
||
|
int GetComponentOffset() { return this->ComponentOffset; }
|
||
|
|
||
|
/**
|
||
|
* This method specifies the number of components to extract. The default
|
||
|
* value is -1, which extracts all available components. When the
|
||
|
* interpolation is performed, this will be clamped to the number of
|
||
|
* available components.
|
||
|
*/
|
||
|
void SetComponentCount(int count);
|
||
|
int GetComponentCount() { return this->ComponentCount; }
|
||
|
|
||
|
/**
|
||
|
* Compute the number of output components based on the ComponentOffset,
|
||
|
* ComponentCount, and the number of components in the input data.
|
||
|
*/
|
||
|
int ComputeNumberOfComponents(int inputComponents);
|
||
|
|
||
|
/**
|
||
|
* Get the number of components that will be returned when Interpolate()
|
||
|
* is called. This is only valid after initialization. Before then, use
|
||
|
* ComputeNumberOfComponents instead.
|
||
|
*/
|
||
|
int GetNumberOfComponents();
|
||
|
|
||
|
//@{
|
||
|
/**
|
||
|
* A version of Interpolate that takes structured coords instead of data
|
||
|
* coords. Structured coords are the data coords after subtracting the
|
||
|
* Origin and dividing by the Spacing.
|
||
|
*/
|
||
|
void InterpolateIJK(const double point[3], double* value);
|
||
|
void InterpolateIJK(const float point[3], float* value);
|
||
|
//@}
|
||
|
|
||
|
//@{
|
||
|
/**
|
||
|
* Check an x,y,z point to see if it is within the bounds for the
|
||
|
* structured coords of the image. This is meant to be called prior
|
||
|
* to InterpolateIJK. The bounds that are checked against are the input
|
||
|
* image extent plus the tolerance.
|
||
|
*/
|
||
|
bool CheckBoundsIJK(const double x[3]);
|
||
|
bool CheckBoundsIJK(const float x[3]);
|
||
|
//@}
|
||
|
|
||
|
//@{
|
||
|
/**
|
||
|
* The border mode (default: clamp). This controls how out-of-bounds
|
||
|
* lookups are handled, i.e. how data will be extrapolated beyond the
|
||
|
* bounds of the image. The default is to clamp the lookup point to the
|
||
|
* bounds. The other modes wrap around to the opposite boundary, or
|
||
|
* mirror the image at the boundary.
|
||
|
*/
|
||
|
void SetBorderMode(int mode);
|
||
|
void SetBorderModeToClamp() { this->SetBorderMode(VTK_IMAGE_BORDER_CLAMP); }
|
||
|
void SetBorderModeToRepeat() { this->SetBorderMode(VTK_IMAGE_BORDER_REPEAT); }
|
||
|
void SetBorderModeToMirror() { this->SetBorderMode(VTK_IMAGE_BORDER_MIRROR); }
|
||
|
int GetBorderMode() { return this->BorderMode; }
|
||
|
const char* GetBorderModeAsString();
|
||
|
//@}
|
||
|
|
||
|
/**
|
||
|
* Enable sliding window for separable kernels.
|
||
|
* When this is enabled, the interpolator will cache partial sums in
|
||
|
* in order to accelerate the computation. It only makes sense to do
|
||
|
* this if the interpolator is used by calling InterpolateRow() while
|
||
|
* incrementing first the Y, and then the Z index with every call.
|
||
|
*/
|
||
|
void SetSlidingWindow(bool x);
|
||
|
void SlidingWindowOn() { this->SetSlidingWindow(true); }
|
||
|
void SlidingWindowOff() { this->SetSlidingWindow(false); }
|
||
|
bool GetSlidingWindow() { return this->SlidingWindow; }
|
||
|
|
||
|
/**
|
||
|
* Get the support size for use in computing update extents. If the data
|
||
|
* will be sampled on a regular grid, then pass a matrix describing the
|
||
|
* structured coordinate transformation between the output and the input.
|
||
|
* Otherwise, pass nullptr as the matrix to retrieve the full kernel size.
|
||
|
*/
|
||
|
virtual void ComputeSupportSize(const double matrix[16], int support[3]) = 0;
|
||
|
|
||
|
/**
|
||
|
* True if the interpolation is separable, which means that the weights
|
||
|
* can be precomputed in order to accelerate the interpolation. Any
|
||
|
* interpolator which is separable will implement the methods
|
||
|
* PrecomputeWeightsForExtent and InterpolateRow
|
||
|
*/
|
||
|
virtual bool IsSeparable() = 0;
|
||
|
|
||
|
//@{
|
||
|
/**
|
||
|
* If the data is going to be sampled on a regular grid, then the
|
||
|
* interpolation weights can be precomputed. A matrix must be supplied
|
||
|
* that provides a transformation between the provided extent and the
|
||
|
* structured coordinates of the input. This matrix must perform only
|
||
|
* permutation, scale, and translation, i.e. each of the three columns
|
||
|
* must have only one non-zero value. A checkExtent is provided that can
|
||
|
* be used to check which indices in the extent map to out-of-bounds
|
||
|
* coordinates in the input data.
|
||
|
*/
|
||
|
virtual void PrecomputeWeightsForExtent(const double matrix[16], const int extent[6],
|
||
|
int checkExtent[6], vtkInterpolationWeights*& weights);
|
||
|
virtual void PrecomputeWeightsForExtent(const float matrix[16], const int extent[6],
|
||
|
int checkExtent[6], vtkInterpolationWeights*& weights);
|
||
|
//@}
|
||
|
|
||
|
/**
|
||
|
* Free the weights that were provided by PrecomputeWeightsForExtent.
|
||
|
*/
|
||
|
virtual void FreePrecomputedWeights(vtkInterpolationWeights*& weights);
|
||
|
|
||
|
//@{
|
||
|
/**
|
||
|
* Get a row of samples, using the weights that were precomputed
|
||
|
* by PrecomputeWeightsForExtent. Note that each sample may have
|
||
|
* multiple components. It is possible to select which components
|
||
|
* will be returned by setting the ComponentOffset and ComponentCount.
|
||
|
*/
|
||
|
void InterpolateRow(
|
||
|
vtkInterpolationWeights*& weights, int xIdx, int yIdx, int zIdx, double* value, int n);
|
||
|
void InterpolateRow(
|
||
|
vtkInterpolationWeights*& weights, int xIdx, int yIdx, int zIdx, float* value, int n);
|
||
|
//@}
|
||
|
|
||
|
//@{
|
||
|
/**
|
||
|
* Get the spacing of the data being interpolated.
|
||
|
*/
|
||
|
vtkGetVector3Macro(Spacing, double);
|
||
|
//@}
|
||
|
|
||
|
//@{
|
||
|
/**
|
||
|
* Get the origin of the data being interpolated.
|
||
|
*/
|
||
|
vtkGetVector3Macro(Origin, double);
|
||
|
//@}
|
||
|
|
||
|
//@{
|
||
|
/**
|
||
|
* Get the extent of the data being interpolated.
|
||
|
*/
|
||
|
vtkGetVector6Macro(Extent, int);
|
||
|
//@}
|
||
|
|
||
|
//@{
|
||
|
/**
|
||
|
* Get the whole extent of the data being interpolated, including
|
||
|
* parts of the data that are not currently in memory.
|
||
|
*/
|
||
|
VTK_LEGACY(int* GetWholeExtent());
|
||
|
VTK_LEGACY(void GetWholeExtent(int extent[6]));
|
||
|
//@}
|
||
|
|
||
|
protected:
|
||
|
vtkAbstractImageInterpolator();
|
||
|
~vtkAbstractImageInterpolator() override;
|
||
|
|
||
|
/**
|
||
|
* Subclass-specific updates.
|
||
|
*/
|
||
|
virtual void InternalUpdate() = 0;
|
||
|
|
||
|
/**
|
||
|
* Subclass-specific copy.
|
||
|
*/
|
||
|
virtual void InternalDeepCopy(vtkAbstractImageInterpolator* obj) = 0;
|
||
|
|
||
|
//@{
|
||
|
/**
|
||
|
* Get the interpolation functions.
|
||
|
*/
|
||
|
virtual void GetInterpolationFunc(
|
||
|
void (**doublefunc)(vtkInterpolationInfo*, const double[3], double*));
|
||
|
virtual void GetInterpolationFunc(
|
||
|
void (**floatfunc)(vtkInterpolationInfo*, const float[3], float*));
|
||
|
//@}
|
||
|
|
||
|
//@{
|
||
|
/**
|
||
|
* Get the row interpolation functions.
|
||
|
*/
|
||
|
virtual void GetRowInterpolationFunc(
|
||
|
void (**doublefunc)(vtkInterpolationWeights*, int, int, int, double*, int));
|
||
|
virtual void GetRowInterpolationFunc(
|
||
|
void (**floatfunc)(vtkInterpolationWeights*, int, int, int, float*, int));
|
||
|
//@}
|
||
|
|
||
|
//@{
|
||
|
/**
|
||
|
* Get the sliding window interpolation functions.
|
||
|
*/
|
||
|
virtual void GetSlidingWindowFunc(
|
||
|
void (**doublefunc)(vtkInterpolationWeights*, int, int, int, double*, int));
|
||
|
virtual void GetSlidingWindowFunc(
|
||
|
void (**floatfunc)(vtkInterpolationWeights*, int, int, int, float*, int));
|
||
|
//@}
|
||
|
|
||
|
vtkDataArray* Scalars;
|
||
|
double StructuredBoundsDouble[6];
|
||
|
float StructuredBoundsFloat[6];
|
||
|
int Extent[6];
|
||
|
double Spacing[3];
|
||
|
double Origin[3];
|
||
|
double OutValue;
|
||
|
double Tolerance;
|
||
|
int BorderMode;
|
||
|
int ComponentOffset;
|
||
|
int ComponentCount;
|
||
|
bool SlidingWindow;
|
||
|
|
||
|
// information needed by the interpolator funcs
|
||
|
vtkInterpolationInfo* InterpolationInfo;
|
||
|
|
||
|
void (*InterpolationFuncDouble)(
|
||
|
vtkInterpolationInfo* info, const double point[3], double* outPtr);
|
||
|
void (*InterpolationFuncFloat)(vtkInterpolationInfo* info, const float point[3], float* outPtr);
|
||
|
|
||
|
void (*RowInterpolationFuncDouble)(
|
||
|
vtkInterpolationWeights* weights, int idX, int idY, int idZ, double* outPtr, int n);
|
||
|
void (*RowInterpolationFuncFloat)(
|
||
|
vtkInterpolationWeights* weights, int idX, int idY, int idZ, float* outPtr, int n);
|
||
|
|
||
|
private:
|
||
|
vtkAbstractImageInterpolator(const vtkAbstractImageInterpolator&) = delete;
|
||
|
void operator=(const vtkAbstractImageInterpolator&) = delete;
|
||
|
};
|
||
|
|
||
|
inline void vtkAbstractImageInterpolator::InterpolateIJK(const double point[3], double* value)
|
||
|
{
|
||
|
this->InterpolationFuncDouble(this->InterpolationInfo, point, value);
|
||
|
}
|
||
|
|
||
|
inline void vtkAbstractImageInterpolator::InterpolateIJK(const float point[3], float* value)
|
||
|
{
|
||
|
this->InterpolationFuncFloat(this->InterpolationInfo, point, value);
|
||
|
}
|
||
|
|
||
|
inline bool vtkAbstractImageInterpolator::CheckBoundsIJK(const double x[3])
|
||
|
{
|
||
|
const double* bounds = this->StructuredBoundsDouble;
|
||
|
return !((x[0] < bounds[0]) || (x[0] > bounds[1]) || (x[1] < bounds[2]) || (x[1] > bounds[3]) ||
|
||
|
(x[2] < bounds[4]) || (x[2] > bounds[5]));
|
||
|
}
|
||
|
|
||
|
inline bool vtkAbstractImageInterpolator::CheckBoundsIJK(const float x[3])
|
||
|
{
|
||
|
const float* bounds = this->StructuredBoundsFloat;
|
||
|
return !((x[0] < bounds[0]) || (x[0] > bounds[1]) || (x[1] < bounds[2]) || (x[1] > bounds[3]) ||
|
||
|
(x[2] < bounds[4]) || (x[2] > bounds[5]));
|
||
|
}
|
||
|
|
||
|
inline void vtkAbstractImageInterpolator::InterpolateRow(
|
||
|
vtkInterpolationWeights*& weights, int xIdx, int yIdx, int zIdx, double* value, int n)
|
||
|
{
|
||
|
this->RowInterpolationFuncDouble(weights, xIdx, yIdx, zIdx, value, n);
|
||
|
}
|
||
|
|
||
|
inline void vtkAbstractImageInterpolator::InterpolateRow(
|
||
|
vtkInterpolationWeights*& weights, int xIdx, int yIdx, int zIdx, float* value, int n)
|
||
|
{
|
||
|
this->RowInterpolationFuncFloat(weights, xIdx, yIdx, zIdx, value, n);
|
||
|
}
|
||
|
|
||
|
#endif
|