20 #ifndef MIRTK_LinearInterpolateImageFunction_HXX 21 #define MIRTK_LinearInterpolateImageFunction_HXX 23 #include "mirtk/LinearInterpolateImageFunction.h" 24 #include "mirtk/InterpolateImageFunction.hxx" 26 #include "mirtk/Math.h" 27 #include "mirtk/VoxelCast.h" 38 template <
class TImage>
45 template <
class TImage>
52 template <
class TImage>
56 Superclass::Initialize(coeff);
59 switch (this->NumberOfDimensions()) {
62 this->_t2 =
fdec(this->Input()->T() - 1);
65 this->_z2 =
fdec(this->Input()->Z() - 1);
68 this->_y2 =
fdec(this->Input()->Y() - 1);
70 this->_x2 =
fdec(this->Input()->X() - 1);
74 const int xoffset[2] = {0, 1};
75 const int yoffset[2] = {0, this->Input()->X()};
76 const int zoffset[2] = {0, this->Input()->X() * this->Input()->Y()};
77 const int toffset[2] = {0, this->Input()->X() * this->Input()->Y() * this->Input()->Z()};
80 for (
int d = 0; d <= 1; ++d)
81 for (
int c = 0; c <= 1; ++c)
82 for (
int b = 0; b <= 1; ++b)
83 for (
int a = 0; a <= 1; ++a, ++idx) {
84 _Offset[idx] = xoffset[a] + yoffset[b] + zoffset[c] + toffset[d];
93 template <
class TImage>
98 w[1] =
static_cast<Real
>(x) - static_cast<Real>(i);
99 w[0] =
static_cast<Real
>(1) - w[1];
108 template <
class TImage>
120 template <
class TImage>
121 inline typename GenericLinearInterpolateImageFunction<TImage>::VoxelType
123 ::Get2D(
double x,
double y,
double z,
double t)
const 127 if (k < 0 || k >= this->Input()->Z() ||
128 l < 0 || l >= this->Input()->T()) {
129 return voxel_cast<VoxelType>(this->DefaultValue());
133 const int i = ComputeWeights(x, wx);
134 const int j = ComputeWeights(y, wy);
136 RealType val = voxel_cast<RealType>(0);
140 for (
int b = 0; b <= 1; ++b) {
142 if (0 <= jb && jb < this->Input()->Y()) {
143 for (
int a = 0; a <= 1; ++a) {
145 if (0 <= ia && ia < this->Input()->X()) {
147 val += w * voxel_cast<RealType>(this->Input()->Get(ia, jb, k, l));
154 if (nrm > Real(1e-3)) val /= nrm;
155 else val = voxel_cast<RealType>(this->DefaultValue());
157 return voxel_cast<VoxelType>(val);
161 template <
class TImage>
162 inline typename GenericLinearInterpolateImageFunction<TImage>::VoxelType
168 if (k < 0 || k >= this->Input()->Z() ||
169 l < 0 || l >= this->Input()->T()) {
170 return voxel_cast<VoxelType>(this->DefaultValue());
174 const int i = ComputeWeights(x, wx);
175 const int j = ComputeWeights(y, wy);
177 RealType val = voxel_cast<RealType>(0);
181 for (
int b = 0; b <= 1; ++b) {
183 for (
int a = 0; a <= 1; ++a) {
186 if (this->Input()->IsInsideForeground(ia, jb, k, l)) {
187 val += w * voxel_cast<RealType>(this->Input()->Get(ia, jb, k, l));
193 if (
ifloor(fgw * 1.e3) > 500) val /= fgw;
194 else val = voxel_cast<RealType>(this->DefaultValue());
196 return voxel_cast<VoxelType>(val);
200 template <
class TImage>
template <
class TOtherImage>
201 inline typename TOtherImage::VoxelType
203 ::Get2D(
const TOtherImage *input,
double x,
double y,
double z,
double t)
const 205 typedef typename TOtherImage::VoxelType VoxelType;
206 typedef typename TOtherImage::RealType RealType;
209 const int i = ComputeWeights(x, wx), I = i + 1;
210 const int j = ComputeWeights(y, wy), J = j + 1;
214 const auto v00 = voxel_cast<RealType>(input->Get(i, j, k, l));
215 const auto v01 = voxel_cast<RealType>(input->Get(I, j, k, l));
216 const auto v10 = voxel_cast<RealType>(input->Get(i, J, k, l));
217 const auto v11 = voxel_cast<RealType>(input->Get(I, J, k, l));
219 return voxel_cast<VoxelType>(wy[0] * (wx[0] * v00 + wx[1] * v01) +
220 wy[1] * (wx[0] * v10 + wx[1] * v11));
224 template <
class TImage>
template <
class TOtherImage>
225 inline typename TOtherImage::VoxelType
229 typedef typename TOtherImage::VoxelType VoxelType;
230 typedef typename TOtherImage::RealType RealType;
234 if (k < 0 || k >= input->Z() ||
235 l < 0 || l >= input->T()) {
236 return voxel_cast<VoxelType>(this->DefaultValue());
240 const int i = ComputeWeights(x, wx);
241 const int j = ComputeWeights(y, wy);
243 RealType val = voxel_cast<RealType>(0);
247 for (
int b = 0; b <= 1; ++b) {
249 for (
int a = 0; a <= 1; ++a) {
252 if (input->IsForeground(ia, jb, k, l)) {
253 val += w * voxel_cast<RealType>(input->Get(ia, jb, k, l));
259 if (
ifloor(fgw * 1.e3) > 500) val /= fgw;
260 else val = voxel_cast<RealType>(this->DefaultValue());
262 return voxel_cast<VoxelType>(val);
266 template <
class TImage>
267 inline typename GenericLinearInterpolateImageFunction<TImage>::VoxelType
269 ::Get3D(
double x,
double y,
double z,
double t)
const 272 if (l < 0 || l >= this->Input()->T()) {
273 return voxel_cast<VoxelType>(this->DefaultValue());
276 Real wx[2], wy[2], wz[2];
277 const int i = ComputeWeights(x, wx);
278 const int j = ComputeWeights(y, wy);
279 const int k = ComputeWeights(z, wz);
281 RealType val = voxel_cast<RealType>(0);
285 for (
int c = 0; c <= 1; ++c) {
287 if (0 <= kc && kc < this->Input()->Z()) {
288 for (
int b = 0; b <= 1; ++b) {
290 if (0 <= jb && jb < this->Input()->Y()) {
291 for (
int a = 0; a <= 1; ++a) {
293 if (0 <= ia && ia < this->Input()->X()) {
294 w = wx[a] * wy[b] * wz[c];
295 val += w * voxel_cast<RealType>(this->Input()->Get(ia, jb, kc, l));
304 if (nrm > Real(1e-3)) val /= nrm;
305 else val = voxel_cast<RealType>(this->DefaultValue());
307 return voxel_cast<VoxelType>(val);
311 template <
class TImage>
312 inline typename GenericLinearInterpolateImageFunction<TImage>::VoxelType
317 if (l < 0 || l >= this->Input()->T()) {
318 return voxel_cast<VoxelType>(this->DefaultValue());
321 Real wx[2], wy[2], wz[2];
322 const int i = ComputeWeights(x, wx);
323 const int j = ComputeWeights(y, wy);
324 const int k = ComputeWeights(z, wz);
326 RealType val = voxel_cast<RealType>(0);
330 for (
int c = 0; c <= 1; ++c) {
332 for (
int b = 0; b <= 1; ++b) {
334 for (
int a = 0; a <= 1; ++a) {
336 w = wx[a] * wy[b] * wz[c];
337 if (this->Input()->IsInsideForeground(ia, jb, kc, l)) {
338 val += w * voxel_cast<RealType>(this->Input()->Get(ia, jb, kc, l));
345 if (
ifloor(fgw * 1.e3) > 500) val /= fgw;
346 else val = voxel_cast<RealType>(this->DefaultValue());
348 return voxel_cast<VoxelType>(val);
352 template <
class TImage>
template <
class TOtherImage>
353 inline typename TOtherImage::VoxelType
355 ::Get3D(
const TOtherImage *input,
double x,
double y,
double z,
double t)
const 357 typedef typename TOtherImage::VoxelType VoxelType;
358 typedef typename TOtherImage::RealType RealType;
360 Real wx[2], wy[2], wz[2];
361 const int i = ComputeWeights(x, wx), I = i + 1;
362 const int j = ComputeWeights(y, wy), J = j + 1;
363 const int k = ComputeWeights(z, wz), K = k + 1;
366 const auto v000 = voxel_cast<RealType>(input->Get(i, j, k, l));
367 const auto v001 = voxel_cast<RealType>(input->Get(I, j, k, l));
368 const auto v010 = voxel_cast<RealType>(input->Get(i, J, k, l));
369 const auto v011 = voxel_cast<RealType>(input->Get(I, J, k, l));
370 const auto v100 = voxel_cast<RealType>(input->Get(i, j, K, l));
371 const auto v101 = voxel_cast<RealType>(input->Get(I, j, K, l));
372 const auto v110 = voxel_cast<RealType>(input->Get(i, J, K, l));
373 const auto v111 = voxel_cast<RealType>(input->Get(I, J, K, l));
375 return voxel_cast<VoxelType>(wz[0] * (wy[0] * (wx[0] * v000 + wx[1] * v001) +
376 wy[1] * (wx[0] * v010 + wx[1] * v011)) +
377 wz[1] * (wy[0] * (wx[0] * v100 + wx[1] * v101) +
378 wy[1] * (wx[0] * v110 + wx[1] * v111)));
382 template <
class TImage>
template <
class TOtherImage>
383 inline typename TOtherImage::VoxelType
387 typedef typename TOtherImage::VoxelType VoxelType;
388 typedef typename TOtherImage::RealType RealType;
391 if (l < 0 || l >= input->T()) {
392 return voxel_cast<VoxelType>(this->DefaultValue());
395 Real wx[2], wy[2], wz[2];
396 const int i = ComputeWeights(x, wx);
397 const int j = ComputeWeights(y, wy);
398 const int k = ComputeWeights(z, wz);
400 RealType val = voxel_cast<RealType>(0);
404 for (
int c = 0; c <= 1; ++c) {
406 for (
int b = 0; b <= 1; ++b) {
409 for (
int a = 0; a <= 1; ++a) {
412 if (input->IsForeground(ia, jb, kc, l)) {
413 val += w *
static_cast<RealType
>(input->Get(ia, jb, kc, l));
420 if (
ifloor(fgw * 1.e3) > 500) val /= fgw;
421 else val = voxel_cast<RealType>(this->DefaultValue());
423 return voxel_cast<VoxelType>(val);
427 template <
class TImage>
428 inline typename GenericLinearInterpolateImageFunction<TImage>::VoxelType
430 ::Get4D(
double x,
double y,
double z,
double t)
const 432 Real wx[2], wy[2], wz[2], wt[2];
433 const int i = ComputeWeights(x, wx);
434 const int j = ComputeWeights(y, wy);
435 const int k = ComputeWeights(z, wz);
436 const int l = ComputeWeights(t, wt);
438 RealType val = voxel_cast<RealType>(0);
442 for (
int d = 0; d <= 1; ++d) {
444 if (0 <= ld && ld < this->Input()->T()) {
445 for (
int c = 0; c <= 1; ++c) {
447 if (0 <= kc && kc < this->Input()->Z()) {
448 for (
int b = 0; b <= 1; ++b) {
450 if (0 <= jb && jb < this->Input()->Y()) {
451 for (
int a = 0; a <= 1; ++a) {
453 if (0 <= ia && ia < this->Input()->X()) {
454 w = wx[a] * wy[b] * wz[c] * wt[d];
455 val += w * voxel_cast<RealType>(this->Input()->Get(ia, jb, kc, ld));
466 if (nrm > Real(1e-3)) val /= nrm;
467 else val = voxel_cast<RealType>(this->DefaultValue());
469 return voxel_cast<VoxelType>(val);
473 template <
class TImage>
474 inline typename GenericLinearInterpolateImageFunction<TImage>::VoxelType
478 Real wx[2], wy[2], wz[2], wt[2];
479 const int i = ComputeWeights(x, wx);
480 const int j = ComputeWeights(y, wy);
481 const int k = ComputeWeights(z, wz);
482 const int l = ComputeWeights(t, wt);
484 RealType val = voxel_cast<RealType>(0);
488 for (
int d = 0; d <= 1; ++d) {
490 for (
int c = 0; c <= 1; ++c) {
492 for (
int b = 0; b <= 1; ++b) {
494 for (
int a = 0; a <= 1; ++a) {
496 w = wx[a] * wy[b] * wz[c] * wt[d];
497 if (this->Input()->IsInsideForeground(ia, jb, kc, ld)) {
498 val += w * voxel_cast<RealType>(this->Input()->Get(ia, jb, kc, ld));
506 if (
ifloor(fgw * 1.e3) > 500) val /= fgw;
507 else val = voxel_cast<RealType>(this->DefaultValue());
509 return voxel_cast<VoxelType>(val);
513 template <
class TImage>
template <
class TOtherImage>
514 inline typename TOtherImage::VoxelType
516 ::Get4D(
const TOtherImage *input,
double x,
double y,
double z,
double t)
const 518 typedef typename TOtherImage::VoxelType VoxelType;
519 typedef typename TOtherImage::RealType RealType;
521 Real wx[2], wy[2], wz[2], wt[2];
522 const int i = ComputeWeights(x, wx), I = i + 1;
523 const int j = ComputeWeights(y, wy), J = j + 1;
524 const int k = ComputeWeights(z, wz), K = k + 1;
525 const int l = ComputeWeights(t, wt), L = l + 1;
527 const auto v0000 = voxel_cast<RealType>(input->Get(i, j, k, l));
528 const auto v0001 = voxel_cast<RealType>(input->Get(I, j, k, l));
529 const auto v0010 = voxel_cast<RealType>(input->Get(i, J, k, l));
530 const auto v0011 = voxel_cast<RealType>(input->Get(I, J, k, l));
531 const auto v0100 = voxel_cast<RealType>(input->Get(i, j, K, l));
532 const auto v0101 = voxel_cast<RealType>(input->Get(I, j, K, l));
533 const auto v0110 = voxel_cast<RealType>(input->Get(i, J, K, l));
534 const auto v0111 = voxel_cast<RealType>(input->Get(I, J, K, l));
535 const auto v1000 = voxel_cast<RealType>(input->Get(i, j, k, L));
536 const auto v1001 = voxel_cast<RealType>(input->Get(I, j, k, L));
537 const auto v1010 = voxel_cast<RealType>(input->Get(i, J, k, L));
538 const auto v1011 = voxel_cast<RealType>(input->Get(I, J, k, L));
539 const auto v1100 = voxel_cast<RealType>(input->Get(i, j, K, L));
540 const auto v1101 = voxel_cast<RealType>(input->Get(I, j, K, L));
541 const auto v1110 = voxel_cast<RealType>(input->Get(i, J, K, L));
542 const auto v1111 = voxel_cast<RealType>(input->Get(I, J, K, L));
544 return voxel_cast<VoxelType>(wt[0] * (wz[0] * (wy[0] * (wx[0] * v0000 + wx[1] * v0001) +
545 wy[1] * (wx[0] * v0010 + wx[1] * v0011)) +
546 wz[1] * (wy[0] * (wx[0] * v0100 + wx[1] * v0101) +
547 wy[1] * (wx[0] * v0110 + wx[1] * v0111))) +
548 wt[1] * (wz[0] * (wy[0] * (wx[0] * v1000 + wx[1] * v1001) +
549 wy[1] * (wx[0] * v1010 + wx[1] * v1011)) +
550 wz[1] * (wy[0] * (wx[0] * v1100 + wx[1] * v1101) +
551 wy[1] * (wx[0] * v1110 + wx[1] * v1111))));
555 template <
class TImage>
template <
class TOtherImage>
556 inline typename TOtherImage::VoxelType
560 typedef typename TOtherImage::VoxelType VoxelType;
561 typedef typename TOtherImage::RealType RealType;
563 Real wx[2], wy[2], wz[2], wt[2];
564 const int i = ComputeWeights(x, wx);
565 const int j = ComputeWeights(y, wy);
566 const int k = ComputeWeights(z, wz);
567 const int l = ComputeWeights(t, wt);
569 RealType val = voxel_cast<RealType>(0);
570 Real fgw(0), wzt, wyzt, w;
573 for (
int d = 0; d <= 1; ++d) {
575 for (
int c = 0; c <= 1; ++c) {
578 for (
int b = 0; b <= 1; ++b) {
581 for (
int a = 0; a <= 1; ++a) {
584 if (input->IsForeground(ia, jb, kc, ld)) {
585 val += w * voxel_cast<RealType>(input->Get(ia, jb, kc, ld));
593 if (
ifloor(fgw * 1.e3) > 500) val /= fgw;
594 else val = voxel_cast<RealType>(this->DefaultValue());
596 return voxel_cast<VoxelType>(val);
600 template <
class TImage>
601 inline typename GenericLinearInterpolateImageFunction<TImage>::VoxelType
603 ::Get(
double x,
double y,
double z,
double t)
const 605 switch (this->NumberOfDimensions()) {
606 case 3:
return Get3D(x, y, z, t);
607 case 2:
return Get2D(x, y, z, t);
608 default:
return Get4D(x, y, z, t);
613 template <
class TImage>
614 inline typename GenericLinearInterpolateImageFunction<TImage>::VoxelType
618 switch (this->NumberOfDimensions()) {
619 case 3:
return GetWithPadding3D(x, y, z, t);
620 case 2:
return GetWithPadding2D(x, y, z, t);
621 default:
return GetWithPadding4D(x, y, z, t);
626 template <
class TImage>
template <
class TOtherImage>
627 inline typename TOtherImage::VoxelType
629 ::Get(
const TOtherImage *input,
double x,
double y,
double z,
double t)
const 631 switch (this->NumberOfDimensions()) {
632 case 3:
return Get3D(input, x, y, z, t);
633 case 2:
return Get2D(input, x, y, z, t);
634 default:
return Get4D(input, x, y, z, t);
639 template <
class TImage>
template <
class TOtherImage>
640 inline typename TOtherImage::VoxelType
644 switch (this->NumberOfDimensions()) {
645 case 3:
return GetWithPadding3D(input, x, y, z, t);
646 case 2:
return GetWithPadding2D(input, x, y, z, t);
647 default:
return GetWithPadding4D(input, x, y, z, t);
652 template <
class TImage>
653 inline typename GenericLinearInterpolateImageFunction<TImage>::VoxelType
658 const int i = ComputeWeights(x, wx);
659 const int j = ComputeWeights(y, wy);
663 auto img =
reinterpret_cast<const VoxelType *
>(this->Input()->GetDataPointer(i, j, k, l));
665 const auto v00 = voxel_cast<RealType>(img[_Offset[0]]);
666 const auto v01 = voxel_cast<RealType>(img[_Offset[1]]);
667 const auto v10 = voxel_cast<RealType>(img[_Offset[2]]);
668 const auto v11 = voxel_cast<RealType>(img[_Offset[3]]);
670 return voxel_cast<VoxelType>(wy[0] * (wx[0] * v00 + wx[1] * v01) +
671 wy[1] * (wx[0] * v10 + wx[1] * v11));
675 template <
class TImage>
676 inline typename GenericLinearInterpolateImageFunction<TImage>::VoxelType
680 Real wx[2], wy[2], wz[2];
681 const int i = ComputeWeights(x, wx);
682 const int j = ComputeWeights(y, wy);
683 const int k = ComputeWeights(z, wz);
686 auto img =
reinterpret_cast<const VoxelType *
>(this->Input()->GetDataPointer(i, j, k, l));
688 const auto v000 = voxel_cast<RealType>(img[_Offset[0]]);
689 const auto v001 = voxel_cast<RealType>(img[_Offset[1]]);
690 const auto v010 = voxel_cast<RealType>(img[_Offset[2]]);
691 const auto v011 = voxel_cast<RealType>(img[_Offset[3]]);
692 const auto v100 = voxel_cast<RealType>(img[_Offset[4]]);
693 const auto v101 = voxel_cast<RealType>(img[_Offset[5]]);
694 const auto v110 = voxel_cast<RealType>(img[_Offset[6]]);
695 const auto v111 = voxel_cast<RealType>(img[_Offset[7]]);
697 return voxel_cast<VoxelType>(wz[0] * (wy[0] * (wx[0] * v000 + wx[1] * v001) +
698 wy[1] * (wx[0] * v010 + wx[1] * v011)) +
699 wz[1] * (wy[0] * (wx[0] * v100 + wx[1] * v101) +
700 wy[1] * (wx[0] * v110 + wx[1] * v111)));
704 template <
class TImage>
705 inline typename GenericLinearInterpolateImageFunction<TImage>::VoxelType
709 Real wx[2], wy[2], wz[2], wt[2];
710 const int i = ComputeWeights(x, wx);
711 const int j = ComputeWeights(y, wy);
712 const int k = ComputeWeights(z, wz);
713 const int l = ComputeWeights(t, wt);
715 auto img =
reinterpret_cast<const VoxelType *
>(this->Input()->GetDataPointer(i, j, k, l));
717 const auto v0000 = voxel_cast<RealType>(img[_Offset[ 0]]);
718 const auto v0001 = voxel_cast<RealType>(img[_Offset[ 1]]);
719 const auto v0010 = voxel_cast<RealType>(img[_Offset[ 2]]);
720 const auto v0011 = voxel_cast<RealType>(img[_Offset[ 3]]);
721 const auto v0100 = voxel_cast<RealType>(img[_Offset[ 4]]);
722 const auto v0101 = voxel_cast<RealType>(img[_Offset[ 5]]);
723 const auto v0110 = voxel_cast<RealType>(img[_Offset[ 6]]);
724 const auto v0111 = voxel_cast<RealType>(img[_Offset[ 7]]);
725 const auto v1000 = voxel_cast<RealType>(img[_Offset[ 8]]);
726 const auto v1001 = voxel_cast<RealType>(img[_Offset[ 9]]);
727 const auto v1010 = voxel_cast<RealType>(img[_Offset[10]]);
728 const auto v1011 = voxel_cast<RealType>(img[_Offset[11]]);
729 const auto v1100 = voxel_cast<RealType>(img[_Offset[12]]);
730 const auto v1101 = voxel_cast<RealType>(img[_Offset[13]]);
731 const auto v1110 = voxel_cast<RealType>(img[_Offset[14]]);
732 const auto v1111 = voxel_cast<RealType>(img[_Offset[15]]);
734 return voxel_cast<VoxelType>(wt[0] * (wz[0] * (wy[0] * (wx[0] * v0000 + wx[1] * v0001) +
735 wy[1] * (wx[0] * v0010 + wx[1] * v0011)) +
736 wz[1] * (wy[0] * (wx[0] * v0100 + wx[1] * v0101) +
737 wy[1] * (wx[0] * v0110 + wx[1] * v0111))) +
738 wt[1] * (wz[0] * (wy[0] * (wx[0] * v1000 + wx[1] * v1001) +
739 wy[1] * (wx[0] * v1010 + wx[1] * v1011)) +
740 wz[1] * (wy[0] * (wx[0] * v1100 + wx[1] * v1101) +
741 wy[1] * (wx[0] * v1110 + wx[1] * v1111))));
745 template <
class TImage>
746 inline typename GenericLinearInterpolateImageFunction<TImage>::VoxelType
752 switch (this->NumberOfDimensions()) {
753 case 3:
return GetInside3D(x, y, z, t);
754 case 2:
return GetInside2D(x, y, z, t);
755 default:
return GetInside4D(x, y, z, t);
765 return Get(this->Input(), x, y, z, t);
769 template <
class TImage>
770 inline typename GenericLinearInterpolateImageFunction<TImage>::VoxelType
774 if (this->Extrapolator()) {
775 return Get(this->Extrapolator(), x, y, z, t);
777 return Get(x, y, z, t);
782 template <
class TImage>
783 inline typename GenericLinearInterpolateImageFunction<TImage>::VoxelType
787 return GetWithPadding(this->Input(), x, y, z, t);
791 template <
class TImage>
792 inline typename GenericLinearInterpolateImageFunction<TImage>::VoxelType
796 if (this->Extrapolator()) {
797 return GetWithPadding(this->Extrapolator(), x, y, z, t);
799 return GetWithPadding(x, y, z, t);
808 template <
class TImage>
812 Jacobian(jac, this->Input(), x, y, z, t);
816 template <
class TImage>
820 if (this->Extrapolator()) {
821 Jacobian(jac, this->Extrapolator(), x, y, z, t);
823 Jacobian(jac, x, y, z, t);
828 template <
class TImage>
832 JacobianWithPadding(jac, x, y, z, t);
836 template <
class TImage>
840 JacobianWithPadding(jac, x, y, z, t);
848 template <
class TImage>
852 const TImage *
const input = this->Input();
854 Real wx[2], wy[2], wd[2] = {Real(-1), Real(1)};
855 const int i = ComputeWeights(x, wx);
856 const int j = ComputeWeights(y, wy);
859 if (
IsNaN(t) &&
IsZero(input->TSize()) && input->N() == 1) {
863 if (i < 0 || i >= input->X() - 1 ||
864 j < 0 || j >= input->Y() - 1 ||
865 k < 0 || k >= input->Z()) {
871 for (
int b = 0; b <= 1; ++b) {
873 for (
int a = 0; a <= 1; ++a) {
875 w[0] = wd[a] * wy[b];
876 w[1] = wx[a] * wd[b];
877 for (
int l = 0; l < input->T(); ++l) {
878 dv = voxel_cast<Real>(input->Get(ia, jb, k, l));
879 jac(l, 0) += w[0] * dv;
880 jac(l, 1) += w[1] * dv;
890 if (i < 0 || i >= input->X() - 1 ||
891 j < 0 || j >= input->Y() - 1 ||
892 k < 0 || k >= input->Z() ||
893 l < 0 || l >= input->T()) {
898 RealType dx = voxel_cast<RealType>(0);
899 RealType dy = voxel_cast<RealType>(0);
902 for (
int b = 0; b <= 1; ++b) {
904 for (
int a = 0; a <= 1; ++a) {
906 dv = voxel_cast<RealType>(input->Get(ia, jb, k, l));
907 dx += (wd[a] * wy[b]) * dv;
908 dy += (wx[a] * wd[b]) * dv;
912 for (
int r = 0; r < input->N(); ++r) {
913 jac(r, 0) =
get(dx, r);
914 jac(r, 1) =
get(dy, r);
921 template <
class TImage>
925 const TImage *
const input = this->Input();
927 Real wx[2], wy[2], wz[2], wd[2] = {Real(-1), Real(1)};
928 const int i = ComputeWeights(x, wx);
929 const int j = ComputeWeights(y, wy);
930 const int k = ComputeWeights(z, wz);
932 if (
IsNaN(t) &&
IsZero(input->TSize()) && input->N() == 1) {
936 if (i < 0 || i >= input->X() - 1 ||
937 j < 0 || j >= input->Y() - 1 ||
938 k < 0 || k >= input->Z() - 1) {
944 for (
int c = 0; c <= 1; ++c) {
946 for (
int b = 0; b <= 1; ++b) {
948 for (
int a = 0; a <= 1; ++a) {
950 w[0] = wd[a] * wy[b] * wz[c];
951 w[1] = wx[a] * wd[b] * wz[c];
952 w[2] = wx[a] * wy[b] * wd[c];
953 for (
int l = 0; l < input->T(); ++l) {
954 dv = voxel_cast<Real>(input->Get(ia, jb, kc, l));
955 jac(l, 0) += w[0] * dv;
956 jac(l, 1) += w[1] * dv;
957 jac(l, 2) += w[2] * dv;
968 if (i < 0 || i >= input->X() - 1 ||
969 j < 0 || j >= input->Y() - 1 ||
970 k < 0 || k >= input->Z() - 1 ||
971 l < 0 || l >= input->T()) {
976 RealType dx = voxel_cast<RealType>(0);
977 RealType dy = voxel_cast<RealType>(0);
978 RealType dz = voxel_cast<RealType>(0);
981 for (
int c = 0; c <= 1; ++c) {
983 for (
int b = 0; b <= 1; ++b) {
985 for (
int a = 0; a <= 1; ++a) {
987 dv = voxel_cast<RealType>(input->Get(ia, jb, kc, l));
988 dx += (wd[a] * wy[b] * wz[c]) * dv;
989 dy += (wx[a] * wd[b] * wz[c]) * dv;
990 dz += (wx[a] * wy[b] * wd[c]) * dv;
995 for (
int r = 0; r < input->N(); ++r) {
996 jac(r, 0) =
get(dx, r);
997 jac(r, 1) =
get(dy, r);
998 jac(r, 2) =
get(dz, r);
1005 template <
class TImage>
1009 const TImage *
const input = this->Input();
1013 Real wx[2], wy[2], wz[2], wt[2], wd[2] = {Real(-1), Real(1)};
1014 const int i = ComputeWeights(x, wx);
1015 const int j = ComputeWeights(y, wy);
1016 const int k = ComputeWeights(z, wz);
1017 const int l = ComputeWeights(
IsNaN(t) ? 0. : t, wt);
1019 if (i < 0 || i >= input->X() - 1 ||
1020 j < 0 || j >= input->Y() - 1 ||
1021 k < 0 || k >= input->Z() - 1 ||
1022 l < 0 || l >= input->T() - 1) {
1027 RealType dx = voxel_cast<RealType>(0);
1028 RealType dy = voxel_cast<RealType>(0);
1029 RealType dz = voxel_cast<RealType>(0);
1030 RealType dt = voxel_cast<RealType>(0);
1033 for (
int d = 0; d <= 1; ++d) {
1035 for (
int c = 0; c <= 1; ++c) {
1037 for (
int b = 0; b <= 1; ++b) {
1039 for (
int a = 0; a <= 1; ++a) {
1041 dv = voxel_cast<RealType>(input->Get(ia, jb, kc, ld));
1042 dx += (wd[a] * wy[b] * wz[c] * wt[d]) * dv;
1043 dy += (wx[a] * wd[b] * wz[c] * wt[d]) * dv;
1044 dz += (wx[a] * wy[b] * wd[c] * wt[d]) * dv;
1045 dt += (wx[a] * wy[b] * wz[c] * wd[d]) * dv;
1051 for (
int r = 0; r < input->N(); ++r) {
1052 jac(r, 0) =
get(dx, r);
1053 jac(r, 1) =
get(dy, r);
1054 jac(r, 2) =
get(dz, r);
1055 jac(r, 3) =
get(dt, r);
1060 template <
class TImage>
1064 switch (this->NumberOfDimensions()) {
1065 case 3:
return Jacobian3D(jac, x, y, z, t);
1066 case 2:
return Jacobian2D(jac, x, y, z, t);
1067 default:
return Jacobian4D(jac, x, y, z, t);
1077 template <
class TImage>
1081 const TImage *
const input = this->Input();
1083 Real wx[2], wy[2], wd[2] = {Real(-1), Real(1)};
1084 const int i = ComputeWeights(x, wx);
1085 const int j = ComputeWeights(y, wy);
1088 if (
IsNaN(t) &&
IsZero(input->TSize()) && input->N() == 1) {
1092 if (i < 0 || i >= input->X() - 1 ||
1093 j < 0 || j >= input->Y() - 1 ||
1094 k < 0 || k >= input->Z()) {
1100 for (
int b = 0; b <= 1; ++b) {
1102 for (
int a = 0; a <= 1; ++a) {
1104 if (!input->IsForeground(ia, jb, k)) {
1108 w[0] = wd[a] * wy[b];
1109 w[1] = wx[a] * wd[b];
1110 for (
int l = 0; l < input->T(); ++l) {
1111 dv = voxel_cast<Real>(input->Get(ia, jb, k, l));
1112 jac(l, 0) += w[0] * dv;
1113 jac(l, 1) += w[1] * dv;
1123 if (i < 0 || i >= input->X() - 1 ||
1124 j < 0 || j >= input->Y() - 1 ||
1125 k < 0 || k >= input->Z() ||
1126 l < 0 || l >= input->T()) {
1131 RealType dx = voxel_cast<RealType>(0);
1132 RealType dy = voxel_cast<RealType>(0);
1135 for (
int b = 0; b <= 1; ++b) {
1137 for (
int a = 0; a <= 1; ++a) {
1139 if (!input->IsForeground(ia, jb, k, l)) {
1142 dv = voxel_cast<RealType>(input->Get(ia, jb, k, l));
1143 dx += (wd[a] * wy[b]) * dv;
1144 dy += (wx[a] * wd[b]) * dv;
1148 for (
int r = 0; r < input->N(); ++r) {
1149 jac(r, 0) =
get(dx, r);
1150 jac(r, 1) =
get(dy, r);
1157 template <
class TImage>
1161 const TImage *
const input = this->Input();
1163 Real wx[2], wy[2], wz[2], wd[2] = {Real(-1), Real(1)};
1164 const int i = ComputeWeights(x, wx);
1165 const int j = ComputeWeights(y, wy);
1166 const int k = ComputeWeights(z, wz);
1168 if (
IsNaN(t) &&
IsZero(input->TSize()) && input->N() == 1) {
1172 if (i < 0 || i >= input->X() - 1 ||
1173 j < 0 || j >= input->Y() - 1 ||
1174 k < 0 || k >= input->Z() - 1) {
1180 for (
int c = 0; c <= 1; ++c) {
1182 for (
int b = 0; b <= 1; ++b) {
1184 for (
int a = 0; a <= 1; ++a) {
1186 if (!input->IsForeground(ia, jb, kc)) {
1190 w[0] = wd[a] * wy[b] * wz[c];
1191 w[1] = wx[a] * wd[b] * wz[c];
1192 w[2] = wx[a] * wy[b] * wd[c];
1193 for (
int l = 0; l < input->T(); ++l) {
1194 dv = voxel_cast<Real>(input->Get(ia, jb, kc, l));
1195 jac(l, 0) += w[0] * dv;
1196 jac(l, 1) += w[1] * dv;
1197 jac(l, 2) += w[2] * dv;
1208 if (i < 0 || i >= input->X() - 1 ||
1209 j < 0 || j >= input->Y() - 1 ||
1210 k < 0 || k >= input->Z() - 1 ||
1211 l < 0 || l >= input->T()) {
1216 RealType dx = voxel_cast<RealType>(0);
1217 RealType dy = voxel_cast<RealType>(0);
1218 RealType dz = voxel_cast<RealType>(0);
1221 for (
int c = 0; c <= 1; ++c) {
1223 for (
int b = 0; b <= 1; ++b) {
1225 for (
int a = 0; a <= 1; ++a) {
1227 if (!input->IsForeground(ia, jb, kc, l)) {
1230 dv = voxel_cast<RealType>(input->Get(ia, jb, kc, l));
1231 dx += (wd[a] * wy[b] * wz[c]) * dv;
1232 dy += (wx[a] * wd[b] * wz[c]) * dv;
1233 dz += (wx[a] * wy[b] * wd[c]) * dv;
1238 for (
int r = 0; r < input->N(); ++r) {
1239 jac(r, 0) =
get(dx, r);
1240 jac(r, 1) =
get(dy, r);
1241 jac(r, 2) =
get(dz, r);
1248 template <
class TImage>
1252 const TImage *
const input = this->Input();
1256 Real wx[2], wy[2], wz[2], wt[2], wd[2] = {Real(-1), Real(1)};
1257 const int i = ComputeWeights(x, wx);
1258 const int j = ComputeWeights(y, wy);
1259 const int k = ComputeWeights(z, wz);
1260 const int l = ComputeWeights(
IsNaN(t) ? 0. : t, wt);
1262 if (i < 0 || i >= input->X() - 1 ||
1263 j < 0 || j >= input->Y() - 1 ||
1264 k < 0 || k >= input->Z() - 1 ||
1265 l < 0 || l >= input->T() - 1) {
1270 RealType dx = voxel_cast<RealType>(0);
1271 RealType dy = voxel_cast<RealType>(0);
1272 RealType dz = voxel_cast<RealType>(0);
1273 RealType dt = voxel_cast<RealType>(0);
1276 for (
int d = 0; d <= 1; ++d) {
1278 for (
int c = 0; c <= 1; ++c) {
1280 for (
int b = 0; b <= 1; ++b) {
1282 for (
int a = 0; a <= 1; ++a) {
1284 if (!input->IsForeground(ia, jb, kc, ld)) {
1287 dv = voxel_cast<RealType>(input->Get(ia, jb, kc, ld));
1288 dx += (wd[a] * wy[b] * wz[c] * wt[d]) * dv;
1289 dy += (wx[a] * wd[b] * wz[c] * wt[d]) * dv;
1290 dz += (wx[a] * wy[b] * wd[c] * wt[d]) * dv;
1291 dt += (wx[a] * wy[b] * wz[c] * wd[d]) * dv;
1297 for (
int r = 0; r < input->N(); ++r) {
1298 jac(r, 0) =
get(dx, r);
1299 jac(r, 1) =
get(dy, r);
1300 jac(r, 2) =
get(dz, r);
1301 jac(r, 3) =
get(dt, r);
1306 template <
class TImage>
1310 switch (this->NumberOfDimensions()) {
1311 case 3:
return JacobianWithPadding3D(jac, x, y, z, t);
1312 case 2:
return JacobianWithPadding2D(jac, x, y, z, t);
1313 default:
return JacobianWithPadding4D(jac, x, y, z, t);
1323 template <
class TImage>
template <
class TOtherImage>
1327 Real wx[2], wy[2], wd[2] = {Real(-1), Real(1)};
1328 const int i = ComputeWeights(x, wx);
1329 const int j = ComputeWeights(y, wy);
1332 if (
IsNaN(t) &&
IsZero(input->TSize()) && input->N() == 1) {
1336 if (k < 0 || k >= input->Z()) {
1342 for (
int b = 0; b <= 1; ++b) {
1344 for (
int a = 0; a <= 1; ++a) {
1346 w[0] = wd[a] * wy[b];
1347 w[1] = wx[a] * wd[b];
1348 for (
int l = 0; l < input->T(); ++l) {
1349 dv = voxel_cast<Real>(input->Get(ia, jb, k, l));
1350 jac(l, 0) += w[0] * dv;
1351 jac(l, 1) += w[1] * dv;
1361 if (k < 0 || k >= input->Z() ||
1362 l < 0 || l >= input->T()) {
1367 RealType dx = voxel_cast<RealType>(0);
1368 RealType dy = voxel_cast<RealType>(0);
1371 for (
int b = 0; b <= 1; ++b) {
1373 for (
int a = 0; a <= 1; ++a) {
1375 dv = voxel_cast<RealType>(input->Get(ia, jb, k, l));
1376 dx += (wd[a] * wy[b]) * dv;
1377 dy += (wx[a] * wd[b]) * dv;
1381 for (
int r = 0; r < input->N(); ++r) {
1382 jac(r, 0) =
get(dx, r);
1383 jac(r, 1) =
get(dy, r);
1390 template <
class TImage>
template <
class TOtherImage>
1393 double x,
double y,
double z,
double t)
const 1395 Real wx[2], wy[2], wz[2], wd[2] = {Real(-1), Real(1)};
1396 const int i = ComputeWeights(x, wx);
1397 const int j = ComputeWeights(y, wy);
1398 const int k = ComputeWeights(z, wz);
1400 if (
IsNaN(t) &&
IsZero(input->TSize()) && input->N() == 1) {
1406 for (
int c = 0; c <= 1; ++c) {
1408 for (
int b = 0; b <= 1; ++b) {
1410 for (
int a = 0; a <= 1; ++a) {
1412 w[0] = wd[a] * wy[b] * wz[c];
1413 w[1] = wx[a] * wd[b] * wz[c];
1414 w[2] = wx[a] * wy[b] * wd[c];
1415 for (
int l = 0; l < input->T(); ++l) {
1416 dv = voxel_cast<Real>(input->Get(ia, jb, kc, l));
1417 jac(l, 0) += w[0] * dv;
1418 jac(l, 1) += w[1] * dv;
1419 jac(l, 2) += w[2] * dv;
1430 if (l < 0 || l >= input->T()) {
1435 RealType dx = voxel_cast<RealType>(0);
1436 RealType dy = voxel_cast<RealType>(0);
1437 RealType dz = voxel_cast<RealType>(0);
1440 for (
int c = 0; c <= 1; ++c) {
1442 for (
int b = 0; b <= 1; ++b) {
1444 for (
int a = 0; a <= 1; ++a) {
1446 dv = voxel_cast<RealType>(input->Get(ia, jb, kc, l));
1447 dx += (wd[a] * wy[b] * wz[c]) * dv;
1448 dy += (wx[a] * wd[b] * wz[c]) * dv;
1449 dz += (wx[a] * wy[b] * wd[c]) * dv;
1454 for (
int r = 0; r < input->N(); ++r) {
1455 jac(r, 0) =
get(dx, r);
1456 jac(r, 1) =
get(dy, r);
1457 jac(r, 2) =
get(dz, r);
1464 template <
class TImage>
template <
class TOtherImage>
1467 double x,
double y,
double z,
double t)
const 1471 Real wx[2], wy[2], wz[2], wt[2], wd[2] = {Real(-1), Real(1)};
1472 const int i = ComputeWeights(x, wx);
1473 const int j = ComputeWeights(y, wy);
1474 const int k = ComputeWeights(z, wz);
1475 const int l = ComputeWeights(
IsNaN(t) ? 0. : t, wt);
1478 RealType dx = voxel_cast<RealType>(0);
1479 RealType dy = voxel_cast<RealType>(0);
1480 RealType dz = voxel_cast<RealType>(0);
1481 RealType dt = voxel_cast<RealType>(0);
1484 for (
int d = 0; d <= 1; ++d) {
1486 for (
int c = 0; c <= 1; ++c) {
1488 for (
int b = 0; b <= 1; ++b) {
1490 for (
int a = 0; a <= 1; ++a) {
1492 dv = voxel_cast<RealType>(input->Get(ia, jb, kc, ld));
1493 dx += (wd[a] * wy[b] * wz[c] * wt[d]) * dv;
1494 dy += (wx[a] * wd[b] * wz[c] * wt[d]) * dv;
1495 dz += (wx[a] * wy[b] * wd[c] * wt[d]) * dv;
1496 dt += (wx[a] * wy[b] * wz[c] * wd[d]) * dv;
1502 for (
int r = 0; r < input->N(); ++r) {
1503 jac(r, 0) =
get(dx, r);
1504 jac(r, 1) =
get(dy, r);
1505 jac(r, 2) =
get(dz, r);
1506 jac(r, 3) =
get(dt, r);
1511 template <
class TImage>
template <
class TOtherImage>
1514 double x,
double y,
double z,
double t)
const 1516 switch (this->NumberOfDimensions()) {
1517 case 3:
return Jacobian3D(jac, input, x, y, z, t);
1518 case 2:
return Jacobian2D(jac, input, x, y, z, t);
1519 default:
return Jacobian4D(jac, input, x, y, z, t);
1526 #endif // MIRTK_LinearInterpolateImageFunction_HXX static int ComputeWeights(double, Real[2])
VoxelType GetWithPadding4D(double, double, double=0, double=0) const
VoxelType Get(double, double, double=0, double=0) const
void JacobianWithPadding3D(Matrix &, double, double, double=0., double=NaN) const
void Jacobian4D(Matrix &, double, double, double=0., double=NaN) const
MIRTKCU_API bool IsZero(double a, double tol=1e-12)
Determine equality of a floating point number with zero.
string Get(const ParameterList ¶ms, string name)
Get parameter value from parameters list.
virtual void EvaluateJacobianWithPaddingInside(Matrix &, double, double, double=0, double=NaN) const
VoxelType Get3D(double, double, double=0, double=0) const
virtual VoxelType GetInside(double, double, double=0, double=0) const
virtual void Initialize()
MIRTKCU_API bool IsNaN(double x)
Check if floating point value is not a number (NaN)
MIRTKCU_API int ifloor(T x)
Round floating-point value to next smaller integer and cast to int.
virtual void EvaluateJacobianInside(Matrix &, double, double, double=0, double=NaN) const
MIRTKCU_API double fdec(double f)
virtual ~GenericLinearInterpolateImageFunction()
Destructor.
void Initialize(int, int=-1, double *=NULL)
Initialize matrix with number of rows and columns.
virtual void EvaluateJacobianOutside(Matrix &, double, double, double=0, double=NaN) const
virtual VoxelType GetInside3D(double, double, double=0, double=0) const
Evaluate generic 3D image without handling boundary conditions.
virtual VoxelType GetWithPaddingOutside(double, double, double=0, double=0) const
virtual void BoundingInterval(double, int &, int &) const
void Jacobian(Matrix &, double, double, double=0., double=NaN) const
Get 1st order derivatives of given image at arbitrary location (in pixels)
VoxelType Get4D(double, double, double=0, double=0) const
virtual VoxelType GetInside2D(double, double, double=0, double=0) const
Evaluate generic 2D image without handling boundary conditions.
void Jacobian3D(Matrix &, double, double, double=0., double=NaN) const
VoxelType Get2D(double, double, double=0, double=0) const
VoxelType GetWithPadding3D(double, double, double=0, double=0) const
virtual VoxelType GetWithPaddingInside(double, double, double=0, double=0) const
void JacobianWithPadding4D(Matrix &, double, double, double=0., double=NaN) const
void Jacobian2D(Matrix &, double, double, double=0., double=NaN) const
GenericLinearInterpolateImageFunction()
Default constructor.
virtual VoxelType GetWithPadding(double, double, double=0, double=0) const
MIRTKCU_API int iround(T x)
Round floating-point value and cast to int.
virtual void EvaluateJacobianWithPaddingOutside(Matrix &, double, double, double=0, double=NaN) const
virtual VoxelType GetInside4D(double, double, double=0, double=0) const
Evaluate generic 4D image without handling boundary conditions.
void JacobianWithPadding(Matrix &, double, double, double=0, double=NaN) const
Get 1st order derivatives of given image at arbitrary location (in pixels)
virtual VoxelType GetOutside(double, double, double=0, double=0) const
Evaluate generic image at an arbitrary location (in pixels)
VoxelType GetWithPadding2D(double, double, double=0, double=0) const
void JacobianWithPadding2D(Matrix &, double, double, double=0., double=NaN) const