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_CubicBSplineInterpolateImageFunction_H
21 #define MIRTK_CubicBSplineInterpolateImageFunction_H
22 
23 #include "mirtk/BSpline.h"
24 #include "mirtk/BaseImage.h"
25 #include "mirtk/InterpolateImageFunction.h"
26 #include "mirtk/MirrorExtrapolateImageFunction.h"
27 
28 
29 namespace mirtk {
30 
31 
32 /**
33  * Cubic B-spline interpolation of generic image
34  *
35  * Note that the coefficient, i.e., input voxel type may also be a vector
36  * type such as Vector3D in particular. This is required by the B-spline
37  * free-form transformations. If the input image contains the cubic B-spline
38  * interpolation coefficients already, make sure that the VoxelType template
39  * argument matches the voxel type of the input image to avoid an unnecessary
40  * copy of the input image. This image function will use the memory of the
41  * input image directly to access the coefficients in this case.
42  */
43 template <class TImage>
44 class GenericCubicBSplineInterpolateImageFunction
45 : public GenericInterpolateImageFunction<TImage>
46 {
47   mirtkGenericInterpolatorMacro(
48     GenericCubicBSplineInterpolateImageFunction,
49     Interpolation_CubicBSpline
50   );
51 
52   // ---------------------------------------------------------------------------
53   // Types
54 
55 public:
56 
57   typedef GenericImage<RealType>                                   CoefficientImage;
58   typedef GenericExtrapolateImageFunction<CoefficientImage>        CoefficientExtrapolator;
59   typedef GenericMirrorExtrapolateImageFunction<CoefficientImage>  DefaultExtrapolator;
60   typedef BSpline<Real>                                            Kernel;
61 
62   // ---------------------------------------------------------------------------
63   // Attributes
64 
65   /// Input image contains spline coefficients
66   mirtkAttributeMacro(bool, UseInputCoefficients);
67 
68   /// Image of spline coefficients
69   mirtkAttributeMacro(CoefficientImage, Coefficient);
70 
71   /// Infinite discrete coefficient image obtained by extrapolation
72   mirtkAggregateMacro(CoefficientExtrapolator, InfiniteCoefficient);
73 
74 protected:
75 
76   /// Strides for fast iteration over coefficient image
77   int _s2, _s3, _s4;
78 
79 public:
80 
81   // ---------------------------------------------------------------------------
82   // Construction/Destruction
83 
84   /// Constructor
85   GenericCubicBSplineInterpolateImageFunction();
86 
87   /// Destructor
88   virtual ~GenericCubicBSplineInterpolateImageFunction();
89 
90   /// Initialize image function
91   virtual void Initialize(bool = false);
92 
93   /// Update spline coefficients
94   virtual void Update();
95 
96   // ---------------------------------------------------------------------------
97   // Domain checks
98 
99   /// Returns interval of discrete image indices whose values are needed for
100   /// interpolation of the image value at a given continuous coordinate
101   virtual void BoundingInterval(double, int &, int &) const;
102 
103   // ---------------------------------------------------------------------------
104   // Evaluation
105 
106   /// Get value of given 2D image at arbitrary location (in pixels)
107   ///
108   /// This function is used to interpolate the image value at arbitrary
109   /// locations when no extrapolator was set.
110   VoxelType Get2D(double, double, double = 0, double = 0) const;
111 
112   /// Get value of given 2D image at arbitrary location (in pixels)
113   ///
114   /// This function is used to only interpolate foreground image values.
115   /// If fully outside the foreground region, the _DefaultValue is returned.
116   VoxelType GetWithPadding2D(double, double, double = 0, double = 0) const;
117 
118   /// Get value of given 2D image at arbitrary location (in pixels)
119   ///
120   /// If the location is inside the finite domain of the image, an actual image
121   /// instance can be passed as first argument directly such as an instance of
122   /// GenericImage. Otherwise, an image function which extends the finite
123   /// image domain to an infinite lattice is needed, i.e., an instance of a
124   /// subclass of ExtrapolateImageFunction.
125   template <class TOtherImage> typename TOtherImage::VoxelType
126   Get2D(const TOtherImage *, double, double, double = 0, double = 0) const;
127 
128   /// Get value of given 2D image at arbitrary location (in pixels)
129   ///
130   /// This function is used to only interpolate foreground image values.
131   /// If fully outside the foreground region, the _DefaultValue is returned.
132   ///
133   /// If the location is inside the finite domain of the image, an actual image
134   /// instance can be passed as first argument directly such as an instance of
135   /// GenericImage. Otherwise, an image function which extends the finite
136   /// image domain to an infinite lattice is needed, i.e., an instance of a
137   /// subclass of ExtrapolateImageFunction.
138   template <class TOtherImage, class TCoefficient> typename TCoefficient::VoxelType
139   GetWithPadding2D(const TOtherImage *, const TCoefficient *,
140                    double, double, double = 0, double = 0) const;
141 
142   /// Get value of given 3D image at arbitrary location (in pixels)
143   ///
144   /// This function is used to interpolate the image value at arbitrary
145   /// locations when no extrapolator was set.
146   VoxelType Get3D(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 only interpolate foreground image values.
151   /// If fully outside the foreground region, the _DefaultValue is returned.
152   VoxelType GetWithPadding3D(double, double, double = 0, double = 0) const;
153 
154   /// Get value of given 3D image at arbitrary location (in pixels)
155   ///
156   /// If the location is inside the finite domain of the image, an actual image
157   /// instance can be passed as first argument directly such as an instance of
158   /// GenericImage. Otherwise, an image function which extends the finite
159   /// image domain to an infinite lattice is needed, i.e., an instance of a
160   /// subclass of ExtrapolateImageFunction.
161   template <class TOtherImage> typename TOtherImage::VoxelType
162   Get3D(const TOtherImage *, double, double, double = 0, double = 0) const;
163 
164   /// Get value of given 3D image at arbitrary location (in pixels)
165   ///
166   /// This function is used to only interpolate foreground image values.
167   /// If fully outside the foreground region, the _DefaultValue is returned.
168   ///
169   /// If the location is inside the finite domain of the image, an actual image
170   /// instance can be passed as first argument directly such as an instance of
171   /// GenericImage. Otherwise, an image function which extends the finite
172   /// image domain to an infinite lattice is needed, i.e., an instance of a
173   /// subclass of ExtrapolateImageFunction.
174   template <class TOtherImage, class TCoefficient> typename TCoefficient::VoxelType
175   GetWithPadding3D(const TOtherImage *, const TCoefficient *,
176                    double, double, double = 0, double = 0) const;
177 
178   /// Get value of given 4D image at arbitrary location (in pixels)
179   ///
180   /// This function is used to interpolate the image value at arbitrary
181   /// locations when no extrapolator was set.
182   VoxelType Get4D(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 only interpolate foreground image values.
187   /// If fully outside the foreground region, the _DefaultValue is returned.
188   VoxelType GetWithPadding4D(double, double, double = 0, double = 0) const;
189 
190   /// Get value of given 4D image at arbitrary location (in pixels)
191   ///
192   /// If the location is inside the finite domain of the image, an actual image
193   /// instance can be passed as first argument directly such as an instance of
194   /// GenericImage. Otherwise, an image function which extends the finite
195   /// image domain to an infinite lattice is needed, i.e., an instance of a
196   /// subclass of ExtrapolateImageFunction.
197   template <class TOtherImage> typename TOtherImage::VoxelType
198   Get4D(const TOtherImage *, double, double, double = 0, double = 0) const;
199 
200   /// Get value of given 4D image at arbitrary location (in pixels)
201   ///
202   /// This function is used to only interpolate foreground image values.
203   /// If fully outside the foreground region, the _DefaultValue is returned.
204   ///
205   /// If the location is inside the finite domain of the image, an actual image
206   /// instance can be passed as first argument directly such as an instance of
207   /// GenericImage. Otherwise, an image function which extends the finite
208   /// image domain to an infinite lattice is needed, i.e., an instance of a
209   /// subclass of ExtrapolateImageFunction.
210   template <class TOtherImage, class TCoefficient> typename TCoefficient::VoxelType
211   GetWithPadding4D(const TOtherImage *, const TCoefficient *,
212                    double, double, double = 0, double = 0) const;
213 
214   /// Get value of given image at arbitrary location (in pixels)
215   ///
216   /// This function is used to interpolate the image value at arbitrary
217   /// locations when no extrapolator was set.
218   VoxelType Get(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 only interpolate foreground image values.
223   /// If fully outside the foreground region, the _DefaultValue is returned.
224   virtual VoxelType GetWithPadding(double, double, double = 0, double = 0) const;
225 
226   /// Get value of given image at arbitrary location (in pixels)
227   ///
228   /// If the location is inside the finite domain of the image, an actual image
229   /// instance can be passed as first argument directly such as an instance of
230   /// GenericImage. Otherwise, an image function which extends the finite
231   /// image domain to an infinite lattice is needed, i.e., an instance of a
232   /// subclass of ExtrapolateImageFunction.
233   template <class TOtherImage> typename TOtherImage::VoxelType
234   Get(const TOtherImage *, double, double, double = 0, double = 0) const;
235 
236   /// Get value of given image at arbitrary location (in pixels)
237   ///
238   /// This function is used to only interpolate foreground image values.
239   /// If fully outside the foreground region, the _DefaultValue is returned.
240   ///
241   /// If the location is inside the finite domain of the image, an actual image
242   /// instance can be passed as first argument directly such as an instance of
243   /// GenericImage. Otherwise, an image function which extends the finite
244   /// image domain to an infinite lattice is needed, i.e., an instance of a
245   /// subclass of ExtrapolateImageFunction.
246   template <class TOtherImage, class TCoefficient> typename TCoefficient::VoxelType
247   GetWithPadding(const TOtherImage *, const TCoefficient *,
248                  double, double, double = 0, double = 0) const;
249 
250   /// Evaluate generic 2D image without handling boundary conditions
251   virtual VoxelType GetInside2D(double, double, double = 0, double = 0) const;
252 
253   /// Evaluate generic 3D image without handling boundary conditions
254   virtual VoxelType GetInside3D(double, double, double = 0, double = 0) const;
255 
256   /// Evaluate generic 4D image without handling boundary conditions
257   virtual VoxelType GetInside4D(double, double, double = 0, double = 0) const;
258 
259   /// Evaluate generic image without handling boundary conditions
260   ///
261   /// This version is faster than EvaluateOutside, but is only defined inside
262   /// the domain for which all image values required for interpolation are
263   /// defined and thus require no extrapolation of the finite image.
264   virtual VoxelType GetInside(double, double, double = 0, double = 0) const;
265 
266   /// Evaluate generic image at an arbitrary location (in pixels)
267   virtual VoxelType GetOutside(double, double, double = 0, double = 0) const;
268 
269   /// Evaluate generic image without handling boundary conditions
270   ///
271   /// This function is used to only interpolate foreground image values.
272   /// If fully outside the foreground region, the _DefaultValue is returned.
273   ///
274   /// This version is faster than GetWithPaddingOutside, but is only defined
275   /// inside the domain for which all image values required for interpolation
276   /// are defined and thus require no extrapolation of the finite image.
277   virtual VoxelType GetWithPaddingInside(double, double, double = 0, double = 0) const;
278 
279   /// Evaluate generic image at an arbitrary location (in pixels)
280   ///
281   /// This function is used to only interpolate foreground image values.
282   /// If fully outside the foreground region, the _DefaultValue is returned.
283   virtual VoxelType GetWithPaddingOutside(double, double, double = 0, double = 0) const;
284 
285 };
286 
287 /**
288  * Cubic B-spline interpolation of any scalar image
289  */
290 class CubicBSplineInterpolateImageFunction
291 : public GenericCubicBSplineInterpolateImageFunction<BaseImage>
292 {
293   mirtkObjectMacro(CubicBSplineInterpolateImageFunction);
294 
295 public:
296 
297   /// Constructor
CubicBSplineInterpolateImageFunction()298   CubicBSplineInterpolateImageFunction() {}
299 
300 };
301 
302 
303 } // namespace mirtk
304 
305 #endif // MIRTK_CubicBSplineInterpolateImageFunction_H
306