20 #ifndef MIRTK_FastCubicBSplineInterpolateImageFunction_HXX 21 #define MIRTK_FastCubicBSplineInterpolateImageFunction_HXX 23 #include "mirtk/FastCubicBSplineInterpolateImageFunction.h" 25 #include "mirtk/Math.h" 26 #include "mirtk/BSpline.h" 27 #include "mirtk/Matrix.h" 28 #include "mirtk/Vector3D.h" 29 #include "mirtk/Vector4D.h" 31 #include "mirtk/InterpolateImageFunction.hxx" 32 #include "mirtk/ImageToInterpolationCoefficients.h" 43 template <
class TImage>
47 _InfiniteCoefficient(NULL)
51 this->Extrapolator(ExtrapolatorType::New(Extrapolation_Mirror),
true);
55 template <
class TImage>
59 delete _InfiniteCoefficient;
63 template <
class TImage>
68 Superclass::Initialize(coeff);
74 const double margin = 2.0;
75 switch (this->NumberOfDimensions()) {
77 this->_t1 =
fdec(margin);
78 this->_t2 = this->Input()->T() - margin - 1;
80 this->_z1 =
fdec(margin);
81 this->_z2 = this->Input()->Z() - margin - 1;
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;
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()));
95 _Coefficient.Initialize(this->Input()->Attributes(), data);
99 if (!_InfiniteCoefficient || _InfiniteCoefficient->ExtrapolationMode() != this->
ExtrapolationMode()) {
100 delete _InfiniteCoefficient;
101 _InfiniteCoefficient = CoefficientExtrapolator::New(this->
ExtrapolationMode(), &_Coefficient);
103 if (_InfiniteCoefficient) {
104 _InfiniteCoefficient->Input(&_Coefficient);
105 _InfiniteCoefficient->Initialize();
110 _s2 = this->Input()->X() - 4;
111 _s3 = (this->Input()->Y() - 4) * this->Input()->X();
112 _s4 = (this->Input()->Z() - 4) * this->Input()->Y() * this->Input()->X();
116 template <
class TImage>
119 if (_Coefficient.GetDataPointer() != this->Input()->GetDataPointer()) {
120 _Coefficient = *(this->Input());
121 if (!_UseInputCoefficients) {
126 switch (this->NumberOfDimensions()) {
127 case 4: ConvertToInterpolationCoefficientsT(_Coefficient, poles, npoles);
128 case 3: ConvertToInterpolationCoefficientsZ(_Coefficient, poles, npoles);
129 default: ConvertToInterpolationCoefficientsY(_Coefficient, poles, npoles);
130 ConvertToInterpolationCoefficientsX(_Coefficient, poles, npoles);
141 template <
class TImage>
153 template <
class TImage>
154 inline typename GenericFastCubicBSplineInterpolateImageFunction<TImage>::VoxelType
156 ::Get2D(
double x,
double y,
double z,
double t)
const 163 if (k < 0 || k >= _Coefficient.Z() ||
164 l < 0 || l >= _Coefficient.T()) {
165 return voxel_cast<VoxelType>(this->DefaultValue());
168 const int A = Kernel::VariableToIndex(Real(x - i));
169 const int B = Kernel::VariableToIndex(Real(y - j));
173 RealType val = voxel_cast<RealType>(0);
177 for (
int b = 0; b <= 3; ++b) {
179 DefaultExtrapolator::Apply(jb, _Coefficient.Y() - 1);
180 for (
int a = 0; a <= 3; ++a) {
182 DefaultExtrapolator::Apply(ia, _Coefficient.X() - 1);
183 w = Kernel::LookupTable[A][a] * Kernel::LookupTable[B][b];
184 val += w * _Coefficient(ia, jb, k, l);
188 return voxel_cast<VoxelType>(val);
192 template <
class TImage>
193 inline typename GenericFastCubicBSplineInterpolateImageFunction<TImage>::VoxelType
202 if (k < 0 || k >= _Coefficient.Z() ||
203 l < 0 || l >= _Coefficient.T()) {
204 return voxel_cast<VoxelType>(this->DefaultValue());
207 const int A = Kernel::VariableToIndex(Real(x - i));
208 const int B = Kernel::VariableToIndex(Real(y - j));
212 RealType val = voxel_cast<RealType>(0);
213 Real fgw(0), bgw(0), w;
216 for (
int b = 0; b <= 3; ++b) {
218 DefaultExtrapolator::Apply(jb, _Coefficient.Y() - 1);
219 for (
int a = 0; a <= 3; ++a) {
221 DefaultExtrapolator::Apply(ia, _Coefficient.X() - 1);
222 w = Kernel::LookupTable[A][a] * Kernel::LookupTable[B][b];
223 val += w * _Coefficient(ia, jb, k, l);
224 if (this->Input()->IsInsideForeground(i + a, j + b, k, l)) {
232 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
233 val = voxel_cast<RealType>(this->DefaultValue());
235 return voxel_cast<VoxelType>(val);
239 template <
class TImage>
template <
class TCoefficient>
240 inline typename TCoefficient::VoxelType
242 ::Get2D(
const TCoefficient *coeff,
double x,
double y,
double z,
double t)
const 244 typedef typename TCoefficient::VoxelType VoxelType;
245 typedef typename TCoefficient::RealType RealType;
252 const int A = Kernel::VariableToIndex(Real(x - i));
253 const int B = Kernel::VariableToIndex(Real(y - j));
257 RealType val = voxel_cast<RealType>(0);
260 for (
int b = 0; b <= 3; ++b) {
262 val += Kernel::LookupTable[A][0] * Kernel::LookupTable[B][b] * coeff->Get(i, jb, k, l);
263 val += Kernel::LookupTable[A][1] * Kernel::LookupTable[B][b] * coeff->Get(i+1, jb, k, l);
264 val += Kernel::LookupTable[A][2] * Kernel::LookupTable[B][b] * coeff->Get(i+2, jb, k, l);
265 val += Kernel::LookupTable[A][3] * Kernel::LookupTable[B][b] * coeff->Get(i+3, jb, k, l);
268 return voxel_cast<VoxelType>(val);
272 template <
class TImage>
template <
class TOtherImage,
class TCoefficient>
273 inline typename TCoefficient::VoxelType
276 double x,
double y,
double z,
double t)
const 278 typedef typename TCoefficient::VoxelType VoxelType;
279 typedef typename TCoefficient::RealType RealType;
286 const int A = Kernel::VariableToIndex(Real(x - i));
287 const int B = Kernel::VariableToIndex(Real(y - j));
291 RealType val = voxel_cast<RealType>(0);
292 Real fgw(0), bgw(0), w;
295 for (
int b = 0; b <= 3; ++b) {
297 for (
int a = 0; a <= 3; ++a) {
299 w = Kernel::LookupTable[A][a] * Kernel::LookupTable[B][b];
300 val += w * voxel_cast<RealType>(coeff->Get(ia, jb, k, l));
301 if (input->IsForeground(ia, jb, k, l)) {
309 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
310 val = voxel_cast<RealType>(this->DefaultValue());
312 return voxel_cast<VoxelType>(val);
316 template <
class TImage>
317 inline typename GenericFastCubicBSplineInterpolateImageFunction<TImage>::VoxelType
319 ::Get3D(
double x,
double y,
double z,
double t)
const 326 if (l < 0 || l >= _Coefficient.T()) {
327 return voxel_cast<VoxelType>(this->DefaultValue());
330 const int A = Kernel::VariableToIndex(Real(x - i));
331 const int B = Kernel::VariableToIndex(Real(y - j));
332 const int C = Kernel::VariableToIndex(Real(z - k));
336 RealType val = voxel_cast<RealType>(0);
340 for (
int c = 0; c <= 3; ++c) {
342 DefaultExtrapolator::Apply(kc, _Coefficient.Z() - 1);
343 for (
int b = 0; b <= 3; ++b) {
345 DefaultExtrapolator::Apply(jb, _Coefficient.Y() - 1);
346 wyz = Kernel::LookupTable[B][b] * Kernel::LookupTable[C][c];
347 for (
int a = 0; a <= 3; ++a) {
349 DefaultExtrapolator::Apply(ia, _Coefficient.X() - 1);
350 w = Kernel::LookupTable[A][a] * wyz;
351 val += w * _Coefficient(ia, jb, kc, l);
356 return voxel_cast<VoxelType>(val);
360 template <
class TImage>
361 inline typename GenericFastCubicBSplineInterpolateImageFunction<TImage>::VoxelType
370 if (l < 0 || l >= _Coefficient.T()) {
371 return voxel_cast<VoxelType>(this->DefaultValue());
374 const int A = Kernel::VariableToIndex(Real(x - i));
375 const int B = Kernel::VariableToIndex(Real(y - j));
376 const int C = Kernel::VariableToIndex(Real(z - k));
380 RealType val = voxel_cast<RealType>(0);
381 Real fgw(0), bgw(0), wyz, w;
384 for (
int c = 0; c <= 3; ++c) {
386 DefaultExtrapolator::Apply(kc, _Coefficient.Z() - 1);
387 for (
int b = 0; b <= 3; ++b) {
389 DefaultExtrapolator::Apply(jb, _Coefficient.Y() - 1);
390 wyz = Kernel::LookupTable[B][b] * Kernel::LookupTable[C][c];
391 for (
int a = 0; a <= 3; ++a) {
393 DefaultExtrapolator::Apply(ia, _Coefficient.X() - 1);
394 w = Kernel::LookupTable[A][a] * wyz;
395 val += w * _Coefficient(ia, jb, kc, l);
396 if (this->Input()->IsInsideForeground(i + a, j + b, k + c, l)) {
405 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
406 val = voxel_cast<RealType>(this->DefaultValue());
408 return voxel_cast<VoxelType>(val);
412 template <
class TImage>
template <
class TCoefficient>
413 inline typename TCoefficient::VoxelType
415 ::Get3D(
const TCoefficient *coeff,
double x,
double y,
double z,
double t)
const 417 typedef typename TCoefficient::VoxelType VoxelType;
418 typedef typename TCoefficient::RealType RealType;
425 const int A = Kernel::VariableToIndex(Real(x - i));
426 const int B = Kernel::VariableToIndex(Real(y - j));
427 const int C = Kernel::VariableToIndex(Real(z - k));
431 RealType val = voxel_cast<RealType>(0);
435 for (
int c = 0; c <= 3; ++c) {
437 for (
int b = 0; b <= 3; ++b) {
439 wyz = Kernel::LookupTable[B][b] * Kernel::LookupTable[C][c];
440 val += Kernel::LookupTable[A][0] * wyz * voxel_cast<RealType>(coeff->Get(i, jb, kc, l));
441 val += Kernel::LookupTable[A][1] * wyz * voxel_cast<RealType>(coeff->Get(i+1, jb, kc, l));
442 val += Kernel::LookupTable[A][2] * wyz * voxel_cast<RealType>(coeff->Get(i+2, jb, kc, l));
443 val += Kernel::LookupTable[A][3] * wyz * voxel_cast<RealType>(coeff->Get(i+3, jb, kc, l));
447 return voxel_cast<VoxelType>(val);
451 template <
class TImage>
template <
class TOtherImage,
class TCoefficient>
452 inline typename TCoefficient::VoxelType
455 double x,
double y,
double z,
double t)
const 457 typedef typename TCoefficient::VoxelType VoxelType;
458 typedef typename TCoefficient::RealType RealType;
465 const int A = Kernel::VariableToIndex(Real(x - i));
466 const int B = Kernel::VariableToIndex(Real(y - j));
467 const int C = Kernel::VariableToIndex(Real(z - k));
471 RealType val = voxel_cast<RealType>(0);
472 Real fgw(0), bgw(0), wyz, w;
475 for (
int c = 0; c <= 3; ++c) {
477 DefaultExtrapolator::Apply(kc, _Coefficient.Z() - 1);
478 for (
int b = 0; b <= 3; ++b) {
480 DefaultExtrapolator::Apply(jb, _Coefficient.Y() - 1);
481 wyz = Kernel::LookupTable[B][b] * Kernel::LookupTable[C][c];
482 for (
int a = 0; a <= 3; ++a) {
484 DefaultExtrapolator::Apply(ia, _Coefficient.X() - 1);
485 w = Kernel::LookupTable[A][a] * wyz;
486 val += w * voxel_cast<RealType>(coeff->Get(ia, jb, kc, l));
487 if (input->IsForeground(i + a, j + b, k + c, l)) {
496 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
497 val = voxel_cast<RealType>(this->DefaultValue());
499 return voxel_cast<VoxelType>(val);
503 template <
class TImage>
504 inline typename GenericFastCubicBSplineInterpolateImageFunction<TImage>::VoxelType
506 ::Get4D(
double x,
double y,
double z,
double t)
const 513 const int A = Kernel::VariableToIndex(Real(x - i));
514 const int B = Kernel::VariableToIndex(Real(y - j));
515 const int C = Kernel::VariableToIndex(Real(z - k));
516 const int D = Kernel::VariableToIndex(Real(t - l));
520 RealType val = voxel_cast<RealType>(0);
524 for (
int d = 0; d <= 3; ++d) {
526 DefaultExtrapolator::Apply(ld, _Coefficient.T() - 1);
527 for (
int c = 0; c <= 3; ++c) {
529 DefaultExtrapolator::Apply(kc, _Coefficient.Z() - 1);
530 wzt = Kernel::LookupTable[C][c] * Kernel::LookupTable[D][d];
531 for (
int b = 0; b <= 3; ++b) {
533 DefaultExtrapolator::Apply(jb, _Coefficient.Y() - 1);
534 wyzt = Kernel::LookupTable[B][b] * wzt;
535 for (
int a = 0; a <= 3; ++a) {
537 DefaultExtrapolator::Apply(ia, _Coefficient.X() - 1);
538 w = Kernel::LookupTable[A][a] * wyzt;
539 val += w * _Coefficient(ia, jb, kc, ld);
545 return voxel_cast<VoxelType>(val);
549 template <
class TImage>
550 inline typename GenericFastCubicBSplineInterpolateImageFunction<TImage>::VoxelType
559 const int A = Kernel::VariableToIndex(Real(x - i));
560 const int B = Kernel::VariableToIndex(Real(y - j));
561 const int C = Kernel::VariableToIndex(Real(z - k));
562 const int D = Kernel::VariableToIndex(Real(t - l));
566 RealType val = voxel_cast<RealType>(0);
567 Real fgw(0), bgw(0), wzt, wyzt, w;
570 for (
int d = 0; d <= 3; ++d) {
572 DefaultExtrapolator::Apply(ld, _Coefficient.T() - 1);
573 for (
int c = 0; c <= 3; ++c) {
575 DefaultExtrapolator::Apply(kc, _Coefficient.Z() - 1);
576 wzt = Kernel::LookupTable[C][c] * Kernel::LookupTable[D][d];
577 for (
int b = 0; b <= 3; ++b) {
579 DefaultExtrapolator::Apply(jb, _Coefficient.Y() - 1);
580 wyzt = Kernel::LookupTable[B][b] * wzt;
581 for (
int a = 0; a <= 3; ++a) {
583 DefaultExtrapolator::Apply(ia, _Coefficient.X() - 1);
584 w = Kernel::LookupTable[A][a] * wyzt;
585 val += w * _Coefficient(ia, jb, kc, ld);
586 if (this->Input()->IsInsideForeground(i + a, j + b, k + c, l + d)) {
596 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
597 val = voxel_cast<RealType>(this->DefaultValue());
599 return voxel_cast<VoxelType>(val);
603 template <
class TImage>
template <
class TCoefficient>
604 inline typename TCoefficient::VoxelType
606 ::Get4D(
const TCoefficient *coeff,
double x,
double y,
double z,
double t)
const 608 typedef typename TCoefficient::VoxelType VoxelType;
609 typedef typename TCoefficient::RealType RealType;
616 const int A = Kernel::VariableToIndex(Real(x - i));
617 const int B = Kernel::VariableToIndex(Real(y - j));
618 const int C = Kernel::VariableToIndex(Real(z - k));
619 const int D = Kernel::VariableToIndex(Real(t - l));
623 RealType val = voxel_cast<RealType>(0);
627 for (
int d = 0; d <= 3; ++d) {
629 for (
int c = 0; c <= 3; ++c) {
631 wzt = Kernel::LookupTable[C][c] * Kernel::LookupTable[D][d];
632 for (
int b = 0; b <= 3; ++b) {
634 wyzt = Kernel::LookupTable[B][b] * wzt;
635 val += Kernel::LookupTable[A][0] * wyzt * voxel_cast<RealType>(coeff->Get(i, jb, kc, ld));
636 val += Kernel::LookupTable[A][1] * wyzt * voxel_cast<RealType>(coeff->Get(i+1, jb, kc, ld));
637 val += Kernel::LookupTable[A][2] * wyzt * voxel_cast<RealType>(coeff->Get(i+2, jb, kc, ld));
638 val += Kernel::LookupTable[A][3] * wyzt * voxel_cast<RealType>(coeff->Get(i+3, jb, kc, ld));
643 return voxel_cast<VoxelType>(val);
647 template <
class TImage>
template <
class TOtherImage,
class TCoefficient>
648 inline typename TCoefficient::VoxelType
651 double x,
double y,
double z,
double t)
const 653 typedef typename TCoefficient::VoxelType VoxelType;
654 typedef typename TCoefficient::RealType RealType;
661 const int A = Kernel::VariableToIndex(Real(x - i));
662 const int B = Kernel::VariableToIndex(Real(y - j));
663 const int C = Kernel::VariableToIndex(Real(z - k));
664 const int D = Kernel::VariableToIndex(Real(t - l));
668 RealType val = voxel_cast<RealType>(0);
669 Real fgw(0), bgw(0), wzt, wyzt, w;
672 for (
int d = 0; d <= 3; ++d) {
674 for (
int c = 0; c <= 3; ++c) {
676 wzt = Kernel::LookupTable[C][c] * Kernel::LookupTable[D][d];
677 for (
int b = 0; b <= 3; ++b) {
679 wyzt = Kernel::LookupTable[B][b] * wzt;
680 for (
int a = 0; a <= 3; ++a) {
682 w = Kernel::LookupTable[A][a] * wyzt;
683 val += w * voxel_cast<RealType>(coeff->Get(ia, jb, kc, ld));
684 if (input->IsForeground(ia, jb, kc, ld)) {
694 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
695 val = voxel_cast<RealType>(this->DefaultValue());
697 return voxel_cast<VoxelType>(val);
701 template <
class TImage>
702 inline typename GenericFastCubicBSplineInterpolateImageFunction<TImage>::VoxelType
704 ::Get(
double x,
double y,
double z,
double t)
const 706 switch (this->NumberOfDimensions()) {
707 case 3:
return Get3D(x, y, z, t);
708 case 2:
return Get2D(x, y, z, t);
709 default:
return Get4D(x, y, z, t);
714 template <
class TImage>
715 inline typename GenericFastCubicBSplineInterpolateImageFunction<TImage>::VoxelType
719 switch (this->NumberOfDimensions()) {
720 case 3:
return GetWithPadding3D(x, y, z, t);
721 case 2:
return GetWithPadding2D(x, y, z, t);
722 default:
return GetWithPadding4D(x, y, z, t);
727 template <
class TImage>
template <
class TOtherImage>
728 inline typename TOtherImage::VoxelType
730 ::Get(
const TOtherImage *coeff,
double x,
double y,
double z,
double t)
const 732 switch (this->NumberOfDimensions()) {
733 case 3:
return Get3D(coeff, x, y, z, t);
734 case 2:
return Get2D(coeff, x, y, z, t);
735 default:
return Get4D(coeff, x, y, z, t);
740 template <
class TImage>
template <
class TOtherImage,
class TCoefficient>
741 inline typename TCoefficient::VoxelType
744 double x,
double y,
double z,
double t)
const 746 switch (this->NumberOfDimensions()) {
747 case 3:
return GetWithPadding3D(input, coeff, x, y, z, t);
748 case 2:
return GetWithPadding2D(input, coeff, x, y, z, t);
749 default:
return GetWithPadding4D(input, coeff, x, y, z, t);
754 template <
class TImage>
755 inline typename GenericFastCubicBSplineInterpolateImageFunction<TImage>::VoxelType
764 const int A = Kernel::VariableToIndex(Real(x - i));
765 const int B = Kernel::VariableToIndex(Real(y - j));
769 RealType val = voxel_cast<RealType>(0);
770 const RealType *coeff = _Coefficient.Data(i, j, k, l);
772 for (
int b = 0; b <= 3; ++b, coeff += _s2) {
773 val += Kernel::LookupTable[A][0] * Kernel::LookupTable[B][b] * (*coeff), ++coeff;
774 val += Kernel::LookupTable[A][1] * Kernel::LookupTable[B][b] * (*coeff), ++coeff;
775 val += Kernel::LookupTable[A][2] * Kernel::LookupTable[B][b] * (*coeff), ++coeff;
776 val += Kernel::LookupTable[A][3] * Kernel::LookupTable[B][b] * (*coeff), ++coeff;
779 return voxel_cast<VoxelType>(val);
783 template <
class TImage>
784 inline typename GenericFastCubicBSplineInterpolateImageFunction<TImage>::VoxelType
793 const int A = Kernel::VariableToIndex(Real(x - i));
794 const int B = Kernel::VariableToIndex(Real(y - j));
795 const int C = Kernel::VariableToIndex(Real(z - k));
799 RealType val = voxel_cast<RealType>(0);
800 const RealType *coeff = _Coefficient.Data(i, j, k, l);
803 for (
int c = 0; c <= 3; ++c, coeff += _s3) {
804 for (
int b = 0; b <= 3; ++b, coeff += _s2) {
805 wyz = Kernel::LookupTable[B][b] * Kernel::LookupTable[C][c];
806 val += Kernel::LookupTable[A][0] * wyz * (*coeff), ++coeff;
807 val += Kernel::LookupTable[A][1] * wyz * (*coeff), ++coeff;
808 val += Kernel::LookupTable[A][2] * wyz * (*coeff), ++coeff;
809 val += Kernel::LookupTable[A][3] * wyz * (*coeff), ++coeff;
813 return voxel_cast<VoxelType>(val);
817 template <
class TImage>
818 inline typename GenericFastCubicBSplineInterpolateImageFunction<TImage>::VoxelType
827 const int A = Kernel::VariableToIndex(Real(x - i));
828 const int B = Kernel::VariableToIndex(Real(y - j));
829 const int C = Kernel::VariableToIndex(Real(z - k));
830 const int D = Kernel::VariableToIndex(Real(t - l));
834 RealType val = voxel_cast<RealType>(0);
835 const RealType *coeff = _Coefficient.Data(i, j, k, l);
838 for (
int d = 0; d <= 3; ++d, coeff += _s4) {
839 for (
int c = 0; c <= 3; ++c, coeff += _s3) {
840 wzt = Kernel::LookupTable[C][c] * Kernel::LookupTable[D][d];
841 for (
int b = 0; b <= 3; ++b, coeff += _s2) {
842 wyzt = Kernel::LookupTable[B][b] * wzt;
843 val += Kernel::LookupTable[A][0] * wyzt * (*coeff), ++coeff;
844 val += Kernel::LookupTable[A][1] * wyzt * (*coeff), ++coeff;
845 val += Kernel::LookupTable[A][2] * wyzt * (*coeff), ++coeff;
846 val += Kernel::LookupTable[A][3] * wyzt * (*coeff), ++coeff;
851 return voxel_cast<VoxelType>(val);
855 template <
class TImage>
856 inline typename GenericFastCubicBSplineInterpolateImageFunction<TImage>::VoxelType
861 switch (this->NumberOfDimensions()) {
862 case 3:
return GetInside3D(x, y, z, t);
863 case 2:
return GetInside2D(x, y, z, t);
864 default:
return GetInside4D(x, y, z, t);
869 template <
class TImage>
870 inline typename GenericFastCubicBSplineInterpolateImageFunction<TImage>::VoxelType
874 if (_InfiniteCoefficient) {
875 return voxel_cast<VoxelType>(
Get(_InfiniteCoefficient, x, y, z, t));
877 return Get(x, y, z, t);
882 template <
class TImage>
883 inline typename GenericFastCubicBSplineInterpolateImageFunction<TImage>::VoxelType
887 switch (this->NumberOfDimensions()) {
888 case 3:
return voxel_cast<VoxelType>(GetWithPadding3D(this->Input(), &_Coefficient, x, y, z, t));
889 case 2:
return voxel_cast<VoxelType>(GetWithPadding2D(this->Input(), &_Coefficient, x, y, z, t));
890 default:
return voxel_cast<VoxelType>(GetWithPadding4D(this->Input(), &_Coefficient, x, y, z, t));
895 template <
class TImage>
896 inline typename GenericFastCubicBSplineInterpolateImageFunction<TImage>::VoxelType
900 if (this->Extrapolator() && _InfiniteCoefficient) {
901 return voxel_cast<VoxelType>(GetWithPadding(this->Extrapolator(), _InfiniteCoefficient, x, y, z, t));
903 return GetWithPadding(x, y, z, t);
912 template <
class TImage>
923 if (k < 0 || k >= _Coefficient.Z() ||
924 l < 0 || l >= _Coefficient.T()) {
928 const int A = Kernel::VariableToIndex(Real(x - i));
929 const int B = Kernel::VariableToIndex(Real(y - j));
933 RealType dx = voxel_cast<RealType>(0);
934 RealType dy = voxel_cast<RealType>(0);
938 for (
int b = 0; b <= 3; ++b) {
940 DefaultExtrapolator::Apply(jb, _Coefficient.Y() - 1);
941 wy[0] = Kernel::LookupTable [B][b];
942 wy[1] = Kernel::LookupTable_I[B][b];
943 for (
int a = 0; a <= 3; ++a) {
945 DefaultExtrapolator::Apply(ia, _Coefficient.X() - 1);
946 wx[0] = Kernel::LookupTable [A][a];
947 wx[1] = Kernel::LookupTable_I[A][a];
948 dx += (wx[1] * wy[0]) * _Coefficient(ia, jb, k, l);
949 dy += (wx[0] * wy[1]) * _Coefficient(ia, jb, k, l);
953 for (
int r = 0; r < _Coefficient.N(); ++r) {
954 jac(r, 0) =
get(dx, r);
955 jac(r, 1) =
get(dy, r);
960 template <
class TImage>
template <
class TCoefficient>
963 double x,
double y,
double z,
double t)
const 972 const int A = Kernel::VariableToIndex(Real(x - i));
973 const int B = Kernel::VariableToIndex(Real(y - j));
977 RealType dx = voxel_cast<RealType>(0);
978 RealType dy = voxel_cast<RealType>(0);
982 for (
int b = 0; b <= 3; ++b) {
984 wy[0] = Kernel::LookupTable [B][b];
985 wy[1] = Kernel::LookupTable_I[B][b];
986 for (
int a = 0; a <= 3; ++a) {
988 wx[0] = Kernel::LookupTable [A][a];
989 wx[1] = Kernel::LookupTable_I[A][a];
990 dx += (wx[1] * wy[0]) * voxel_cast<RealType>(coeff->Get(ia, jb, k, l));
991 dy += (wx[0] * wy[1]) * voxel_cast<RealType>(coeff->Get(ia, jb, k, l));
995 for (
int r = 0; r < coeff->N(); ++r) {
996 jac(r, 0) =
get(dx, r);
997 jac(r, 1) =
get(dy, r);
1002 template <
class TImage>
1013 if (l < 0 || l >= _Coefficient.T()) {
1017 const int A = Kernel::VariableToIndex(Real(x - i));
1018 const int B = Kernel::VariableToIndex(Real(y - j));
1019 const int C = Kernel::VariableToIndex(Real(z - k));
1023 RealType dx = voxel_cast<RealType>(0);
1024 RealType dy = voxel_cast<RealType>(0);
1025 RealType dz = voxel_cast<RealType>(0);
1026 Real wx[2], wy[2], wz[2];
1029 for (
int c = 0; c <= 3; ++c) {
1031 DefaultExtrapolator::Apply(kc, _Coefficient.Z() - 1);
1032 wz[0] = Kernel::LookupTable [C][c];
1033 wz[1] = Kernel::LookupTable_I[C][c];
1034 for (
int b = 0; b <= 3; ++b) {
1036 DefaultExtrapolator::Apply(jb, _Coefficient.Y() - 1);
1037 wy[0] = Kernel::LookupTable [B][b];
1038 wy[1] = Kernel::LookupTable_I[B][b];
1039 for (
int a = 0; a <= 3; ++a) {
1041 DefaultExtrapolator::Apply(ia, _Coefficient.X() - 1);
1042 wx[0] = Kernel::LookupTable [A][a];
1043 wx[1] = Kernel::LookupTable_I[A][a];
1044 dx += (wx[1] * wy[0] * wz[0]) * _Coefficient(ia, jb, kc, l);
1045 dy += (wx[0] * wy[1] * wz[0]) * _Coefficient(ia, jb, kc, l);
1046 dz += (wx[0] * wy[0] * wz[1]) * _Coefficient(ia, jb, kc, l);
1051 for (
int r = 0; r < _Coefficient.N(); ++r) {
1052 jac(r, 0) =
get(dx, r);
1053 jac(r, 1) =
get(dy, r);
1054 jac(r, 2) =
get(dz, r);
1059 template <
class TImage>
template <
class TOtherImage>
1062 double x,
double y,
double z,
double t)
const 1071 const int A = Kernel::VariableToIndex(Real(x - i));
1072 const int B = Kernel::VariableToIndex(Real(y - j));
1073 const int C = Kernel::VariableToIndex(Real(z - k));
1077 RealType dx = voxel_cast<RealType>(0);
1078 RealType dy = voxel_cast<RealType>(0);
1079 RealType dz = voxel_cast<RealType>(0);
1080 Real wx[2], wy[2], wz[2];
1083 for (
int c = 0; c <= 3; ++c) {
1085 wz[0] = Kernel::LookupTable [C][c];
1086 wz[1] = Kernel::LookupTable_I[C][c];
1087 for (
int b = 0; b <= 3; ++b) {
1089 wy[0] = Kernel::LookupTable [B][b];
1090 wy[1] = Kernel::LookupTable_I[B][b];
1091 for (
int a = 0; a <= 3; ++a) {
1093 wx[0] = Kernel::LookupTable [A][a];
1094 wx[1] = Kernel::LookupTable_I[A][a];
1095 dx += (wx[1] * wy[0] * wz[0]) * voxel_cast<RealType>(coeff->Get(ia, jb, kc, l));
1096 dy += (wx[0] * wy[1] * wz[0]) * voxel_cast<RealType>(coeff->Get(ia, jb, kc, l));
1097 dz += (wx[0] * wy[0] * wz[1]) * voxel_cast<RealType>(coeff->Get(ia, jb, kc, l));
1102 for (
int r = 0; r < coeff->N(); ++r) {
1103 jac(r, 0) =
get(dx, r);
1104 jac(r, 1) =
get(dy, r);
1105 jac(r, 2) =
get(dz, r);
1110 template <
class TImage>
1121 const int A = Kernel::VariableToIndex(Real(x - i));
1122 const int B = Kernel::VariableToIndex(Real(y - j));
1123 const int C = Kernel::VariableToIndex(Real(z - k));
1124 const int D = Kernel::VariableToIndex(Real(t - l));
1128 RealType dx = voxel_cast<RealType>(0);
1129 RealType dy = voxel_cast<RealType>(0);
1130 RealType dz = voxel_cast<RealType>(0);
1131 RealType dt = voxel_cast<RealType>(0);
1132 Real wx[2], wy[2], wz[2], wt[2];
1135 for (
int d = 0; d <= 3; ++d) {
1137 DefaultExtrapolator::Apply(ld, _Coefficient.T() - 1);
1138 wt[0] = Kernel::LookupTable [D][d];
1139 wt[1] = Kernel::LookupTable_I[D][d];
1140 for (
int c = 0; c <= 3; ++c) {
1142 DefaultExtrapolator::Apply(kc, _Coefficient.Z() - 1);
1143 wz[0] = Kernel::LookupTable [C][c];
1144 wz[1] = Kernel::LookupTable_I[C][c];
1145 for (
int b = 0; b <= 3; ++b) {
1147 DefaultExtrapolator::Apply(jb, _Coefficient.Y() - 1);
1148 wy[0] = Kernel::LookupTable [B][b];
1149 wy[1] = Kernel::LookupTable_I[B][b];
1150 for (
int a = 0; a <= 3; ++a) {
1152 DefaultExtrapolator::Apply(ia, _Coefficient.X() - 1);
1153 wx[0] = Kernel::LookupTable [A][a];
1154 wx[1] = Kernel::LookupTable_I[A][a];
1155 dx += (wx[1] * wy[0] * wz[0] * wt[0]) * _Coefficient(ia, jb, kc, ld);
1156 dy += (wx[0] * wy[1] * wz[0] * wt[0]) * _Coefficient(ia, jb, kc, ld);
1157 dz += (wx[0] * wy[0] * wz[1] * wt[0]) * _Coefficient(ia, jb, kc, ld);
1158 dt += (wx[0] * wy[0] * wz[0] * wt[1]) * _Coefficient(ia, jb, kc, ld);
1164 for (
int r = 0; r < _Coefficient.N(); ++r) {
1165 jac(r, 0) =
get(dx, r);
1166 jac(r, 1) =
get(dy, r);
1167 jac(r, 2) =
get(dz, r);
1168 jac(r, 3) =
get(dt, r);
1173 template <
class TImage>
template <
class TOtherImage>
1176 double x,
double y,
double z,
double t)
const 1185 const int A = Kernel::VariableToIndex(Real(x - i));
1186 const int B = Kernel::VariableToIndex(Real(y - j));
1187 const int C = Kernel::VariableToIndex(Real(z - k));
1188 const int D = Kernel::VariableToIndex(Real(t - l));
1192 RealType dx = voxel_cast<RealType>(0);
1193 RealType dy = voxel_cast<RealType>(0);
1194 RealType dz = voxel_cast<RealType>(0);
1195 RealType dt = voxel_cast<RealType>(0);
1196 Real wx[2], wy[2], wz[2], wt[2];
1199 for (
int d = 0; d <= 3; ++d) {
1201 wt[0] = Kernel::LookupTable [D][d];
1202 wt[1] = Kernel::LookupTable_I[D][d];
1203 for (
int c = 0; c <= 3; ++c) {
1205 wz[0] = Kernel::LookupTable [C][c];
1206 wz[1] = Kernel::LookupTable_I[C][c];
1207 for (
int b = 0; b <= 3; ++b) {
1209 wy[0] = Kernel::LookupTable [B][b];
1210 wy[1] = Kernel::LookupTable_I[B][b];
1211 for (
int a = 0; a <= 3; ++a) {
1213 wx[0] = Kernel::LookupTable [A][a];
1214 wx[1] = Kernel::LookupTable_I[A][a];
1215 dx += (wx[1] * wy[0] * wz[0] * wt[0]) * voxel_cast<RealType>(coeff->Get(ia, jb, kc, ld));
1216 dy += (wx[0] * wy[1] * wz[0] * wt[0]) * voxel_cast<RealType>(coeff->Get(ia, jb, kc, ld));
1217 dz += (wx[0] * wy[0] * wz[1] * wt[0]) * voxel_cast<RealType>(coeff->Get(ia, jb, kc, ld));
1218 dt += (wx[0] * wy[0] * wz[0] * wt[1]) * voxel_cast<RealType>(coeff->Get(ia, jb, kc, ld));
1224 for (
int r = 0; r < _Coefficient.N(); ++r) {
1225 jac(r, 0) =
get(dx, r);
1226 jac(r, 1) =
get(dy, r);
1227 jac(r, 2) =
get(dz, r);
1228 jac(r, 3) =
get(dt, r);
1233 template <
class TImage>
1237 switch (this->NumberOfDimensions()) {
1238 case 3:
return Jacobian3D(jac, x, y, z, t);
1239 case 2:
return Jacobian2D(jac, x, y, z, t);
1240 default:
return Jacobian4D(jac, x, y, z, t);
1245 template <
class TImage>
template <
class TOtherImage>
1248 double x,
double y,
double z,
double t)
const 1250 switch (this->NumberOfDimensions()) {
1251 case 3:
return Jacobian3D(jac, coeff, x, y, z, t);
1252 case 2:
return Jacobian2D(jac, coeff, x, y, z, t);
1253 default:
return Jacobian4D(jac, coeff, x, y, z, t);
1258 template <
class TImage>
1262 Jacobian(jac, &_Coefficient, x, y, z, t);
1266 template <
class TImage>
1270 Jacobian(jac, _InfiniteCoefficient, x, y, z, t);
1276 #endif // MIRTK_FastCubicBSplineInterpolateImageFunction_HXX VoxelType Get4D(double, double, double=0, double=0) const
virtual void BoundingInterval(double, int &, int &) const
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
GenericFastCubicBSplineInterpolateImageFunction()
Constructor.
VoxelType GetWithPadding2D(double, double, double=0, double=0) const
void SplinePoles(int degree, TReal pole[2], int &npoles)
Recover spline poles from a lookup table.
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.
string Get(const ParameterList ¶ms, string name)
Get parameter value from parameters list.
VoxelType GetWithPadding4D(double, double, double=0, double=0) const
virtual void Update()
Update spline coefficients.
virtual void Initialize()
virtual void EvaluateJacobianInside(Matrix &, double, double, double=0, double=0) const
Get 1st order derivatives of given image at arbitrary location (in pixels)
VoxelType Get2D(double, double, double=0, double=0) const
virtual VoxelType GetWithPaddingInside(double, double, double=0, double=0) const
void FillBackgroundBeforeConversionToSplineCoefficients(GenericImage< TData > &image)
Fill background by front propagation of foreground.
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)
MIRTKCU_API int ifloor(T x)
Round floating-point value to next smaller integer and cast to int.
VoxelType Get(double, double, double=0, double=0) const
MIRTKCU_API double fdec(double f)
virtual VoxelType GetWithPadding(double, double, double=0, double=0) const
virtual VoxelType GetWithPaddingOutside(double, double, double=0, double=0) const
void Initialize(int, int=-1, double *=NULL)
Initialize matrix with number of rows and columns.
virtual ~GenericFastCubicBSplineInterpolateImageFunction()
Destructor.
virtual VoxelType GetOutside(double, double, double=0, double=0) const
Evaluate generic image at an arbitrary location (in pixels)
ExtrapolationMode
Image extrapolation modes.
VoxelType GetWithPadding3D(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.
void Jacobian2D(Matrix &, double, double, double=0, double=0) const
virtual VoxelType GetInside(double, double, double=0, double=0) const
VoxelType Get3D(double, double, double=0, double=0) const
MIRTKCU_API int iround(T x)
Round floating-point value and cast to int.
virtual VoxelType GetInside2D(double, double, double=0, double=0) const
Evaluate generic 2D image without handling boundary conditions.