20 #ifndef MIRTK_SincInterpolateImageFunction_HXX 21 #define MIRTK_SincInterpolateImageFunction_HXX 23 #include "mirtk/SincInterpolateImageFunction.h" 24 #include "mirtk/InterpolateImageFunction.hxx" 26 #include "mirtk/Math.h" 27 #include "mirtk/Sinc.h" 28 #include "mirtk/VoxelCast.h" 39 template <
class TImage>
48 template <
class TImage>
52 Superclass::Initialize(coeff);
58 switch (this->NumberOfDimensions()) {
60 this->_t1 = Kernel::Radius;
61 this->_t2 = this->Input()->T() - Kernel::Radius - 1;
63 this->_z1 = Kernel::Radius;
64 this->_z2 = this->Input()->Z() - Kernel::Radius - 1;
66 this->_y1 = Kernel::Radius;
67 this->_y2 = this->Input()->Y() - Kernel::Radius - 1;
68 this->_x1 = Kernel::Radius;
69 this->_x2 = this->Input()->X() - Kernel::Radius - 1;
78 template <
class TImage>
83 i = c - Kernel::Radius;
84 I = c + Kernel::Radius;
92 template <
class TImage>
93 inline typename GenericSincInterpolateImageFunction<TImage>::VoxelType
95 ::Get2D(
double x,
double y,
double z,
double t)
const 102 if (k < 0 || k >= this->Input()->Z() ||
103 l < 0 || l >= this->Input()->T()) {
104 return voxel_cast<VoxelType>(this->DefaultValue());
108 if (
fequal(x, i, _Epsilon) &&
110 if (0 <= i && i < this->Input()->X() &&
111 0 <= j && j < this->Input()->Y()) {
112 return this->Input()->Get(i, j, k, l);
114 return voxel_cast<VoxelType>(this->DefaultValue());
120 const int i1 = i - Kernel::Radius;
121 const int j1 = j - Kernel::Radius;
122 const int i2 = i + Kernel::Radius;
123 const int j2 = j + Kernel::Radius;
125 RealType val = voxel_cast<RealType>(0);
128 for (j = j1; j <= j2; ++j) {
129 if (0 <= j && j < this->Input()->Y()) {
130 wy = Kernel::Lookup(Real(y - j));
131 for (i = i1; i <= i2; ++i) {
132 if (0 <= i && i < this->Input()->X()) {
133 w = Kernel::Lookup(Real(x - i)) * wy;
134 val += w * voxel_cast<RealType>(this->Input()->Get(i, j, k, l));
141 if (nrm > 1e-3) val /= nrm;
142 else val = voxel_cast<RealType>(this->DefaultValue());
144 return voxel_cast<VoxelType>(val);
148 template <
class TImage>
149 inline typename GenericSincInterpolateImageFunction<TImage>::VoxelType
158 if (k < 0 || k >= this->Input()->Z() ||
159 l < 0 || l >= this->Input()->T()) {
160 return voxel_cast<VoxelType>(this->DefaultValue());
164 if (
fequal(x, i, _Epsilon) &&
166 if (this->Input()->IsInsideForeground(i, j, k, l)) {
167 return this->Input()->Get(i, j, k, l);
169 return voxel_cast<VoxelType>(this->DefaultValue());
175 const int i1 = i - Kernel::Radius;
176 const int j1 = j - Kernel::Radius;
177 const int i2 = i + Kernel::Radius;
178 const int j2 = j + Kernel::Radius;
180 RealType val = voxel_cast<RealType>(0);
181 Real fgw(0), bgw(0), wy, w;
183 for (j = j1; j <= j2; ++j) {
184 wy = Kernel::Lookup(Real(y - j));
185 for (i = i1; i <= i2; ++i) {
186 w = Kernel::Lookup(Real(x - i)) * wy;
187 if (this->Input()->IsInsideForeground(i, j, k, l)) {
188 val += w * voxel_cast<RealType>(this->Input()->Get(i, j, k, l));
196 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
197 return voxel_cast<VoxelType>(this->DefaultValue());
199 return voxel_cast<VoxelType>(val / fgw);
203 template <
class TImage>
template <
class TOtherImage>
204 inline typename TOtherImage::VoxelType
206 ::Get2D(
const TOtherImage *input,
double x,
double y,
double z,
double t)
const 208 typedef typename TOtherImage::VoxelType VoxelType;
209 typedef typename TOtherImage::RealType RealType;
217 if (
fequal(x, i, _Epsilon) &&
219 return input->Get(i, j, k, l);
224 const int i1 = i - Kernel::Radius;
225 const int j1 = j - Kernel::Radius;
226 const int i2 = i + Kernel::Radius;
227 const int j2 = j + Kernel::Radius;
229 RealType val = voxel_cast<RealType>(0);
232 for (j = j1; j <= j2; ++j) {
233 wy = Kernel::Lookup(Real(y - j));
234 for (i = i1; i <= i2; ++i) {
235 w = Kernel::Lookup(Real(x - i)) * wy;
236 val += w * voxel_cast<RealType>(input->Get(i, j, k, l));
241 if (nrm > 1e-3) val /= nrm;
242 else val = voxel_cast<RealType>(this->DefaultValue());
244 return voxel_cast<VoxelType>(val);
248 template <
class TImage>
template <
class TOtherImage>
249 inline typename TOtherImage::VoxelType
253 typedef typename TOtherImage::VoxelType VoxelType;
254 typedef typename TOtherImage::RealType RealType;
262 if (
fequal(x, i, _Epsilon) &&
264 if (input->IsForeground(i, j, k, l)) {
265 return input->Get(i, j, k, l);
267 return voxel_cast<VoxelType>(this->DefaultValue());
273 const int i1 = i - Kernel::Radius;
274 const int j1 = j - Kernel::Radius;
275 const int i2 = i + Kernel::Radius;
276 const int j2 = j + Kernel::Radius;
278 RealType val = voxel_cast<RealType>(0);
279 Real fgw(0), bgw(0), wy, w;
281 for (j = j1; j <= j2; ++j) {
282 wy = Kernel::Lookup(Real(y - j));
283 for (i = i1; i <= i2; ++i) {
284 w = Kernel::Lookup(Real(x - i)) * wy;
285 if (input->IsForeground(i, j, k, l)) {
286 val += w * voxel_cast<RealType>(input->Get(i, j, k, l));
294 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
295 return voxel_cast<VoxelType>(this->DefaultValue());
297 return voxel_cast<VoxelType>(val / fgw);
301 template <
class TImage>
302 inline typename GenericSincInterpolateImageFunction<TImage>::VoxelType
304 ::Get3D(
double x,
double y,
double z,
double t)
const 311 if (l < 0 || l >= this->Input()->T()) {
312 return voxel_cast<VoxelType>(this->DefaultValue());
316 if (
fequal(x, i, _Epsilon) &&
319 if (0 <= i && i < this->Input()->X() &&
320 0 <= j && j < this->Input()->Y() &&
321 0 <= k && k < this->Input()->Z()) {
322 return this->Input()->Get(i, j, k, l);
324 return voxel_cast<VoxelType>(this->DefaultValue());
330 const int i1 = i - Kernel::Radius;
331 const int j1 = j - Kernel::Radius;
332 const int k1 = k - Kernel::Radius;
333 const int i2 = i + Kernel::Radius;
334 const int j2 = j + Kernel::Radius;
335 const int k2 = k + Kernel::Radius;
337 RealType val = voxel_cast<RealType>(0);
338 Real nrm(0), wz, wyz, w;
340 for (k = k1; k <= k2; ++k) {
341 if (0 <= k && k < this->Input()->Z()) {
342 wz = Kernel::Lookup(Real(z - k));
343 for (j = j1; j <= j2; ++j) {
344 if (0 <= j && j < this->Input()->Y()) {
345 wyz = Kernel::Lookup(Real(y - j)) * wz;
346 for (i = i1; i <= i2; ++i) {
347 if (0 <= i && i < this->Input()->X()) {
348 w = Kernel::Lookup(Real(x - i)) * wyz;
349 val += w * voxel_cast<RealType>(this->Input()->Get(i, j, k, l));
358 if (nrm > 1e-3) val /= nrm;
359 else val = voxel_cast<RealType>(this->DefaultValue());
361 return voxel_cast<VoxelType>(val);
365 template <
class TImage>
366 inline typename GenericSincInterpolateImageFunction<TImage>::VoxelType
375 if (l < 0 || l >= this->Input()->T()) {
376 return voxel_cast<VoxelType>(this->DefaultValue());
380 if (
fequal(x, i, _Epsilon) &&
383 if (this->Input()->IsInsideForeground(i, j, k, l)) {
384 return this->Input()->Get(i, j, k, l);
386 return voxel_cast<VoxelType>(this->DefaultValue());
392 const int i1 = i - Kernel::Radius;
393 const int j1 = j - Kernel::Radius;
394 const int k1 = k - Kernel::Radius;
395 const int i2 = i + Kernel::Radius;
396 const int j2 = j + Kernel::Radius;
397 const int k2 = k + Kernel::Radius;
399 RealType val = voxel_cast<RealType>(0);
400 Real fgw(0), bgw(0), wz, wyz, w;
402 for (k = k1; k <= k2; ++k) {
403 wz = Kernel::Lookup(Real(z - k));
404 for (j = j1; j <= j2; ++j) {
405 wyz = Kernel::Lookup(Real(y - j)) * wz;
406 for (i = i1; i <= i2; ++i) {
407 w = Kernel::Lookup(Real(x - i)) * wyz;
408 if (this->Input()->IsInsideForeground(i, j, k, l)) {
409 val += w * voxel_cast<RealType>(this->Input()->Get(i, j, k, l));
418 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
419 return voxel_cast<VoxelType>(this->DefaultValue());
421 return voxel_cast<VoxelType>(val / fgw);
425 template <
class TImage>
template <
class TOtherImage>
426 inline typename TOtherImage::VoxelType
428 ::Get3D(
const TOtherImage *input,
double x,
double y,
double z,
double t)
const 430 typedef typename TOtherImage::VoxelType VoxelType;
431 typedef typename TOtherImage::RealType RealType;
439 if (
fequal(x, i, _Epsilon) &&
442 return input->Get(i, j, k, l);
447 const int i1 = i - Kernel::Radius;
448 const int j1 = j - Kernel::Radius;
449 const int k1 = k - Kernel::Radius;
450 const int i2 = i + Kernel::Radius;
451 const int j2 = j + Kernel::Radius;
452 const int k2 = k + Kernel::Radius;
454 RealType val = voxel_cast<RealType>(0);
455 Real nrm(0), wz, wyz, w;
457 for (k = k1; k <= k2; ++k) {
458 wz = Kernel::Lookup(Real(z - k));
459 for (j = j1; j <= j2; ++j) {
460 wyz = Kernel::Lookup(Real(y - j)) * wz;
461 for (i = i1; i <= i2; ++i) {
462 w = Kernel::Lookup(Real(x - i)) * wyz;
463 val += w * voxel_cast<RealType>(input->Get(i, j, k, l));
469 if (nrm > 1e-3) val /= nrm;
470 else val = voxel_cast<RealType>(this->DefaultValue());
472 return voxel_cast<VoxelType>(val);
476 template <
class TImage>
template <
class TOtherImage>
477 inline typename TOtherImage::VoxelType
481 typedef typename TOtherImage::VoxelType VoxelType;
482 typedef typename TOtherImage::RealType RealType;
490 if (
fequal(x, i, _Epsilon) &&
493 if (input->IsForeground(i, j, k, l)) {
494 return input->Get(i, j, k, l);
496 return voxel_cast<VoxelType>(this->DefaultValue());
502 const int i1 = i - Kernel::Radius;
503 const int j1 = j - Kernel::Radius;
504 const int k1 = k - Kernel::Radius;
505 const int i2 = i + Kernel::Radius;
506 const int j2 = j + Kernel::Radius;
507 const int k2 = k + Kernel::Radius;
509 RealType val = voxel_cast<RealType>(0);
510 Real fgw(0), bgw(0), wz, wyz, w;
512 for (k = k1; k <= k2; ++k) {
513 wz = Kernel::Lookup(Real(z - k));
514 for (j = j1; j <= j2; ++j) {
515 wyz = Kernel::Lookup(Real(y - j)) * wz;
516 for (i = i1; i <= i2; ++i) {
517 w = Kernel::Lookup(Real(x - i)) * wyz;
518 if (input->IsForeground(i, j, k, l)) {
519 val += w * voxel_cast<RealType>(input->Get(i, j, k, l));
528 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
529 return voxel_cast<VoxelType>(this->DefaultValue());
531 return voxel_cast<VoxelType>(val / fgw);
535 template <
class TImage>
536 inline typename GenericSincInterpolateImageFunction<TImage>::VoxelType
538 ::Get4D(
double x,
double y,
double z,
double t)
const 546 if (
fequal(x, i, _Epsilon) &&
550 if (this->Input()->IsInside(i, j, k, l)) {
551 return this->Input()->Get(i, j, k, l);
553 return voxel_cast<VoxelType>(this->DefaultValue());
559 const int i1 = i - Kernel::Radius;
560 const int j1 = j - Kernel::Radius;
561 const int k1 = k - Kernel::Radius;
562 const int l1 = l - Kernel::Radius;
563 const int i2 = i + Kernel::Radius;
564 const int j2 = j + Kernel::Radius;
565 const int k2 = k + Kernel::Radius;
566 const int l2 = l + Kernel::Radius;
568 RealType val = voxel_cast<RealType>(0);
569 Real nrm(0), wt, wzt, wyzt, w;
571 for (l = l1; l <= l2; ++l) {
572 if (0 <= l && l < this->Input()->T()) {
573 wt = Kernel::Lookup(Real(t - l));
574 for (k = k1; k <= k2; ++k) {
575 if (0 <= k && k < this->Input()->Z()) {
576 wzt = Kernel::Lookup(Real(z - k)) * wt;
577 for (j = j1; j <= j2; ++j) {
578 if (0 <= j && j < this->Input()->Y()) {
579 wyzt = Kernel::Lookup(Real(y - j)) * wzt;
580 for (i = i1; i <= i2; ++i) {
581 if (0 <= i && i < this->Input()->X()) {
582 w = Kernel::Lookup(Real(x - i)) * wyzt;
583 val += w * voxel_cast<RealType>(this->Input()->Get(i, j, k, l));
594 if (nrm > 1e-3) val /= nrm;
595 else val = voxel_cast<RealType>(this->DefaultValue());
597 return voxel_cast<VoxelType>(val);
601 template <
class TImage>
602 inline typename GenericSincInterpolateImageFunction<TImage>::VoxelType
612 if (
fequal(x, i, _Epsilon) &&
616 if (this->Input()->IsInsideForeground(i, j, k, l)) {
617 return this->Input()->Get(i, j, k, l);
619 return voxel_cast<VoxelType>(this->DefaultValue());
625 const int i1 = i - Kernel::Radius;
626 const int j1 = j - Kernel::Radius;
627 const int k1 = k - Kernel::Radius;
628 const int l1 = l - Kernel::Radius;
629 const int i2 = i + Kernel::Radius;
630 const int j2 = j + Kernel::Radius;
631 const int k2 = k + Kernel::Radius;
632 const int l2 = l + Kernel::Radius;
634 RealType val = voxel_cast<RealType>(0);
635 Real fgw(0), bgw(0), wt, wzt, wyzt, w;
637 for (l = l1; l <= l2; ++l) {
638 wt = Kernel::Lookup(Real(t - l));
639 for (k = k1; k <= k2; ++k) {
640 wzt = Kernel::Lookup(Real(z - k)) * wt;
641 for (j = j1; j <= j2; ++j) {
642 wyzt = Kernel::Lookup(Real(y - j)) * wzt;
643 for (i = i1; i <= i2; ++i) {
644 w = Kernel::Lookup(Real(x - i)) * wyzt;
645 if (this->Input()->IsInsideForeground(i, j, k, l)) {
646 val += w * voxel_cast<RealType>(this->Input()->Get(i, j, k, l));
656 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
657 return voxel_cast<VoxelType>(this->DefaultValue());
659 return voxel_cast<VoxelType>(val / fgw);
663 template <
class TImage>
template <
class TOtherImage>
664 inline typename TOtherImage::VoxelType
666 ::Get4D(
const TOtherImage *input,
double x,
double y,
double z,
double t)
const 668 typedef typename TOtherImage::VoxelType VoxelType;
669 typedef typename TOtherImage::RealType RealType;
677 if (
fequal(x, i, _Epsilon) &&
681 return input->Get(i, j, k, l);
686 const int i1 = i - Kernel::Radius;
687 const int j1 = j - Kernel::Radius;
688 const int k1 = k - Kernel::Radius;
689 const int l1 = l - Kernel::Radius;
690 const int i2 = i + Kernel::Radius;
691 const int j2 = j + Kernel::Radius;
692 const int k2 = k + Kernel::Radius;
693 const int l2 = l + Kernel::Radius;
695 RealType val = voxel_cast<RealType>(0);
696 Real nrm(0), wt, wzt, wyzt, w;
698 for (l = l1; l <= l2; ++l) {
699 wt = Kernel::Lookup(Real(t - l));
700 for (k = k1; k <= k2; ++k) {
701 wzt = Kernel::Lookup(Real(z - k)) * wt;
702 for (j = j1; j <= j2; ++j) {
703 wyzt = Kernel::Lookup(Real(y - j)) * wzt;
704 for (i = i1; i <= i2; ++i) {
705 w = Kernel::Lookup(Real(x - i)) * wyzt;
706 val += w * voxel_cast<RealType>(input->Get(i, j, k, l));
713 if (nrm > 1e-3) val /= nrm;
714 else val = voxel_cast<RealType>(this->DefaultValue());
716 return voxel_cast<VoxelType>(val);
720 template <
class TImage>
template <
class TOtherImage>
721 inline typename TOtherImage::VoxelType
725 typedef typename TOtherImage::VoxelType VoxelType;
726 typedef typename TOtherImage::RealType RealType;
734 if (
fequal(x, i, _Epsilon) &&
738 if (input->IsForeground(i, j, k, l)) {
739 return input->Get(i, j, k, l);
741 return voxel_cast<VoxelType>(this->DefaultValue());
747 const int i1 = i - Kernel::Radius;
748 const int j1 = j - Kernel::Radius;
749 const int k1 = k - Kernel::Radius;
750 const int l1 = l - Kernel::Radius;
751 const int i2 = i + Kernel::Radius;
752 const int j2 = j + Kernel::Radius;
753 const int k2 = k + Kernel::Radius;
754 const int l2 = l + Kernel::Radius;
756 RealType val = voxel_cast<RealType>(0);
757 Real fgw(0), bgw(0), wt, wzt, wyzt, w;
759 for (l = l1; l <= l2; ++l) {
760 wt = Kernel::Lookup(Real(t - l));
761 for (k = k1; k <= k2; ++k) {
762 wzt = Kernel::Lookup(Real(z - k)) * wt;
763 for (j = j1; j <= j2; ++j) {
764 wyzt = Kernel::Lookup(Real(y - j)) * wzt;
765 for (i = i1; i <= i2; ++i) {
766 w = Kernel::Lookup(Real(x - i)) * wyzt;
767 if (input->IsForeground(i, j, k, l)) {
768 val += w * voxel_cast<RealType>(input->Get(i, j, k, l));
778 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
779 return voxel_cast<VoxelType>(this->DefaultValue());
781 return voxel_cast<VoxelType>(val / fgw);
785 template <
class TImage>
786 inline typename GenericSincInterpolateImageFunction<TImage>::VoxelType
788 ::Get(
double x,
double y,
double z,
double t)
const 790 switch (this->NumberOfDimensions()) {
791 case 3:
return Get3D(x, y, z, t);
792 case 2:
return Get2D(x, y, z, t);
793 default:
return Get4D(x, y, z, t);
798 template <
class TImage>
799 inline typename GenericSincInterpolateImageFunction<TImage>::VoxelType
803 switch (this->NumberOfDimensions()) {
804 case 3:
return GetWithPadding3D(x, y, z, t);
805 case 2:
return GetWithPadding2D(x, y, z, t);
806 default:
return GetWithPadding4D(x, y, z, t);
811 template <
class TImage>
template <
class TOtherImage>
812 inline typename TOtherImage::VoxelType
814 ::Get(
const TOtherImage *input,
double x,
double y,
double z,
double t)
const 816 switch (this->NumberOfDimensions()) {
817 case 3:
return Get3D(input, x, y, z, t);
818 case 2:
return Get2D(input, x, y, z, t);
819 default:
return Get4D(input, x, y, z, t);
824 template <
class TImage>
template <
class TOtherImage>
825 inline typename TOtherImage::VoxelType
829 switch (this->NumberOfDimensions()) {
830 case 3:
return GetWithPadding3D(input, x, y, z, t);
831 case 2:
return GetWithPadding2D(input, x, y, z, t);
832 default:
return GetWithPadding4D(input, x, y, z, t);
837 template <
class TImage>
838 inline typename GenericSincInterpolateImageFunction<TImage>::VoxelType
842 return Get(this->Input(), x, y, z, t);
846 template <
class TImage>
847 inline typename GenericSincInterpolateImageFunction<TImage>::VoxelType
851 if (this->Extrapolator()) {
852 return Get(this->Extrapolator(), x, y, z, t);
854 return Get(x, y, z, t);
859 template <
class TImage>
860 inline typename GenericSincInterpolateImageFunction<TImage>::VoxelType
864 return GetWithPadding(this->Input(), x, y, z, t);
868 template <
class TImage>
869 inline typename GenericSincInterpolateImageFunction<TImage>::VoxelType
873 if (this->Extrapolator()) {
874 return GetWithPadding(this->Extrapolator(), x, y, z, t);
876 return GetWithPadding(x, y, z, t);
883 #endif // MIRTK_SincInterpolateImageFunction_HXX string Get(const ParameterList ¶ms, string name)
Get parameter value from parameters list.
GenericSincInterpolateImageFunction()
Default constructor.
VoxelType GetWithPadding2D(double, double, double=0, double=0) const
VoxelType Get4D(double, double, double=0, double=0) const
virtual void Initialize()
VoxelType GetWithPadding4D(double, double, double=0, double=0) const
virtual VoxelType GetWithPaddingInside(double, double, double=0, double=0) const
MIRTKCU_API bool fequal(double a, double b, double tol=1e-12)
VoxelType Get2D(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)
virtual VoxelType GetInside(double, double, double=0, double=0) const
MIRTKCU_API bool AreEqual(double a, double b, double tol=1e-12)
Determine equality of two floating point numbers.
virtual VoxelType GetWithPadding(double, double, double=0, double=0) const
VoxelType Get(double, double, double=0, double=0) const
MIRTKCU_API int iround(T x)
Round floating-point value and cast to int.
virtual VoxelType GetWithPaddingOutside(double, double, double=0, double=0) const
virtual void BoundingInterval(double, int &, int &) const
VoxelType GetWithPadding3D(double, double, double=0, double=0) const
VoxelType Get3D(double, double, double=0, double=0) const