GaussianInterpolateImageFunction.hxx
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2008-2015 Imperial College London
5  * Copyright 2008-2013 Daniel Rueckert, Julia Schnabel
6  * Copyright 2013-2015 Andreas Schuh
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifndef MIRTK_GaussianInterpolateImageFunction_HXX
22 #define MIRTK_GaussianInterpolateImageFunction_HXX
23 
24 #include "mirtk/GaussianInterpolateImageFunction.h"
25 #include "mirtk/InterpolateImageFunction.hxx"
26 
27 #include "mirtk/Math.h"
28 #include "mirtk/VoxelCast.h"
29 #include "mirtk/ScalarGaussian.h"
30 
31 
32 namespace mirtk {
33 
34 
35 // =============================================================================
36 // Construction/Destruction
37 // =============================================================================
38 
39 // -----------------------------------------------------------------------------
40 template <class TImage>
43 :
44  _Sigma(sigma),
45  _RadiusX(.0), _RadiusY(.0), _RadiusZ(.0), _RadiusT(.0),
46  _dx (.0), _dy (.0), _dz (.0), _dt (.0)
47 {
48 }
49 
50 // -----------------------------------------------------------------------------
51 template <class TImage>
53 {
54  // Initialize base class
55  Superclass::Initialize(coeff);
56 
57  // Get input voxel size
58  this->Input()->GetPixelSize(_dx, _dy, _dz, _dt);
59 
60  // Compute filter extent
61  _RadiusX = _RadiusY = _RadiusZ = _RadiusT = .0;
62  switch (this->NumberOfDimensions()) {
63  case 4: _RadiusT = round(ceil(3.0 * _Sigma/_dt));
64  case 3: _RadiusZ = round(ceil(3.0 * _Sigma/_dz));
65  default: _RadiusY = round(ceil(3.0 * _Sigma/_dy));
66  _RadiusX = round(ceil(3.0 * _Sigma/_dx));
67  }
68 
69  // Domain on which the C-spline interpolation is defined
70  this->_x1 = _RadiusX;
71  this->_x2 = this->Input()->X() - _RadiusX - 1;
72  this->_y1 = _RadiusY;
73  this->_y2 = this->Input()->Y() - _RadiusY - 1;
74  this->_z1 = _RadiusZ;
75  this->_z2 = this->Input()->Z() - _RadiusZ - 1;
76  this->_t1 = _RadiusT;
77  this->_t2 = this->Input()->T() - _RadiusT - 1;
78 }
79 
80 // -----------------------------------------------------------------------------
81 template <class TImage>
83 ::BoundingInterval(double x, int &i, int &I) const
84 {
85  double r = max(_RadiusX, max(_RadiusY, max(_RadiusZ, _RadiusT)));
86  i = ifloor(x - r), I = ifloor(x + r);
87 }
88 
89 // -----------------------------------------------------------------------------
90 template <class TImage>
92 ::BoundingBox(double x, double y, int &i1, int &i2,
93  int &j1, int &j2) const
94 {
95  i1 = ifloor(x - _RadiusX), i2 = ifloor(x + _RadiusX);
96  j1 = ifloor(y - _RadiusY), j2 = ifloor(y + _RadiusY);
97 }
98 
99 // -----------------------------------------------------------------------------
100 template <class TImage>
102 ::BoundingBox(double x, double y, double z, int &i1, int &i2, int &k1,
103  int &j1, int &j2, int &k2) const
104 {
105  i1 = ifloor(x - _RadiusX), i2 = ifloor(x + _RadiusX);
106  j1 = ifloor(y - _RadiusY), j2 = ifloor(y + _RadiusY);
107  k1 = ifloor(z - _RadiusZ), k2 = ifloor(z + _RadiusZ);
108 }
109 
110 // -----------------------------------------------------------------------------
111 template <class TImage>
113 ::BoundingBox(double x, double y, double z, double t,
114  int &i1, int &i2, int &k1, int &l1,
115  int &j1, int &j2, int &k2, int &l2) const
116 {
117  i1 = ifloor(x - _RadiusX), i2 = ifloor(x + _RadiusX);
118  j1 = ifloor(y - _RadiusY), j2 = ifloor(y + _RadiusY);
119  k1 = ifloor(z - _RadiusZ), k2 = ifloor(z + _RadiusZ);
120  l1 = ifloor(t - _RadiusT), l2 = ifloor(t + _RadiusT);
121 }
122 
123 // =============================================================================
124 // Evaluation
125 // =============================================================================
126 
127 // -----------------------------------------------------------------------------
128 template <class TImage>
129 inline typename GenericGaussianInterpolateImageFunction<TImage>::VoxelType
131 ::Get2D(double x, double y, double z, double t) const
132 {
133  const int k = iround(z);
134  const int l = iround(t);
135 
136  if (k < 0 || k >= this->Input()->Z() ||
137  l < 0 || l >= this->Input()->T()) {
138  return voxel_cast<VoxelType>(this->DefaultValue());
139  }
140 
141  const int i1 = ifloor(x - _RadiusX);
142  const int j1 = ifloor(y - _RadiusY);
143  const int i2 = ifloor(x + _RadiusX);
144  const int j2 = ifloor(y + _RadiusY);
145 
146  // Create Gaussian interpolation kernel
147  ScalarGaussian kernel(_Sigma/_dx, _Sigma/_dy, .0, x, y, .0);
148 
149  // Perform Gaussian interpolation
150  RealType val = voxel_cast<RealType>(0);
151  Real nrm(0), w;
152 
153  for (int j = j1; j <= j2; ++j) {
154  if (0 <= j && j < this->Input()->Y()) {
155  for (int i = i1; i <= i2; ++i) {
156  if (0 <= i && i < this->Input()->X()) {
157  w = static_cast<Real>(kernel.Evaluate(i, j));
158  val += w * voxel_cast<RealType>(this->Input()->Get(i, j, k, l));
159  nrm += w;
160  }
161  }
162  }
163  }
164 
165  if (nrm > 1e-3) val /= nrm;
166  else val = voxel_cast<RealType>(this->DefaultValue());
167 
168  return voxel_cast<VoxelType>(val);
169 }
170 
171 // -----------------------------------------------------------------------------
172 template <class TImage>
173 inline typename GenericGaussianInterpolateImageFunction<TImage>::VoxelType
175 ::GetWithPadding2D(double x, double y, double z, double t) const
176 {
177  const int k = iround(z);
178  const int l = iround(t);
179 
180  if (k < 0 || k >= this->Input()->Z() ||
181  l < 0 || l >= this->Input()->T()) {
182  return voxel_cast<VoxelType>(this->DefaultValue());
183  }
184 
185  const int i1 = ifloor(x - _RadiusX);
186  const int j1 = ifloor(y - _RadiusY);
187  const int i2 = ifloor(x + _RadiusX);
188  const int j2 = ifloor(y + _RadiusY);
189 
190  // Create Gaussian interpolation kernel
191  ScalarGaussian kernel(_Sigma/_dx, _Sigma/_dy, .0, x, y, .0);
192 
193  // Perform Gaussian interpolation
194  RealType val = voxel_cast<RealType>(0);
195  Real fgw(0), bgw(0), w;
196 
197  for (int j = j1; j <= j2; ++j) {
198  for (int i = i1; i <= i2; ++i) {
199  w = static_cast<Real>(kernel.Evaluate(i, j));
200  if (this->Input()->IsInsideForeground(i, j, k, l)) {
201  val += w * voxel_cast<RealType>(this->Input()->Get(i, j, k, l));
202  fgw += w;
203  } else {
204  bgw += w;
205  }
206  }
207  }
208 
209  if (bgw > fgw || AreEqual(bgw, fgw, 1e-3)) {
210  return voxel_cast<VoxelType>(this->DefaultValue());
211  }
212  return voxel_cast<VoxelType>(val / fgw);
213 }
214 
215 // -----------------------------------------------------------------------------
216 template <class TImage> template <class TOtherImage>
217 inline typename TOtherImage::VoxelType
219 ::Get2D(const TOtherImage *input, double x, double y, double z, double t) const
220 {
221  typedef typename TOtherImage::VoxelType VoxelType;
222  typedef typename TOtherImage::RealType RealType;
223 
224  const int k = iround(z);
225  const int l = iround(t);
226 
227  const int i1 = ifloor(x - _RadiusX);
228  const int j1 = ifloor(y - _RadiusY);
229  const int i2 = ifloor(x + _RadiusX);
230  const int j2 = ifloor(y + _RadiusY);
231 
232  // Create Gaussian interpolation kernel
233  ScalarGaussian kernel(_Sigma/_dx, _Sigma/_dy, .0, x, y, .0);
234 
235  // Perform Gaussian interpolation
236  RealType val = voxel_cast<RealType>(0);
237  Real nrm(0), w;
238 
239  for (int j = j1; j <= j2; ++j) {
240  for (int i = i1; i <= i2; ++i) {
241  w = static_cast<Real>(kernel.Evaluate(i, j));
242  val += w * voxel_cast<RealType>(input->Get(i, j, k, l));
243  nrm += w;
244  }
245  }
246 
247  if (nrm > 1e-3) val /= nrm;
248  else val = voxel_cast<RealType>(this->DefaultValue());
249 
250  return voxel_cast<VoxelType>(val);
251 }
252 
253 // -----------------------------------------------------------------------------
254 template <class TImage> template <class TOtherImage>
255 inline typename TOtherImage::VoxelType
257 ::GetWithPadding2D(const TOtherImage *input, double x, double y, double z, double t) const
258 {
259  typedef typename TOtherImage::VoxelType VoxelType;
260  typedef typename TOtherImage::RealType RealType;
261 
262  const int k = iround(z);
263  const int l = iround(t);
264 
265  const int i1 = ifloor(x - _RadiusX);
266  const int j1 = ifloor(y - _RadiusY);
267  const int i2 = ifloor(x + _RadiusX);
268  const int j2 = ifloor(y + _RadiusY);
269 
270  // Create Gaussian interpolation kernel
271  ScalarGaussian kernel(_Sigma/_dx, _Sigma/_dy, .0, x, y, .0);
272 
273  // Perform Gaussian interpolation
274  RealType val = voxel_cast<RealType>(0);
275  Real fgw(0), bgw(0), w;
276 
277  for (int j = j1; j <= j2; ++j) {
278  for (int i = i1; i <= i2; ++i) {
279  w = static_cast<Real>(kernel.Evaluate(i, j));
280  if (input->IsForeground(i, j, k, l)) {
281  val += w * voxel_cast<RealType>(input->Get(i, j, k, l));
282  fgw += w;
283  } else {
284  bgw += w;
285  }
286  }
287  }
288 
289  if (bgw > fgw || AreEqual(bgw, fgw, 1e-3)) {
290  return voxel_cast<VoxelType>(this->DefaultValue());
291  }
292  return voxel_cast<VoxelType>(val / fgw);
293 }
294 
295 // -----------------------------------------------------------------------------
296 template <class TImage>
297 inline typename GenericGaussianInterpolateImageFunction<TImage>::VoxelType
299 ::Get3D(double x, double y, double z, double t) const
300 {
301  const int l = iround(t);
302 
303  if (l < 0 || l >= this->Input()->T()) {
304  return voxel_cast<VoxelType>(this->DefaultValue());
305  }
306 
307  const int i1 = ifloor(x - _RadiusX);
308  const int j1 = ifloor(y - _RadiusY);
309  const int k1 = ifloor(z - _RadiusZ);
310  const int i2 = ifloor(x + _RadiusX);
311  const int j2 = ifloor(y + _RadiusY);
312  const int k2 = ifloor(z + _RadiusZ);
313 
314  // Create Gaussian interpolation kernel
315  ScalarGaussian kernel(_Sigma/_dx, _Sigma/_dy, _Sigma/_dz, x, y, z);
316 
317  // Perform Gaussian interpolation
318  RealType val = voxel_cast<RealType>(0);
319  Real nrm(0), w;
320 
321  for (int k = k1; k <= k2; ++k) {
322  if (0 <= k && k < this->Input()->Z()) {
323  for (int j = j1; j <= j2; ++j) {
324  if (0 <= j && j < this->Input()->Y()) {
325  for (int i = i1; i <= i2; ++i) {
326  if (0 <= i && i < this->Input()->X()) {
327  w = static_cast<Real>(kernel.Evaluate(i, j, k));
328  val += w * voxel_cast<RealType>(this->Input()->Get(i, j, k, l));
329  nrm += w;
330  }
331  }
332  }
333  }
334  }
335  }
336 
337  if (nrm > 1e-3) val /= nrm;
338  else val = voxel_cast<RealType>(this->DefaultValue());
339 
340  return voxel_cast<VoxelType>(val);
341 }
342 
343 // -----------------------------------------------------------------------------
344 template <class TImage>
345 inline typename GenericGaussianInterpolateImageFunction<TImage>::VoxelType
347 ::GetWithPadding3D(double x, double y, double z, double t) const
348 {
349  const int l = iround(t);
350 
351  if (l < 0 || l >= this->Input()->T()) {
352  return voxel_cast<VoxelType>(this->DefaultValue());
353  }
354 
355  const int i1 = ifloor(x - _RadiusX);
356  const int j1 = ifloor(y - _RadiusY);
357  const int k1 = ifloor(z - _RadiusZ);
358  const int i2 = ifloor(x + _RadiusX);
359  const int j2 = ifloor(y + _RadiusY);
360  const int k2 = ifloor(z + _RadiusZ);
361 
362  // Create Gaussian interpolation kernel
363  ScalarGaussian kernel(_Sigma/_dx, _Sigma/_dy, _Sigma/_dz, x, y, z);
364 
365  // Perform Gaussian interpolation
366  RealType val = voxel_cast<RealType>(0);
367  Real fgw(0), bgw(0), w;
368 
369  for (int k = k1; k <= k2; ++k) {
370  for (int j = j1; j <= j2; ++j) {
371  for (int i = i1; i <= i2; ++i) {
372  w = static_cast<Real>(kernel.Evaluate(i, j, k));
373  if (this->Input()->IsInsideForeground(i, j, k, l)) {
374  val += w * voxel_cast<RealType>(this->Input()->Get(i, j, k, l));
375  fgw += w;
376  } else {
377  bgw += w;
378  }
379  }
380  }
381  }
382 
383  if (bgw > fgw || AreEqual(bgw, fgw, 1e-3)) {
384  return voxel_cast<VoxelType>(this->DefaultValue());
385  }
386  return voxel_cast<VoxelType>(val / fgw);
387 }
388 
389 // -----------------------------------------------------------------------------
390 template <class TImage> template <class TOtherImage>
391 inline typename TOtherImage::VoxelType
393 ::Get3D(const TOtherImage *input, double x, double y, double z, double t) const
394 {
395  typedef typename TOtherImage::VoxelType VoxelType;
396  typedef typename TOtherImage::RealType RealType;
397 
398  const int l = iround(t);
399 
400  const int i1 = ifloor(x - _RadiusX);
401  const int j1 = ifloor(y - _RadiusY);
402  const int k1 = ifloor(z - _RadiusZ);
403  const int i2 = ifloor(x + _RadiusX);
404  const int j2 = ifloor(y + _RadiusY);
405  const int k2 = ifloor(z + _RadiusZ);
406 
407  // Create Gaussian interpolation kernel
408  ScalarGaussian kernel(_Sigma/_dx, _Sigma/_dy, _Sigma/_dz, x, y, z);
409 
410  // Perform Gaussian interpolation
411  RealType val = voxel_cast<RealType>(0);
412  Real nrm(0), w;
413 
414  for (int k = k1; k <= k2; ++k) {
415  for (int j = j1; j <= j2; ++j) {
416  for (int i = i1; i <= i2; ++i) {
417  w = static_cast<Real>(kernel.Evaluate(i, j, k));
418  val += w * voxel_cast<RealType>(input->Get(i, j, k, l));
419  nrm += w;
420  }
421  }
422  }
423 
424  if (nrm > 1e-3) val /= nrm;
425  else val = voxel_cast<RealType>(this->DefaultValue());
426 
427  return voxel_cast<VoxelType>(val);
428 }
429 
430 // -----------------------------------------------------------------------------
431 template <class TImage> template <class TOtherImage>
432 inline typename TOtherImage::VoxelType
434 ::GetWithPadding3D(const TOtherImage *input, double x, double y, double z, double t) const
435 {
436  typedef typename TOtherImage::VoxelType VoxelType;
437  typedef typename TOtherImage::RealType RealType;
438 
439  const int l = iround(t);
440 
441  const int i1 = ifloor(x - _RadiusX);
442  const int j1 = ifloor(y - _RadiusY);
443  const int k1 = ifloor(z - _RadiusZ);
444  const int i2 = ifloor(x + _RadiusX);
445  const int j2 = ifloor(y + _RadiusY);
446  const int k2 = ifloor(z + _RadiusZ);
447 
448  // Create Gaussian interpolation kernel
449  ScalarGaussian kernel(_Sigma/_dx, _Sigma/_dy, _Sigma/_dz, x, y, z);
450 
451  // Perform Gaussian interpolation
452  RealType val = voxel_cast<RealType>(0);
453  Real fgw(0), bgw(0), w;
454 
455  for (int k = k1; k <= k2; ++k) {
456  for (int j = j1; j <= j2; ++j) {
457  for (int i = i1; i <= i2; ++i) {
458  w = static_cast<Real>(kernel.Evaluate(i, j, k));
459  if (input->IsForeground(i, j, k, l)) {
460  val += w * voxel_cast<RealType>(input->Get(i, j, k, l));
461  fgw += w;
462  } else {
463  bgw += w;
464  }
465  }
466  }
467  }
468 
469  if (bgw > fgw || AreEqual(bgw, fgw, 1e-3)) {
470  return voxel_cast<VoxelType>(this->DefaultValue());
471  }
472  return voxel_cast<VoxelType>(val / fgw);
473 }
474 
475 // -----------------------------------------------------------------------------
476 template <class TImage>
477 inline typename GenericGaussianInterpolateImageFunction<TImage>::VoxelType
479 ::Get4D(double x, double y, double z, double t) const
480 {
481  const int i1 = ifloor(x - _RadiusX);
482  const int j1 = ifloor(y - _RadiusY);
483  const int k1 = ifloor(z - _RadiusZ);
484  const int l1 = ifloor(t - _RadiusT);
485  const int i2 = ifloor(x + _RadiusX);
486  const int j2 = ifloor(y + _RadiusY);
487  const int k2 = ifloor(z + _RadiusZ);
488  const int l2 = ifloor(t + _RadiusT);
489 
490  // Create Gaussian interpolation kernel
491  ScalarGaussian kernel(_Sigma/_dx, _Sigma/_dy, _Sigma/_dz, _Sigma/_dt, x, y, z, t);
492 
493  // Perform Gaussian interpolation
494  RealType val = voxel_cast<RealType>(0);
495  Real nrm(0), w;
496 
497  for (int l = l1; l <= l2; ++l) {
498  if (0 <= l && l < this->Input()->T()) {
499  for (int k = k1; k <= k2; ++k) {
500  if (0 <= k && k < this->Input()->Z()) {
501  for (int j = j1; j <= j2; ++j) {
502  if (0 <= j && j < this->Input()->Y()) {
503  for (int i = i1; i <= i2; ++i) {
504  if (0 <= i && i < this->Input()->X()) {
505  w = static_cast<Real>(kernel.Evaluate(i, j, k, l));
506  val += w * voxel_cast<RealType>(this->Input()->Get(i, j, k, l));
507  nrm += w;
508  }
509  }
510  }
511  }
512  }
513  }
514  }
515  }
516 
517  if (nrm > 1e-3) val /= nrm;
518  else val = voxel_cast<RealType>(this->DefaultValue());
519 
520  return voxel_cast<VoxelType>(val);
521 }
522 
523 // -----------------------------------------------------------------------------
524 template <class TImage>
525 inline typename GenericGaussianInterpolateImageFunction<TImage>::VoxelType
527 ::GetWithPadding4D(double x, double y, double z, double t) const
528 {
529  const int i1 = ifloor(x - _RadiusX);
530  const int j1 = ifloor(y - _RadiusY);
531  const int k1 = ifloor(z - _RadiusZ);
532  const int l1 = ifloor(t - _RadiusT);
533  const int i2 = ifloor(x + _RadiusX);
534  const int j2 = ifloor(y + _RadiusY);
535  const int k2 = ifloor(z + _RadiusZ);
536  const int l2 = ifloor(t + _RadiusT);
537 
538  // Create Gaussian interpolation kernel
539  ScalarGaussian kernel(_Sigma/_dx, _Sigma/_dy, _Sigma/_dz, _Sigma/_dt, x, y, z, t);
540 
541  // Perform Gaussian interpolation
542  RealType val = voxel_cast<RealType>(0);
543  Real fgw(0), bgw(0), w;
544 
545  for (int l = l1; l <= l2; ++l) {
546  for (int k = k1; k <= k2; ++k) {
547  for (int j = j1; j <= j2; ++j) {
548  for (int i = i1; i <= i2; ++i) {
549  w = static_cast<Real>(kernel.Evaluate(i, j, k, l));
550  if (this->Input()->IsInsideForeground(i, j, k, l)) {
551  val += w * voxel_cast<RealType>(this->Input()->Get(i, j, k, l));
552  fgw += w;
553  } else {
554  bgw += w;
555  }
556  }
557  }
558  }
559  }
560 
561  if (bgw > fgw || AreEqual(bgw, fgw, 1e-3)) {
562  return voxel_cast<VoxelType>(this->DefaultValue());
563  }
564  return voxel_cast<VoxelType>(val / fgw);
565 }
566 
567 // -----------------------------------------------------------------------------
568 template <class TImage> template <class TOtherImage>
569 inline typename TOtherImage::VoxelType
571 ::Get4D(const TOtherImage *input, double x, double y, double z, double t) const
572 {
573  typedef typename TOtherImage::VoxelType VoxelType;
574  typedef typename TOtherImage::RealType RealType;
575 
576  const int i1 = ifloor(x - _RadiusX);
577  const int j1 = ifloor(y - _RadiusY);
578  const int k1 = ifloor(z - _RadiusZ);
579  const int l1 = ifloor(t - _RadiusT);
580 
581  const int i2 = ifloor(x + _RadiusX);
582  const int j2 = ifloor(y + _RadiusY);
583  const int k2 = ifloor(z + _RadiusZ);
584  const int l2 = ifloor(t + _RadiusT);
585 
586  // Create Gaussian interpolation kernel
587  ScalarGaussian kernel(_Sigma/_dx, _Sigma/_dy, _Sigma/_dz, _Sigma/_dt, x, y, z, t);
588 
589  // Perform Gaussian interpolation
590  RealType val = voxel_cast<RealType>(0);
591  Real nrm(0), w;
592 
593  for (int l = l1; l <= l2; ++l) {
594  for (int k = k1; k <= k2; ++k) {
595  for (int j = j1; j <= j2; ++j) {
596  for (int i = i1; i <= i2; ++i) {
597  w = static_cast<Real>(kernel.Evaluate(i, j, k, l));
598  val += w * voxel_cast<RealType>(input->Get(i, j, k, l));
599  nrm += w;
600  }
601  }
602  }
603  }
604 
605  if (nrm > 1e-3) val /= nrm;
606  else val = voxel_cast<RealType>(this->DefaultValue());
607 
608  return voxel_cast<VoxelType>(val);
609 }
610 
611 // -----------------------------------------------------------------------------
612 template <class TImage> template <class TOtherImage>
613 inline typename TOtherImage::VoxelType
615 ::GetWithPadding4D(const TOtherImage *input, double x, double y, double z, double t) const
616 {
617  typedef typename TOtherImage::VoxelType VoxelType;
618  typedef typename TOtherImage::RealType RealType;
619 
620  const int i1 = ifloor(x - _RadiusX);
621  const int j1 = ifloor(y - _RadiusY);
622  const int k1 = ifloor(z - _RadiusZ);
623  const int l1 = ifloor(t - _RadiusT);
624 
625  const int i2 = ifloor(x + _RadiusX);
626  const int j2 = ifloor(y + _RadiusY);
627  const int k2 = ifloor(z + _RadiusZ);
628  const int l2 = ifloor(t + _RadiusT);
629 
630  // Create Gaussian interpolation kernel
631  ScalarGaussian kernel(_Sigma/_dx, _Sigma/_dy, _Sigma/_dz, _Sigma/_dt, x, y, z, t);
632 
633  // Perform Gaussian interpolation
634  RealType val = voxel_cast<RealType>(0);
635  Real fgw(0), bgw(0), w;
636 
637  for (int l = l1; l <= l2; ++l) {
638  for (int k = k1; k <= k2; ++k) {
639  for (int j = j1; j <= j2; ++j) {
640  for (int i = i1; i <= i2; ++i) {
641  w = static_cast<Real>(kernel.Evaluate(i, j, k, l));
642  if (input->IsForeground(i, j, k, l)) {
643  val += w * voxel_cast<RealType>(input->Get(i, j, k, l));
644  fgw += w;
645  } else {
646  bgw += w;
647  }
648  }
649  }
650  }
651  }
652 
653  if (bgw > fgw || AreEqual(bgw, fgw, 1e-3)) {
654  return voxel_cast<VoxelType>(this->DefaultValue());
655  }
656  return voxel_cast<VoxelType>(val / fgw);
657 }
658 
659 // -----------------------------------------------------------------------------
660 template <class TImage>
661 inline typename GenericGaussianInterpolateImageFunction<TImage>::VoxelType
663 ::Get(double x, double y, double z, double t) const
664 {
665  switch (this->NumberOfDimensions()) {
666  case 3: return Get3D(x, y, z, t);
667  case 2: return Get2D(x, y, z, t);
668  default: return Get4D(x, y, z, t);
669  }
670 }
671 
672 // -----------------------------------------------------------------------------
673 template <class TImage>
674 inline typename GenericGaussianInterpolateImageFunction<TImage>::VoxelType
676 ::GetWithPadding(double x, double y, double z, double t) const
677 {
678  switch (this->NumberOfDimensions()) {
679  case 3: return GetWithPadding3D(x, y, z, t);
680  case 2: return GetWithPadding2D(x, y, z, t);
681  default: return GetWithPadding4D(x, y, z, t);
682  }
683 }
684 
685 // -----------------------------------------------------------------------------
686 template <class TImage> template <class TOtherImage>
687 inline typename TOtherImage::VoxelType
689 ::Get(const TOtherImage *input, double x, double y, double z, double t) const
690 {
691  switch (this->NumberOfDimensions()) {
692  case 3: return Get3D(input, x, y, z, t);
693  case 2: return Get2D(input, x, y, z, t);
694  default: return Get4D(input, x, y, z, t);
695  }
696 }
697 
698 // -----------------------------------------------------------------------------
699 template <class TImage> template <class TOtherImage>
700 inline typename TOtherImage::VoxelType
702 ::GetWithPadding(const TOtherImage *input, double x, double y, double z, double t) const
703 {
704  switch (this->NumberOfDimensions()) {
705  case 3: return GetWithPadding3D(input, x, y, z, t);
706  case 2: return GetWithPadding2D(input, x, y, z, t);
707  default: return GetWithPadding4D(input, x, y, z, t);
708  }
709 }
710 
711 // -----------------------------------------------------------------------------
712 template <class TImage>
713 inline typename GenericGaussianInterpolateImageFunction<TImage>::VoxelType
715 ::GetInside(double x, double y, double z, double t) const
716 {
717  return Get(this->Input(), x, y, z, t);
718 }
719 
720 // -----------------------------------------------------------------------------
721 template <class TImage>
722 inline typename GenericGaussianInterpolateImageFunction<TImage>::VoxelType
724 ::GetOutside(double x, double y, double z, double t) const
725 {
726  if (this->Extrapolator()) {
727  return Get(this->Extrapolator(), x, y, z, t);
728  } else {
729  return Get(x, y, z, t);
730  }
731 }
732 
733 // -----------------------------------------------------------------------------
734 template <class TImage>
735 inline typename GenericGaussianInterpolateImageFunction<TImage>::VoxelType
737 ::GetWithPaddingInside(double x, double y, double z, double t) const
738 {
739  return GetWithPadding(this->Input(), x, y, z, t);
740 }
741 
742 // -----------------------------------------------------------------------------
743 template <class TImage>
744 inline typename GenericGaussianInterpolateImageFunction<TImage>::VoxelType
746 ::GetWithPaddingOutside(double x, double y, double z, double t) const
747 {
748  if (this->Extrapolator()) {
749  return GetWithPadding(this->Extrapolator(), x, y, z, t);
750  } else {
751  return GetWithPadding(x, y, z, t);
752  }
753 }
754 
755 
756 } // namespace mirtk
757 
758 #endif // MIRTK_GaussianInterpolateImageFunction_HXX
virtual VoxelType GetWithPadding(double, double, double=0, double=0) const
VoxelType GetWithPadding2D(double, double, double=0, double=0) const
virtual VoxelType GetWithPaddingInside(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 Get(double, double, double=0, double=0) const
virtual void BoundingBox(double, double, int &, int &, int &, int &) const
Returns discrete boundaries of local 2D image region needed for interpolation.
VoxelType Get2D(double, double, double=0, double=0) const
MIRTKCU_API int ifloor(T x)
Round floating-point value to next smaller integer and cast to int.
Definition: Math.h:154
virtual VoxelType GetOutside(double, double, double=0, double=0) const
Evaluate generic image at an arbitrary location (in pixels)
Definition: IOConfig.h:41
VoxelType GetWithPadding4D(double, double, double=0, double=0) const
virtual VoxelType GetWithPaddingOutside(double, double, double=0, double=0) const
virtual void BoundingInterval(double, int &, int &) const
MIRTKCU_API bool AreEqual(double a, double b, double tol=1e-12)
Determine equality of two floating point numbers.
Definition: Math.h:115
VoxelType Get4D(double, double, double=0, double=0) const
virtual double Evaluate(double)
Evaluate 1D Gaussian.
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
GenericGaussianInterpolateImageFunction(double=1.0)
Default constructor.
VoxelType Get3D(double, double, double=0, double=0) const
virtual VoxelType GetInside(double, double, double=0, double=0) const