FastCubicBSplineInterpolateImageFunction.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2013-2015 Imperial College London
5  * Copyright 2013-2015 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_FastCubicBSplineInterpolateImageFunction_H
21 #define MIRTK_FastCubicBSplineInterpolateImageFunction_H
22 
23 #include "mirtk/BaseImage.h"
24 #include "mirtk/InterpolateImageFunction.h"
25 #include "mirtk/MirrorExtrapolateImageFunction.h"
26 
27 
28 namespace mirtk {
29 
30 
31 // Jacobian matrix type
32 class Matrix;
33 
34 // Interpolation kernel
35 template <class T> class BSpline;
36 
37 
38 /**
39  * Fast cubic B-spline interpolation of generic image
40  *
41  * Note that the coefficient, i.e., input voxel type may also be a vector
42  * type such as Vector3D in particular. This is required by the B-spline
43  * free-form transformations. If the input image contains the cubic B-spline
44  * interpolation coefficients already, make sure that the VoxelType template
45  * argument matches the voxel type of the input image to avoid an unnecessary
46  * copy of the input image. This image function will use the memory of the
47  * input image directly to access the coefficients in this case.
48  */
49 template <class TImage>
51 : public GenericInterpolateImageFunction<TImage>
52 {
53  mirtkGenericInterpolatorMacro(
55  Interpolation_FastCubicBSpline
56  );
57 
58  // ---------------------------------------------------------------------------
59  // Types
60 
61 public:
62 
66  typedef BSpline<Real> Kernel;
67 
68  // ---------------------------------------------------------------------------
69  // Attributes
70 
71  /// Input image contains spline coefficients
72  mirtkAttributeMacro(bool, UseInputCoefficients);
73 
74  /// Image of spline coefficients
75  mirtkAttributeMacro(CoefficientImage, Coefficient);
76 
77  /// Infinite discrete coefficient image obtained by extrapolation
78  mirtkAggregateMacro(CoefficientExtrapolator, InfiniteCoefficient);
79 
80 protected:
81 
82  /// Strides for fast iteration over coefficient image
83  int _s2, _s3, _s4;
84 
85 public:
86 
87  // ---------------------------------------------------------------------------
88  // Construction/Destruction
89 
90  /// Constructor
92 
93  /// Destructor
95 
96  /// Initialize image function
97  virtual void Initialize(bool = false);
98 
99  /// Update spline coefficients
100  virtual void Update();
101 
102  // ---------------------------------------------------------------------------
103  // Domain checks
104 
105  /// Returns interval of discrete image indices whose values are needed for
106  /// interpolation of the image value at a given continuous coordinate
107  virtual void BoundingInterval(double, int &, int &) const;
108 
109  // ---------------------------------------------------------------------------
110  // Evaluation
111 
112  /// Get value of given 2D image at arbitrary location (in pixels)
113  ///
114  /// This function is used to interpolate the image value at arbitrary
115  /// locations when no extrapolator was set.
116  VoxelType Get2D(double, double, double = 0, double = 0) const;
117 
118  /// Get value of given 2D image at arbitrary location (in pixels)
119  ///
120  /// This function is used to only interpolate foreground image values.
121  /// If fully outside the foreground region, the _DefaultValue is returned.
122  VoxelType GetWithPadding2D(double, double, double = 0, double = 0) const;
123 
124  /// Get value of given 2D image at arbitrary location (in pixels)
125  ///
126  /// If the location is inside the finite domain of the image, an actual image
127  /// instance can be passed as first argument directly such as an instance of
128  /// GenericImage. Otherwise, an image function which extends the finite
129  /// image domain to an infinite lattice is needed, i.e., an instance of a
130  /// subclass of ExtrapolateImageFunction.
131  template <class TOtherImage> typename TOtherImage::VoxelType
132  Get2D(const TOtherImage *, double, double, double = 0, double = 0) const;
133 
134  /// Get value of given 2D image at arbitrary location (in pixels)
135  ///
136  /// This function is used to only interpolate foreground image values.
137  /// If fully outside the foreground region, the _DefaultValue is returned.
138  ///
139  /// If the location is inside the finite domain of the image, an actual image
140  /// instance can be passed as first argument directly such as an instance of
141  /// GenericImage. Otherwise, an image function which extends the finite
142  /// image domain to an infinite lattice is needed, i.e., an instance of a
143  /// subclass of ExtrapolateImageFunction.
144  template <class TOtherImage, class TCoefficient> typename TCoefficient::VoxelType
145  GetWithPadding2D(const TOtherImage *, const TCoefficient *,
146  double, double, double = 0, double = 0) const;
147 
148  /// Get value of given 3D image at arbitrary location (in pixels)
149  ///
150  /// This function is used to interpolate the image value at arbitrary
151  /// locations when no extrapolator was set.
152  VoxelType Get3D(double, double, double = 0, double = 0) const;
153 
154  /// Get value of given 3D image at arbitrary location (in pixels)
155  ///
156  /// This function is used to only interpolate foreground image values.
157  /// If fully outside the foreground region, the _DefaultValue is returned.
158  VoxelType GetWithPadding3D(double, double, double = 0, double = 0) const;
159 
160  /// Get value of given 3D image at arbitrary location (in pixels)
161  ///
162  /// If the location is inside the finite domain of the image, an actual image
163  /// instance can be passed as first argument directly such as an instance of
164  /// GenericImage. Otherwise, an image function which extends the finite
165  /// image domain to an infinite lattice is needed, i.e., an instance of a
166  /// subclass of ExtrapolateImageFunction.
167  template <class TOtherImage> typename TOtherImage::VoxelType
168  Get3D(const TOtherImage *, double, double, double = 0, double = 0) const;
169 
170  /// Get value of given 3D image at arbitrary location (in pixels)
171  ///
172  /// This function is used to only interpolate foreground image values.
173  /// If fully outside the foreground region, the _DefaultValue is returned.
174  ///
175  /// If the location is inside the finite domain of the image, an actual image
176  /// instance can be passed as first argument directly such as an instance of
177  /// GenericImage. Otherwise, an image function which extends the finite
178  /// image domain to an infinite lattice is needed, i.e., an instance of a
179  /// subclass of ExtrapolateImageFunction.
180  template <class TOtherImage, class TCoefficient> typename TCoefficient::VoxelType
181  GetWithPadding3D(const TOtherImage *, const TCoefficient *,
182  double, double, double = 0, double = 0) const;
183 
184  /// Get value of given 4D image at arbitrary location (in pixels)
185  ///
186  /// This function is used to interpolate the image value at arbitrary
187  /// locations when no extrapolator was set.
188  VoxelType Get4D(double, double, double = 0, double = 0) const;
189 
190  /// Get value of given 4D image at arbitrary location (in pixels)
191  ///
192  /// This function is used to only interpolate foreground image values.
193  /// If fully outside the foreground region, the _DefaultValue is returned.
194  VoxelType GetWithPadding4D(double, double, double = 0, double = 0) const;
195 
196  /// Get value of given 4D image at arbitrary location (in pixels)
197  ///
198  /// If the location is inside the finite domain of the image, an actual image
199  /// instance can be passed as first argument directly such as an instance of
200  /// GenericImage. Otherwise, an image function which extends the finite
201  /// image domain to an infinite lattice is needed, i.e., an instance of a
202  /// subclass of ExtrapolateImageFunction.
203  template <class TOtherImage> typename TOtherImage::VoxelType
204  Get4D(const TOtherImage *, double, double, double = 0, double = 0) const;
205 
206  /// Get value of given 4D image at arbitrary location (in pixels)
207  ///
208  /// This function is used to only interpolate foreground image values.
209  /// If fully outside the foreground region, the _DefaultValue is returned.
210  ///
211  /// If the location is inside the finite domain of the image, an actual image
212  /// instance can be passed as first argument directly such as an instance of
213  /// GenericImage. Otherwise, an image function which extends the finite
214  /// image domain to an infinite lattice is needed, i.e., an instance of a
215  /// subclass of ExtrapolateImageFunction.
216  template <class TOtherImage, class TCoefficient> typename TCoefficient::VoxelType
217  GetWithPadding4D(const TOtherImage *, const TCoefficient *,
218  double, double, double = 0, double = 0) const;
219 
220  /// Get value of given image at arbitrary location (in pixels)
221  ///
222  /// This function is used to interpolate the image value at arbitrary
223  /// locations when no extrapolator was set.
224  VoxelType Get(double, double, double = 0, double = 0) const;
225 
226  /// Get value of given image at arbitrary location (in pixels)
227  ///
228  /// This function is used to only interpolate foreground image values.
229  /// If fully outside the foreground region, the _DefaultValue is returned.
230  virtual VoxelType GetWithPadding(double, double, double = 0, double = 0) const;
231 
232  /// Get value of given image at arbitrary location (in pixels)
233  ///
234  /// If the location is inside the finite domain of the image, an actual image
235  /// instance can be passed as first argument directly such as an instance of
236  /// GenericImage. Otherwise, an image function which extends the finite
237  /// image domain to an infinite lattice is needed, i.e., an instance of a
238  /// subclass of ExtrapolateImageFunction.
239  template <class TOtherImage> typename TOtherImage::VoxelType
240  Get(const TOtherImage *, double, double, double = 0, double = 0) const;
241 
242  /// Get value of given image at arbitrary location (in pixels)
243  ///
244  /// This function is used to only interpolate foreground image values.
245  /// If fully outside the foreground region, the _DefaultValue is returned.
246  ///
247  /// If the location is inside the finite domain of the image, an actual image
248  /// instance can be passed as first argument directly such as an instance of
249  /// GenericImage. Otherwise, an image function which extends the finite
250  /// image domain to an infinite lattice is needed, i.e., an instance of a
251  /// subclass of ExtrapolateImageFunction.
252  template <class TOtherImage, class TCoefficient> typename TCoefficient::VoxelType
253  GetWithPadding(const TOtherImage *, const TCoefficient *,
254  double, double, double = 0, double = 0) const;
255 
256  /// Evaluate generic 2D image without handling boundary conditions
257  virtual VoxelType GetInside2D(double, double, double = 0, double = 0) const;
258 
259  /// Evaluate generic 3D image without handling boundary conditions
260  virtual VoxelType GetInside3D(double, double, double = 0, double = 0) const;
261 
262  /// Evaluate generic 4D image without handling boundary conditions
263  virtual VoxelType GetInside4D(double, double, double = 0, double = 0) const;
264 
265  /// Evaluate generic image without handling boundary conditions
266  ///
267  /// This version is faster than EvaluateOutside, but is only defined inside
268  /// the domain for which all image values required for interpolation are
269  /// defined and thus require no extrapolation of the finite image.
270  virtual VoxelType GetInside(double, double, double = 0, double = 0) const;
271 
272  /// Evaluate generic image at an arbitrary location (in pixels)
273  virtual VoxelType GetOutside(double, double, double = 0, double = 0) const;
274 
275  /// Evaluate generic image without handling boundary conditions
276  ///
277  /// This function is used to only interpolate foreground image values.
278  /// If fully outside the foreground region, the _DefaultValue is returned.
279  ///
280  /// This version is faster than GetWithPaddingOutside, but is only defined
281  /// inside the domain for which all image values required for interpolation
282  /// are defined and thus require no extrapolation of the finite image.
283  virtual VoxelType GetWithPaddingInside(double, double, double = 0, double = 0) const;
284 
285  /// Evaluate generic image at an arbitrary location (in pixels)
286  ///
287  /// This function is used to only interpolate foreground image values.
288  /// If fully outside the foreground region, the _DefaultValue is returned.
289  virtual VoxelType GetWithPaddingOutside(double, double, double = 0, double = 0) const;
290 
291  // ---------------------------------------------------------------------------
292  // Derivative evaluation
293 
294  /// Get 1st order derivatives of given 2D image at arbitrary location (in pixels)
295  ///
296  /// This function is used when no extrapolator was set.
297  void Jacobian2D(Matrix &, double, double, double = 0, double = 0) const;
298 
299  /// Get 1st order derivatives of given 2D image at arbitrary location (in pixels)
300  ///
301  /// If the location is inside the finite domain of the image, an actual image
302  /// instance can be passed as first argument directly such as an instance of
303  /// GenericImage. Otherwise, an image function which extends the finite
304  /// image domain to an infinite lattice is needed, i.e., an instance of a
305  /// subclass of ExtrapolateImageFunction.
306  template <class TOtherImage>
307  void Jacobian2D(Matrix &, const TOtherImage *, double, double, double = 0, double = 0) const;
308 
309  /// Get 1st order derivatives of given 3D image at arbitrary location (in pixels)
310  ///
311  /// This function is used when no extrapolator was set.
312  void Jacobian3D(Matrix &, double, double, double = 0, double = 0) const;
313 
314  /// Get 1st order derivatives of given 3D image at arbitrary location (in pixels)
315  ///
316  /// If the location is inside the finite domain of the image, an actual image
317  /// instance can be passed as first argument directly such as an instance of
318  /// GenericImage. Otherwise, an image function which extends the finite
319  /// image domain to an infinite lattice is needed, i.e., an instance of a
320  /// subclass of ExtrapolateImageFunction.
321  template <class TOtherImage>
322  void Jacobian3D(Matrix &, const TOtherImage *, double, double, double = 0, double = 0) const;
323 
324  /// Get 1st order derivatives of given 4D image at arbitrary location (in pixels)
325  ///
326  /// This function is used when no extrapolator was set.
327  void Jacobian4D(Matrix &, double, double, double = 0, double = 0) const;
328 
329  /// Get 1st order derivatives of given 4D image at arbitrary location (in pixels)
330  ///
331  /// If the location is inside the finite domain of the image, an actual image
332  /// instance can be passed as first argument directly such as an instance of
333  /// GenericImage. Otherwise, an image function which extends the finite
334  /// image domain to an infinite lattice is needed, i.e., an instance of a
335  /// subclass of ExtrapolateImageFunction.
336  template <class TOtherImage>
337  void Jacobian4D(Matrix &, const TOtherImage *, double, double, double = 0, double = 0) const;
338 
339  /// Get 1st order derivatives of given image at arbitrary location (in pixels)
340  void Jacobian(Matrix &, double, double, double = 0, double = 0) const;
341 
342  /// Get 1st order derivatives of given image at arbitrary location (in pixels)
343  ///
344  /// If the location is inside the finite domain of the image, an actual image
345  /// instance can be passed as first argument directly such as an instance of
346  /// GenericImage. Otherwise, an image function which extends the finite
347  /// image domain to an infinite lattice is needed, i.e., an instance of a
348  /// subclass of ExtrapolateImageFunction.
349  template <class TOtherImage>
350  void Jacobian(Matrix &, const TOtherImage *, double, double, double = 0, double = 0) const;
351 
352  /// Get 1st order derivatives of given image at arbitrary location (in pixels)
353  virtual void EvaluateJacobianInside(Matrix &, double, double, double = 0, double = 0) const;
354 
355  /// Get 1st order derivatives of given image at arbitrary location (in pixels)
356  virtual void EvaluateJacobianOutside(Matrix &, double, double, double = 0, double = 0) const;
357 
358 };
359 
360 
361 /**
362  * Fast cubic B-spline interpolation of any scalar image
363  */
366 {
368 
369 public:
370 
371  /// Constructor
373 
374 };
375 
376 
377 } // namespace mirtk
378 
379 #endif // MIRTK_FastCubicBSplineInterpolateImageFunction_H
virtual void EvaluateJacobianOutside(Matrix &, double, double, double=0, double=0) const
Get 1st order derivatives of given image at arbitrary location (in pixels)
void Jacobian4D(Matrix &, double, double, double=0, double=0) const
VoxelType GetWithPadding2D(double, double, double=0, double=0) const
void Jacobian3D(Matrix &, double, double, double=0, double=0) const
virtual VoxelType GetInside4D(double, double, double=0, double=0) const
Evaluate generic 4D image without handling boundary conditions.
VoxelType GetWithPadding4D(double, double, double=0, double=0) const
virtual void EvaluateJacobianInside(Matrix &, double, double, double=0, double=0) const
Get 1st order derivatives of given image at arbitrary location (in pixels)
virtual VoxelType GetWithPaddingInside(double, double, double=0, double=0) const
virtual VoxelType GetInside3D(double, double, double=0, double=0) const
Evaluate generic 3D image without handling boundary conditions.
void Jacobian(Matrix &, double, double, double=0, double=0) const
Get 1st order derivatives of given image at arbitrary location (in pixels)
virtual VoxelType GetWithPadding(double, double, double=0, double=0) const
virtual VoxelType GetWithPaddingOutside(double, double, double=0, double=0) const
Definition: IOConfig.h:41
virtual VoxelType GetOutside(double, double, double=0, double=0) const
Evaluate generic image at an arbitrary location (in pixels)
int _s2
Strides for fast iteration over coefficient image.
mirtkAggregateMacro(CoefficientExtrapolator, InfiniteCoefficient)
Infinite discrete coefficient image obtained by extrapolation.
VoxelType GetWithPadding3D(double, double, double=0, double=0) const
void Jacobian2D(Matrix &, double, double, double=0, double=0) const
virtual VoxelType GetInside(double, double, double=0, double=0) const
mirtkAttributeMacro(bool, UseInputCoefficients)
Input image contains spline coefficients.
virtual VoxelType GetInside2D(double, double, double=0, double=0) const
Evaluate generic 2D image without handling boundary conditions.