BSplineInterpolateImageFunction.hxx
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_BSplineInterpolateImageFunction_HXX
21 #define MIRTK_BSplineInterpolateImageFunction_HXX
22 
23 #include "mirtk/BSplineInterpolateImageFunction.h"
24 
25 #include "mirtk/Math.h"
26 #include "mirtk/BSpline.h"
27 #include "mirtk/InterpolateImageFunction.hxx"
28 #include "mirtk/ImageToInterpolationCoefficients.h"
29 #include "mirtk/VoxelCast.h"
30 
31 
32 namespace mirtk {
33 
34 // =============================================================================
35 // Construction/Destruction
36 // =============================================================================
37 
38 // -----------------------------------------------------------------------------
39 template <class TImage>
42 :
43  _SplineDegree (degree),
44  _InfiniteCoefficient(NULL)
45 {
46  // Default extrapolation mode is to apply the mirror boundary condition
47  // which is also assumed when converting an input image to spline coefficients
48  this->Extrapolator(ExtrapolatorType::New(Extrapolation_Mirror), true);
49 }
50 
51 // -----------------------------------------------------------------------------
52 template <class TImage>
55 {
56  delete _InfiniteCoefficient;
57 }
58 
59 // -----------------------------------------------------------------------------
60 template <class TImage>
62 ::Initialize(bool coeff)
63 {
64  // Initialize base class
65  Superclass::Initialize(coeff);
66 
67  // Check spline degree
68  if (_SplineDegree < 2 || _SplineDegree > 5) {
69  cerr << this->NameOfClass() << "::Initialize: Spline degree must be 2, 3, 4, or 5" << endl;
70  exit(1);
71  }
72 
73  // Domain on which B-spline interpolation is defined
74  const double margin = round(static_cast<double>(_SplineDegree) / 2.0);
75  switch (this->NumberOfDimensions()) {
76  case 4:
77  this->_t1 = fdec(margin);
78  this->_t2 = this->Input()->T() - margin - 1;
79  case 3:
80  this->_z1 = fdec(margin);
81  this->_z2 = this->Input()->Z() - margin - 1;
82  default:
83  this->_y1 = fdec(margin);
84  this->_y2 = this->Input()->Y() - margin - 1;
85  this->_x1 = fdec(margin);
86  this->_x2 = this->Input()->X() - margin - 1;
87  }
88 
89  // Initialize coefficient image
90  RealType *data = nullptr;
91  _UseInputCoefficients = coeff;
92  if (_UseInputCoefficients && this->Input()->GetDataType() == voxel_info<RealType>::type()) {
93  data = reinterpret_cast<RealType *>(const_cast<void *>(this->Input()->GetDataPointer()));
94  }
95  _Coefficient.Initialize(this->Input()->Attributes(), data);
96  this->Update();
97 
98  // Initialize infinite coefficient image (i.e., extrapolator)
99  if (!_InfiniteCoefficient || _InfiniteCoefficient->ExtrapolationMode() != this->ExtrapolationMode()) {
100  delete _InfiniteCoefficient;
101  _InfiniteCoefficient = CoefficientExtrapolator::New(this->ExtrapolationMode(), &_Coefficient);
102  }
103  if (_InfiniteCoefficient) {
104  _InfiniteCoefficient->Input(&_Coefficient);
105  _InfiniteCoefficient->Initialize();
106  }
107 }
108 
109 // -----------------------------------------------------------------------------
110 template <class TImage>
112 {
113  if (_Coefficient.GetDataPointer() != this->Input()->GetDataPointer()) {
114  _Coefficient = *(this->Input());
115  if (!_UseInputCoefficients) {
116  Real poles[2];
117  int npoles;
118  SplinePoles(_SplineDegree, poles, npoles);
120  switch (this->NumberOfDimensions()) {
121  case 4: ConvertToInterpolationCoefficientsT(_Coefficient, poles, npoles);
122  case 3: ConvertToInterpolationCoefficientsZ(_Coefficient, poles, npoles);
123  default: ConvertToInterpolationCoefficientsY(_Coefficient, poles, npoles);
124  ConvertToInterpolationCoefficientsX(_Coefficient, poles, npoles);
125  }
126  }
127  }
128 }
129 
130 // =============================================================================
131 // Domain checks
132 // =============================================================================
133 
134 // -----------------------------------------------------------------------------
135 template <class TImage>
137 ::BoundingInterval(double x, int &i, int &I) const
138 {
139  if (_SplineDegree & 1) i = ifloor(x ) - _SplineDegree / 2;
140  else i = ifloor(x + 0.5) - _SplineDegree / 2;
141  I = i + _SplineDegree;
142 }
143 
144 // =============================================================================
145 // Evaluation
146 // =============================================================================
147 
148 // -----------------------------------------------------------------------------
149 template <class TImage>
150 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
152 ::Get2D(double x, double y, double z, double t) const
153 {
154  const int k = iround(z);
155  const int l = iround(t);
156 
157  if (k < 0 || k >= _Coefficient.Z() ||
158  l < 0 || l >= _Coefficient.T()) {
159  return voxel_cast<VoxelType>(this->DefaultValue());
160  }
161 
162  // Compute indices and weights
163  int i [6], j [6];
164  Real wx[6], wy[6];
165 
166  ComputeBSplineIndicesAndWeights(x, y, _SplineDegree, i, j, wx, wy);
167 
168  // Perform interpolation without extrapolation
169  RealType val = voxel_cast<RealType>(0);
170 
171  for (int b = 0; b <= _SplineDegree; ++b) {
172  DefaultExtrapolator::Apply(j[b], _Coefficient.Y() - 1);
173  for (int a = 0; a <= _SplineDegree; ++a) {
174  DefaultExtrapolator::Apply(i[a], _Coefficient.X() - 1);
175  val += wx[a] * wy[b] * _Coefficient(i[a], j[b], k, l);
176  }
177  }
178 
179  return voxel_cast<VoxelType>(val);
180 }
181 
182 // -----------------------------------------------------------------------------
183 template <class TImage>
184 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
186 ::GetWithPadding2D(double x, double y, double z, double t) const
187 {
188  const int k = iround(z);
189  const int l = iround(t);
190 
191  if (k < 0 || k >= _Coefficient.Z() ||
192  l < 0 || l >= _Coefficient.T()) {
193  return voxel_cast<VoxelType>(this->DefaultValue());
194  }
195 
196  // Compute indices and weights
197  int i [6], j [6], ia, jb;
198  Real wx[6], wy[6];
199 
200  ComputeBSplineIndicesAndWeights(x, y, _SplineDegree, i, j, wx, wy);
201 
202  // Perform interpolation without extrapolation
203  RealType val = voxel_cast<RealType>(0);
204  Real fgw(0), bgw(0), w;
205 
206  for (int b = 0; b <= _SplineDegree; ++b) {
207  jb = j[b];
208  DefaultExtrapolator::Apply(jb, _Coefficient.Y() - 1);
209  for (int a = 0; a <= _SplineDegree; ++a) {
210  ia = i[a];
211  DefaultExtrapolator::Apply(ia, _Coefficient.X() - 1);
212  w = wx[a] * wy[b];
213  val += w * _Coefficient(ia, jb, k, l);
214  if (this->Input()->IsInsideForeground(i[a], j[b], k, l)) {
215  fgw += w;
216  } else {
217  bgw += w;
218  }
219  }
220  }
221 
222  if (bgw > fgw || AreEqual(bgw, fgw, 1e-3)) {
223  val = voxel_cast<RealType>(this->DefaultValue());
224  }
225  return voxel_cast<VoxelType>(val);
226 }
227 
228 // -----------------------------------------------------------------------------
229 template <class TImage> template <class TCoefficient>
230 typename TCoefficient::VoxelType GenericBSplineInterpolateImageFunction<TImage>
231 ::Get2D(const TCoefficient *coeff, double x, double y, double z, double t) const
232 {
233  typedef typename TCoefficient::VoxelType VoxelType;
234  typedef typename TCoefficient::RealType RealType;
235 
236  const int k = iround(z);
237  const int l = iround(t);
238 
239  // Compute indices and weights
240  int i [6], j [6];
241  Real wx[6], wy[6];
242 
243  ComputeBSplineIndicesAndWeights(x, y, _SplineDegree, i, j, wx, wy);
244 
245  // Perform interpolation
246  RealType val = voxel_cast<RealType>(0);
247  for (int b = 0; b <= _SplineDegree; ++b) {
248  for (int a = 0; a <= _SplineDegree; ++a) {
249  val += wx[a] * wy[b] * voxel_cast<RealType>(coeff->Get(i[a], j[b], k, l));
250  }
251  }
252 
253  return voxel_cast<VoxelType>(val);
254 }
255 
256 // -----------------------------------------------------------------------------
257 template <class TImage> template <class TOtherImage, class TCoefficient>
258 typename TCoefficient::VoxelType GenericBSplineInterpolateImageFunction<TImage>
259 ::GetWithPadding2D(const TOtherImage *image, const TCoefficient *coeff,
260  double x, double y, double z, double t) const
261 {
262  typedef typename TCoefficient::VoxelType VoxelType;
263  typedef typename TCoefficient::RealType RealType;
264 
265  const int k = iround(z);
266  const int l = iround(t);
267 
268  // Compute indices and weights
269  int i [6], j [6];
270  Real wx[6], wy[6];
271 
272  ComputeBSplineIndicesAndWeights(x, y, _SplineDegree, i, j, wx, wy);
273 
274  // Perform interpolation
275  RealType val = voxel_cast<RealType>(0);
276  Real fgw(0), bgw(0), w;
277 
278  for (int b = 0; b <= _SplineDegree; ++b) {
279  for (int a = 0; a <= _SplineDegree; ++a) {
280  w = wx[a] * wy[b];
281  val += w * voxel_cast<RealType>(coeff->Get(i[a], j[b], k, l));
282  if (image->IsForeground(i[a], j[b], k, l)) {
283  fgw += w;
284  } else {
285  bgw += w;
286  }
287  }
288  }
289 
290  if (bgw > fgw || AreEqual(bgw, fgw, 1e-3)) {
291  val = voxel_cast<RealType>(this->DefaultValue());
292  }
293  return voxel_cast<VoxelType>(val);
294 }
295 
296 // -----------------------------------------------------------------------------
297 template <class TImage>
298 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
300 ::Get3D(double x, double y, double z, double t) const
301 {
302  const int l = iround(t);
303 
304  if (l < 0 || l >= _Coefficient.T()) {
305  return voxel_cast<VoxelType>(this->DefaultValue());
306  }
307 
308  // Compute indices and weights
309  int i [6], j [6], k [6];
310  Real wx[6], wy[6], wz[6];
311 
312  ComputeBSplineIndicesAndWeights(x, y, z, _SplineDegree, i, j, k, wx, wy, wz);
313 
314  // Perform interpolation without extrapolation
315  RealType val = voxel_cast<RealType>(0);
316  Real wyz;
317 
318  for (int c = 0; c <= _SplineDegree; ++c) {
319  DefaultExtrapolator::Apply(k[c], _Coefficient.Z() - 1);
320  for (int b = 0; b <= _SplineDegree; ++b) {
321  DefaultExtrapolator::Apply(j[b], _Coefficient.Y() - 1);
322  wyz = wy[b] * wz[c];
323  for (int a = 0; a <= _SplineDegree; ++a) {
324  DefaultExtrapolator::Apply(i[a], _Coefficient.X() - 1);
325  val += wx[a] * wyz * _Coefficient(i[a], j[b], k[c], l);
326  }
327  }
328  }
329 
330  return voxel_cast<VoxelType>(val);
331 }
332 
333 // -----------------------------------------------------------------------------
334 template <class TImage>
335 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
337 ::GetWithPadding3D(double x, double y, double z, double t) const
338 {
339  const int l = iround(t);
340 
341  if (l < 0 || l >= _Coefficient.T()) {
342  return voxel_cast<VoxelType>(this->DefaultValue());
343  }
344 
345  // Compute indices and weights
346  int i [6], j [6], k [6], ia, jb, kc;
347  Real wx[6], wy[6], wz[6];
348 
349  ComputeBSplineIndicesAndWeights(x, y, z, _SplineDegree, i, j, k, wx, wy, wz);
350 
351  // Perform interpolation without extrapolation
352  RealType val = voxel_cast<RealType>(0);
353  Real fgw(0), bgw(0), wyz, w;
354 
355  for (int c = 0; c <= _SplineDegree; ++c) {
356  kc = k[c];
357  DefaultExtrapolator::Apply(kc, _Coefficient.Z() - 1);
358  for (int b = 0; b <= _SplineDegree; ++b) {
359  jb = j[b];
360  DefaultExtrapolator::Apply(jb, _Coefficient.Y() - 1);
361  wyz = wy[b] * wz[c];
362  for (int a = 0; a <= _SplineDegree; ++a) {
363  ia = i[a];
364  DefaultExtrapolator::Apply(ia, _Coefficient.X() - 1);
365  w = wx[a] * wyz;
366  val += w * _Coefficient(ia, jb, kc, l);
367  if (this->Input()->IsInsideForeground(i[a], j[b], k[c], l)) {
368  fgw += w;
369  } else {
370  bgw += w;
371  }
372  }
373  }
374  }
375 
376  if (bgw > fgw || AreEqual(bgw, fgw, 1e-3)) {
377  val = voxel_cast<RealType>(this->DefaultValue());
378  }
379  return voxel_cast<VoxelType>(val);
380 }
381 
382 // -----------------------------------------------------------------------------
383 template <class TImage> template <class TCoefficient>
384 typename TCoefficient::VoxelType GenericBSplineInterpolateImageFunction<TImage>
385 ::Get3D(const TCoefficient *coeff, double x, double y, double z, double t) const
386 {
387  typedef typename TCoefficient::VoxelType VoxelType;
388  typedef typename TCoefficient::RealType RealType;
389 
390  const int l = iround(t);
391 
392  // Compute indices and weights
393  int i [6], j [6], k [6];
394  Real wx[6], wy[6], wz[6];
395 
396  ComputeBSplineIndicesAndWeights(x, y, z, _SplineDegree, i, j, k, wx, wy, wz);
397 
398  // Perform interpolation
399  RealType val = voxel_cast<RealType>(0);
400  Real wyz;
401 
402  for (int c = 0; c <= _SplineDegree; ++c) {
403  for (int b = 0; b <= _SplineDegree; ++b) {
404  wyz = wy[b] * wz[c];
405  for (int a = 0; a <= _SplineDegree; ++a) {
406  val += wx[a] * wyz * voxel_cast<RealType>(coeff->Get(i[a], j[b], k[c], l));
407  }
408  }
409  }
410 
411  return voxel_cast<VoxelType>(val);
412 }
413 
414 // -----------------------------------------------------------------------------
415 template <class TImage> template <class TOtherImage, class TCoefficient>
416 typename TCoefficient::VoxelType GenericBSplineInterpolateImageFunction<TImage>
417 ::GetWithPadding3D(const TOtherImage *image, const TCoefficient *coeff,
418  double x, double y, double z, double t) const
419 {
420  typedef typename TCoefficient::RealType RealType;
421 
422  const int l = iround(t);
423 
424  // Compute indices and weights
425  int i [6], j [6], k [6];
426  Real wx[6], wy[6], wz[6];
427 
428  ComputeBSplineIndicesAndWeights(x, y, z, _SplineDegree, i, j, k, wx, wy, wz);
429 
430  // Perform interpolation
431  RealType val = voxel_cast<RealType>(0);
432  Real fgw(0), bgw(0), wyz, w;
433 
434  for (int c = 0; c <= _SplineDegree; ++c) {
435  for (int b = 0; b <= _SplineDegree; ++b) {
436  wyz = wy[b] * wz[c];
437  for (int a = 0; a <= _SplineDegree; ++a) {
438  w = wx[a] * wyz;
439  val += w * voxel_cast<RealType>(coeff->Get(i[a], j[b], k[c], l));
440  if (image->IsForeground(i[a], j[b], k[c], l)) {
441  fgw += w;
442  } else {
443  bgw += w;
444  }
445  }
446  }
447  }
448 
449  if (bgw > fgw || AreEqual(bgw, fgw, 1e-3)) {
450  val = voxel_cast<RealType>(this->DefaultValue());
451  }
452  return voxel_cast<typename TCoefficient::VoxelType>(val);
453 }
454 
455 // -----------------------------------------------------------------------------
456 template <class TImage>
457 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
459 ::Get4D(double x, double y, double z, double t) const
460 {
461  // Compute indices and weights
462  int i [6], j [6], k [6], l [6];
463  Real wx[6], wy[6], wz[6], wt[6];
464 
465  ComputeBSplineIndicesAndWeights(x, y, z, t, _SplineDegree, i, j, k, l, wx, wy, wz, wt);
466 
467  // Perform interpolation without extrapolation
468  RealType val = voxel_cast<RealType>(0);
469  Real wzt, wyzt;
470 
471  for (int d = 0; d <= _SplineDegree; ++d) {
472  DefaultExtrapolator::Apply(l[d], _Coefficient.T() - 1);
473  for (int c = 0; c <= _SplineDegree; ++c) {
474  DefaultExtrapolator::Apply(k[c], _Coefficient.Z() - 1);
475  wzt = wz[c] * wt[d];
476  for (int b = 0; b <= _SplineDegree; ++b) {
477  DefaultExtrapolator::Apply(j[b], _Coefficient.Y() - 1);
478  wyzt = wy[b] * wzt;
479  for (int a = 0; a <= _SplineDegree; ++a) {
480  DefaultExtrapolator::Apply(i[a], _Coefficient.X() - 1);
481  val += wx[a] * wyzt * _Coefficient(i[a], j[b], k[c], l[d]);
482  }
483  }
484  }
485  }
486 
487  return voxel_cast<VoxelType>(val);
488 }
489 
490 // -----------------------------------------------------------------------------
491 template <class TImage>
492 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
494 ::GetWithPadding4D(double x, double y, double z, double t) const
495 {
496  // Compute indices and weights
497  int i [6], j [6], k [6], l [6], ia, jb, kc, ld;
498  Real wx[6], wy[6], wz[6], wt[6];
499 
500  ComputeBSplineIndicesAndWeights(x, y, z, t, _SplineDegree, i, j, k, l, wx, wy, wz, wt);
501 
502  // Perform interpolation without extrapolation
503  RealType val = voxel_cast<RealType>(0);
504  Real fgw(0), bgw(0), wzt, wyzt, w;
505 
506  for (int d = 0; d <= _SplineDegree; ++d) {
507  ld = l[d];
508  DefaultExtrapolator::Apply(ld, _Coefficient.T() - 1);
509  for (int c = 0; c <= _SplineDegree; ++c) {
510  kc = k[c];
511  DefaultExtrapolator::Apply(kc, _Coefficient.Z() - 1);
512  wzt = wz[c] * wt[d];
513  for (int b = 0; b <= _SplineDegree; ++b) {
514  jb = j[b];
515  DefaultExtrapolator::Apply(jb, _Coefficient.Y() - 1);
516  wyzt = wy[b] * wzt;
517  for (int a = 0; a <= _SplineDegree; ++a) {
518  ia = i[a];
519  DefaultExtrapolator::Apply(ia, _Coefficient.X() - 1);
520  w = wx[a] * wyzt;
521  val += w * _Coefficient(ia, jb, kc, ld);
522  if (this->Input()->IsInsideForeground(i[a], j[b], k[c], l[d])) {
523  fgw += w;
524  } else {
525  bgw += w;
526  }
527  }
528  }
529  }
530  }
531 
532  if (bgw > fgw || AreEqual(bgw, fgw, 1e-3)) {
533  val = voxel_cast<RealType>(this->DefaultValue());
534  }
535  return voxel_cast<VoxelType>(val);
536 }
537 
538 // -----------------------------------------------------------------------------
539 template <class TImage> template <class TCoefficient>
540 typename TCoefficient::VoxelType GenericBSplineInterpolateImageFunction<TImage>
541 ::Get4D(const TCoefficient *coeff, double x, double y, double z, double t) const
542 {
543  typedef typename TCoefficient::VoxelType VoxelType;
544  typedef typename TCoefficient::RealType RealType;
545 
546  // Compute indices and weights
547  int i [6], j [6], k [6], l [6];
548  Real wx[6], wy[6], wz[6], wt[6];
549 
550  ComputeBSplineIndicesAndWeights(x, y, z, t, _SplineDegree, i, j, k, l, wx, wy, wz, wt);
551 
552  // Perform interpolation
553  RealType val = voxel_cast<RealType>(0);
554  Real wzt, wyzt;
555 
556  for (int d = 0; d <= _SplineDegree; ++d) {
557  for (int c = 0; c <= _SplineDegree; ++c) {
558  wzt = wz[c] * wt[d];
559  for (int b = 0; b <= _SplineDegree; ++b) {
560  wyzt = wy[b] * wzt;
561  for (int a = 0; a <= _SplineDegree; ++a) {
562  val += wx[a] * wyzt * voxel_cast<RealType>(coeff->Get(i[a], j[b], k[c], l[d]));
563  }
564  }
565  }
566  }
567 
568  return voxel_cast<VoxelType>(val);
569 }
570 
571 // -----------------------------------------------------------------------------
572 template <class TImage> template <class TOtherImage, class TCoefficient>
573 typename TCoefficient::VoxelType GenericBSplineInterpolateImageFunction<TImage>
574 ::GetWithPadding4D(const TOtherImage *image, const TCoefficient *coeff,
575  double x, double y, double z, double t) const
576 {
577  typedef typename TCoefficient::VoxelType VoxelType;
578  typedef typename TCoefficient::RealType RealType;
579 
580  // Compute indices and weights
581  int i [6], j [6], k [6], l [6];
582  Real wx[6], wy[6], wz[6], wt[6];
583 
584  ComputeBSplineIndicesAndWeights(x, y, z, t, _SplineDegree, i, j, k, l, wx, wy, wz, wt);
585 
586  // Perform interpolation
587  RealType val = voxel_cast<RealType>(0);
588  Real fgw(0), bgw(0), wzt, wyzt, w;
589 
590  for (int d = 0; d <= _SplineDegree; ++d) {
591  for (int c = 0; c <= _SplineDegree; ++c) {
592  wzt = wz[c] * wt[d];
593  for (int b = 0; b <= _SplineDegree; ++b) {
594  wyzt = wy[b] * wzt;
595  for (int a = 0; a <= _SplineDegree; ++a) {
596  w = wx[a] * wyzt;
597  val += w * voxel_cast<RealType>(coeff->Get(i[a], j[b], k[c], l[d]));
598  if (image->IsForeground(i[a], j[b], k[c], l[d])) {
599  fgw += w;
600  } else {
601  bgw += w;
602  }
603  }
604  }
605  }
606  }
607 
608  if (bgw > fgw || AreEqual(bgw, fgw, 1e-3)) {
609  val = voxel_cast<RealType>(this->DefaultValue());
610  }
611  return voxel_cast<VoxelType>(val);
612 }
613 
614 // -----------------------------------------------------------------------------
615 template <class TImage>
616 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
618 ::Get(double x, double y, double z, double t) const
619 {
620  switch (this->NumberOfDimensions()) {
621  case 3: return Get3D(x, y, z, t);
622  case 2: return Get2D(x, y, z, t);
623  default: return Get4D(x, y, z, t);
624  }
625 }
626 
627 // -----------------------------------------------------------------------------
628 template <class TImage>
629 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
631 ::GetWithPadding(double x, double y, double z, double t) const
632 {
633  switch (this->NumberOfDimensions()) {
634  case 3: return GetWithPadding3D(x, y, z, t);
635  case 2: return GetWithPadding2D(x, y, z, t);
636  default: return GetWithPadding4D(x, y, z, t);
637  }
638 }
639 
640 // -----------------------------------------------------------------------------
641 template <class TImage> template <class TOtherImage>
642 typename TOtherImage::VoxelType
644 ::Get(const TOtherImage *coeff, double x, double y, double z, double t) const
645 {
646  switch (this->NumberOfDimensions()) {
647  case 3: return Get3D(coeff, x, y, z, t);
648  case 2: return Get2D(coeff, x, y, z, t);
649  default: return Get4D(coeff, x, y, z, t);
650  }
651 }
652 
653 // -----------------------------------------------------------------------------
654 template <class TImage> template <class TOtherImage, class TCoefficient>
655 typename TCoefficient::VoxelType
657 ::GetWithPadding(const TOtherImage *image, const TCoefficient *coeff,
658  double x, double y, double z, double t) const
659 {
660  switch (this->NumberOfDimensions()) {
661  case 3: return GetWithPadding3D(image, coeff, x, y, z, t);
662  case 2: return GetWithPadding2D(image, coeff, x, y, z, t);
663  default: return GetWithPadding4D(image, coeff, x, y, z, t);
664  }
665 }
666 
667 // -----------------------------------------------------------------------------
668 template <class TImage>
669 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
671 ::GetInside(double x, double y, double z, double t) const
672 {
673  return voxel_cast<VoxelType>(Get(&_Coefficient, x, y, z, t));
674 }
675 
676 // -----------------------------------------------------------------------------
677 template <class TImage>
678 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
680 ::GetOutside(double x, double y, double z, double t) const
681 {
682  if (_InfiniteCoefficient) {
683  return voxel_cast<VoxelType>(Get(_InfiniteCoefficient, x, y, z, t));
684  } else {
685  return Get(x, y, z, t);
686  }
687 }
688 
689 // -----------------------------------------------------------------------------
690 template <class TImage>
691 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
693 ::GetWithPaddingInside(double x, double y, double z, double t) const
694 {
695  return voxel_cast<VoxelType>(GetWithPadding(this->Input(), &_Coefficient, x, y, z, t));
696 }
697 
698 // -----------------------------------------------------------------------------
699 template <class TImage>
700 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
702 ::GetWithPaddingOutside(double x, double y, double z, double t) const
703 {
704  if (this->Extrapolator() && _InfiniteCoefficient) {
705  return voxel_cast<VoxelType>(GetWithPadding(this->Extrapolator(), _InfiniteCoefficient, x, y, z, t));
706  } else {
707  return GetWithPadding(x, y, z, t);
708  }
709 }
710 
711 
712 } // namespace mirtk
713 
714 #endif // MIRTK_BSplineInterpolateImageFunction_HXX
void SplinePoles(int degree, TReal pole[2], int &npoles)
Recover spline poles from a lookup table.
VoxelType Get3D(double, double, double=0, double=0) const
string Get(const ParameterList &params, string name)
Get parameter value from parameters list.
Definition: Object.h:202
VoxelType Get2D(double, double, double=0, double=0) const
VoxelType Get4D(double, double, double=0, double=0) const
void FillBackgroundBeforeConversionToSplineCoefficients(GenericImage< TData > &image)
Fill background by front propagation of foreground.
MIRTKCU_API int ifloor(T x)
Round floating-point value to next smaller integer and cast to int.
Definition: Math.h:154
MIRTKCU_API double fdec(double f)
Definition: Math.h:188
Definition: IOConfig.h:41
void ComputeBSplineIndicesAndWeights(double x, double y, int spline_degree, int xIndex [6], int yIndex [6], TReal xWeight[6], TReal yWeight[6])
Compute indices and weights required for 2D B-spline interpolation.
Definition: BSpline.h:673
VoxelType Get(double, double, double=0, double=0) const
virtual VoxelType GetWithPaddingOutside(double, double, double=0, double=0) const
VoxelType GetWithPadding4D(double, double, double=0, double=0) const
VoxelType GetWithPadding2D(double, double, double=0, double=0) const
virtual VoxelType GetOutside(double, double, double=0, double=0) const
Evaluate generic image at an arbitrary location (in pixels)
ExtrapolationMode
Image extrapolation modes.
MIRTKCU_API bool AreEqual(double a, double b, double tol=1e-12)
Determine equality of two floating point numbers.
Definition: Math.h:115
virtual VoxelType GetInside(double, double, double=0, double=0) const
virtual void BoundingInterval(double, int &, int &) const
VoxelType GetWithPadding(double, double, double=0, double=0) const
VoxelType GetWithPadding3D(double, double, double=0, double=0) const
MIRTKCU_API int iround(T x)
Round floating-point value and cast to int.
Definition: Math.h:170
virtual VoxelType GetWithPaddingInside(double, double, double=0, double=0) const