20 #ifndef MIRTK_BSplineInterpolateImageFunction_HXX 21 #define MIRTK_BSplineInterpolateImageFunction_HXX 23 #include "mirtk/BSplineInterpolateImageFunction.h" 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" 39 template <
class TImage>
43 _SplineDegree (degree),
44 _InfiniteCoefficient(NULL)
48 this->Extrapolator(ExtrapolatorType::New(Extrapolation_Mirror),
true);
52 template <
class TImage>
56 delete _InfiniteCoefficient;
60 template <
class TImage>
65 Superclass::Initialize(coeff);
68 if (_SplineDegree < 2 || _SplineDegree > 5) {
69 cerr << this->NameOfClass() <<
"::Initialize: Spline degree must be 2, 3, 4, or 5" << endl;
74 const double margin = round(static_cast<double>(_SplineDegree) / 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 template <
class TImage>
113 if (_Coefficient.GetDataPointer() != this->Input()->GetDataPointer()) {
114 _Coefficient = *(this->Input());
115 if (!_UseInputCoefficients) {
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);
135 template <
class TImage>
139 if (_SplineDegree & 1) i =
ifloor(x ) - _SplineDegree / 2;
140 else i =
ifloor(x + 0.5) - _SplineDegree / 2;
141 I = i + _SplineDegree;
149 template <
class TImage>
150 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
152 ::Get2D(
double x,
double y,
double z,
double t)
const 157 if (k < 0 || k >= _Coefficient.Z() ||
158 l < 0 || l >= _Coefficient.T()) {
159 return voxel_cast<VoxelType>(this->DefaultValue());
169 RealType val = voxel_cast<RealType>(0);
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);
179 return voxel_cast<VoxelType>(val);
183 template <
class TImage>
184 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
191 if (k < 0 || k >= _Coefficient.Z() ||
192 l < 0 || l >= _Coefficient.T()) {
193 return voxel_cast<VoxelType>(this->DefaultValue());
197 int i [6], j [6], ia, jb;
203 RealType val = voxel_cast<RealType>(0);
204 Real fgw(0), bgw(0), w;
206 for (
int b = 0; b <= _SplineDegree; ++b) {
208 DefaultExtrapolator::Apply(jb, _Coefficient.Y() - 1);
209 for (
int a = 0; a <= _SplineDegree; ++a) {
211 DefaultExtrapolator::Apply(ia, _Coefficient.X() - 1);
213 val += w * _Coefficient(ia, jb, k, l);
214 if (this->Input()->IsInsideForeground(i[a], j[b], k, l)) {
222 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
223 val = voxel_cast<RealType>(this->DefaultValue());
225 return voxel_cast<VoxelType>(val);
229 template <
class TImage>
template <
class TCoefficient>
231 ::Get2D(
const TCoefficient *coeff,
double x,
double y,
double z,
double t)
const 233 typedef typename TCoefficient::VoxelType VoxelType;
234 typedef typename TCoefficient::RealType RealType;
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));
253 return voxel_cast<VoxelType>(val);
257 template <
class TImage>
template <
class TOtherImage,
class TCoefficient>
260 double x,
double y,
double z,
double t)
const 262 typedef typename TCoefficient::VoxelType VoxelType;
263 typedef typename TCoefficient::RealType RealType;
275 RealType val = voxel_cast<RealType>(0);
276 Real fgw(0), bgw(0), w;
278 for (
int b = 0; b <= _SplineDegree; ++b) {
279 for (
int a = 0; a <= _SplineDegree; ++a) {
281 val += w * voxel_cast<RealType>(coeff->Get(i[a], j[b], k, l));
282 if (image->IsForeground(i[a], j[b], k, l)) {
290 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
291 val = voxel_cast<RealType>(this->DefaultValue());
293 return voxel_cast<VoxelType>(val);
297 template <
class TImage>
298 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
300 ::Get3D(
double x,
double y,
double z,
double t)
const 304 if (l < 0 || l >= _Coefficient.T()) {
305 return voxel_cast<VoxelType>(this->DefaultValue());
309 int i [6], j [6], k [6];
310 Real wx[6], wy[6], wz[6];
315 RealType val = voxel_cast<RealType>(0);
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);
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);
330 return voxel_cast<VoxelType>(val);
334 template <
class TImage>
335 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
341 if (l < 0 || l >= _Coefficient.T()) {
342 return voxel_cast<VoxelType>(this->DefaultValue());
346 int i [6], j [6], k [6], ia, jb, kc;
347 Real wx[6], wy[6], wz[6];
352 RealType val = voxel_cast<RealType>(0);
353 Real fgw(0), bgw(0), wyz, w;
355 for (
int c = 0; c <= _SplineDegree; ++c) {
357 DefaultExtrapolator::Apply(kc, _Coefficient.Z() - 1);
358 for (
int b = 0; b <= _SplineDegree; ++b) {
360 DefaultExtrapolator::Apply(jb, _Coefficient.Y() - 1);
362 for (
int a = 0; a <= _SplineDegree; ++a) {
364 DefaultExtrapolator::Apply(ia, _Coefficient.X() - 1);
366 val += w * _Coefficient(ia, jb, kc, l);
367 if (this->Input()->IsInsideForeground(i[a], j[b], k[c], l)) {
376 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
377 val = voxel_cast<RealType>(this->DefaultValue());
379 return voxel_cast<VoxelType>(val);
383 template <
class TImage>
template <
class TCoefficient>
385 ::Get3D(
const TCoefficient *coeff,
double x,
double y,
double z,
double t)
const 387 typedef typename TCoefficient::VoxelType VoxelType;
388 typedef typename TCoefficient::RealType RealType;
393 int i [6], j [6], k [6];
394 Real wx[6], wy[6], wz[6];
399 RealType val = voxel_cast<RealType>(0);
402 for (
int c = 0; c <= _SplineDegree; ++c) {
403 for (
int b = 0; b <= _SplineDegree; ++b) {
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));
411 return voxel_cast<VoxelType>(val);
415 template <
class TImage>
template <
class TOtherImage,
class TCoefficient>
418 double x,
double y,
double z,
double t)
const 420 typedef typename TCoefficient::RealType RealType;
425 int i [6], j [6], k [6];
426 Real wx[6], wy[6], wz[6];
431 RealType val = voxel_cast<RealType>(0);
432 Real fgw(0), bgw(0), wyz, w;
434 for (
int c = 0; c <= _SplineDegree; ++c) {
435 for (
int b = 0; b <= _SplineDegree; ++b) {
437 for (
int a = 0; a <= _SplineDegree; ++a) {
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)) {
449 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
450 val = voxel_cast<RealType>(this->DefaultValue());
452 return voxel_cast<
typename TCoefficient::VoxelType>(val);
456 template <
class TImage>
457 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
459 ::Get4D(
double x,
double y,
double z,
double t)
const 462 int i [6], j [6], k [6], l [6];
463 Real wx[6], wy[6], wz[6], wt[6];
465 ComputeBSplineIndicesAndWeights(x, y, z, t, _SplineDegree, i, j, k, l, wx, wy, wz, wt);
468 RealType val = voxel_cast<RealType>(0);
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);
476 for (
int b = 0; b <= _SplineDegree; ++b) {
477 DefaultExtrapolator::Apply(j[b], _Coefficient.Y() - 1);
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]);
487 return voxel_cast<VoxelType>(val);
491 template <
class TImage>
492 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
497 int i [6], j [6], k [6], l [6], ia, jb, kc, ld;
498 Real wx[6], wy[6], wz[6], wt[6];
500 ComputeBSplineIndicesAndWeights(x, y, z, t, _SplineDegree, i, j, k, l, wx, wy, wz, wt);
503 RealType val = voxel_cast<RealType>(0);
504 Real fgw(0), bgw(0), wzt, wyzt, w;
506 for (
int d = 0; d <= _SplineDegree; ++d) {
508 DefaultExtrapolator::Apply(ld, _Coefficient.T() - 1);
509 for (
int c = 0; c <= _SplineDegree; ++c) {
511 DefaultExtrapolator::Apply(kc, _Coefficient.Z() - 1);
513 for (
int b = 0; b <= _SplineDegree; ++b) {
515 DefaultExtrapolator::Apply(jb, _Coefficient.Y() - 1);
517 for (
int a = 0; a <= _SplineDegree; ++a) {
519 DefaultExtrapolator::Apply(ia, _Coefficient.X() - 1);
521 val += w * _Coefficient(ia, jb, kc, ld);
522 if (this->Input()->IsInsideForeground(i[a], j[b], k[c], l[d])) {
532 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
533 val = voxel_cast<RealType>(this->DefaultValue());
535 return voxel_cast<VoxelType>(val);
539 template <
class TImage>
template <
class TCoefficient>
541 ::Get4D(
const TCoefficient *coeff,
double x,
double y,
double z,
double t)
const 543 typedef typename TCoefficient::VoxelType VoxelType;
544 typedef typename TCoefficient::RealType RealType;
547 int i [6], j [6], k [6], l [6];
548 Real wx[6], wy[6], wz[6], wt[6];
550 ComputeBSplineIndicesAndWeights(x, y, z, t, _SplineDegree, i, j, k, l, wx, wy, wz, wt);
553 RealType val = voxel_cast<RealType>(0);
556 for (
int d = 0; d <= _SplineDegree; ++d) {
557 for (
int c = 0; c <= _SplineDegree; ++c) {
559 for (
int b = 0; b <= _SplineDegree; ++b) {
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]));
568 return voxel_cast<VoxelType>(val);
572 template <
class TImage>
template <
class TOtherImage,
class TCoefficient>
575 double x,
double y,
double z,
double t)
const 577 typedef typename TCoefficient::VoxelType VoxelType;
578 typedef typename TCoefficient::RealType RealType;
581 int i [6], j [6], k [6], l [6];
582 Real wx[6], wy[6], wz[6], wt[6];
584 ComputeBSplineIndicesAndWeights(x, y, z, t, _SplineDegree, i, j, k, l, wx, wy, wz, wt);
587 RealType val = voxel_cast<RealType>(0);
588 Real fgw(0), bgw(0), wzt, wyzt, w;
590 for (
int d = 0; d <= _SplineDegree; ++d) {
591 for (
int c = 0; c <= _SplineDegree; ++c) {
593 for (
int b = 0; b <= _SplineDegree; ++b) {
595 for (
int a = 0; a <= _SplineDegree; ++a) {
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])) {
608 if (bgw > fgw ||
AreEqual(bgw, fgw, 1e-3)) {
609 val = voxel_cast<RealType>(this->DefaultValue());
611 return voxel_cast<VoxelType>(val);
615 template <
class TImage>
616 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
618 ::Get(
double x,
double y,
double z,
double t)
const 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);
628 template <
class TImage>
629 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
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);
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 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);
654 template <
class TImage>
template <
class TOtherImage,
class TCoefficient>
655 typename TCoefficient::VoxelType
658 double x,
double y,
double z,
double t)
const 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);
668 template <
class TImage>
669 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
673 return voxel_cast<VoxelType>(
Get(&_Coefficient, x, y, z, t));
677 template <
class TImage>
678 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
682 if (_InfiniteCoefficient) {
683 return voxel_cast<VoxelType>(
Get(_InfiniteCoefficient, x, y, z, t));
685 return Get(x, y, z, t);
690 template <
class TImage>
691 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
695 return voxel_cast<VoxelType>(GetWithPadding(this->Input(), &_Coefficient, x, y, z, t));
699 template <
class TImage>
700 typename GenericBSplineInterpolateImageFunction<TImage>::VoxelType
704 if (this->Extrapolator() && _InfiniteCoefficient) {
705 return voxel_cast<VoxelType>(GetWithPadding(this->Extrapolator(), _InfiniteCoefficient, x, y, z, t));
707 return GetWithPadding(x, y, z, t);
714 #endif // MIRTK_BSplineInterpolateImageFunction_HXX GenericBSplineInterpolateImageFunction(int=3)
Constructor.
virtual ~GenericBSplineInterpolateImageFunction()
Destructor.
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 ¶ms, string name)
Get parameter value from parameters list.
VoxelType Get2D(double, double, double=0, double=0) const
virtual void Initialize()
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.
virtual void Update()
Update spline coefficients.
MIRTKCU_API double fdec(double f)
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.
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.
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.
virtual VoxelType GetWithPaddingInside(double, double, double=0, double=0) const