17#ifndef __interp_cubic_h__
18#define __interp_cubic_h__
71 template <
class ImageType,
class SplineType, Math::SplineProcessingType PType>
75 using typename Base<ImageType>::value_type;
79 H { SplineType(PType), SplineType(PType), SplineType(PType) } { }
85 ssize_t
clamp (ssize_t x, ssize_t dim)
const {
87 if (x >= dim)
return (dim-1);
93 template <
class ImageType,
class SplineType, Math::SplineProcessingType PType>
103 template <
class ImageType,
class SplineType>
105 public SplineInterpBase <ImageType, SplineType, Math::SplineProcessingType::Value>
113 using SplineBase::clamp;
115 SplineInterp (
const ImageType& parent, value_type value_when_out_of_bounds = SplineBase::default_out_of_bounds_value()) :
121 template <
class VectorType>
122 bool voxel (
const VectorType& pos) {
127 for(
size_t i = 0; i < 3; ++i)
132 for (ssize_t z = 0; z < 4; ++z) {
133 for (ssize_t y = 0; y < 4; ++y) {
134 value_type partial_weight =
H[1].weights[y] *
H[2].weights[z];
135 for (ssize_t x = 0; x < 4; ++x)
136 weights_vec[i++] =
H[0].weights[x] * partial_weight;
145 template <
class VectorType>
152 template <
class VectorType>
159 value_type
value () {
165 Eigen::Matrix<value_type, 64, 1> coeff_vec;
168 for (ssize_t z = 0; z < 4; ++z) {
170 for (ssize_t y = 0; y < 4; ++y) {
172 for (ssize_t x = 0; x < 4; ++x) {
179 return coeff_vec.dot (weights_vec);
184 Eigen::Matrix<value_type, Eigen::Dynamic, 1> row (
size_t axis) {
186 Eigen::Matrix<value_type, Eigen::Dynamic, 1> out_of_bounds_row (ImageType::size(
axis));
187 out_of_bounds_row.setOnes();
189 return out_of_bounds_row;
194 Eigen::Matrix<value_type, Eigen::Dynamic, 64> coeff_matrix ( ImageType::size(3), 64 );
197 for (ssize_t z = 0; z < 4; ++z) {
199 for (ssize_t y = 0; y < 4; ++y) {
201 for (ssize_t x = 0; x < 4; ++x) {
203 coeff_matrix.col (i++) = ImageType::row (
axis);
208 return coeff_matrix * weights_vec;
218 template <
class ImageType,
class SplineType>
220 public SplineInterpBase <ImageType, SplineType, Math::SplineProcessingType::Derivative>
228 using SplineBase::clamp;
230 SplineInterp (
const ImageType& parent, value_type value_when_out_of_bounds = SplineBase::default_out_of_bounds_value()) :
232 out_of_bounds_vec (value_when_out_of_bounds, value_when_out_of_bounds, value_when_out_of_bounds),
235 if (ImageType::ndim() == 4) {
236 out_of_bounds_matrix.resize(ImageType::size(3), 3);
238 out_of_bounds_matrix.resize(1, 3);
240 out_of_bounds_matrix.fill(value_when_out_of_bounds);
245 template <
class VectorType>
246 bool voxel (
const VectorType& pos) {
251 for(
size_t i =0; i <3; ++i)
256 for (ssize_t z = 0; z < 4; ++z) {
257 for (ssize_t y = 0; y < 4; ++y) {
258 value_type partial_weight =
H[1].weights[y] *
H[2].weights[z];
259 value_type partial_weight_dy =
H[1].deriv_weights[y] *
H[2].weights[z];
260 value_type partial_weight_dz =
H[1].weights[y] *
H[2].deriv_weights[z];
262 for (ssize_t x = 0; x < 4; ++x) {
263 weights_matrix(i,0) =
H[0].deriv_weights[x] * partial_weight;
264 weights_matrix(i,1) =
H[0].weights[x] * partial_weight_dy;
265 weights_matrix(i,2) =
H[0].weights[x] * partial_weight_dz;
277 template <
class VectorType>
283 template <
class VectorType>
289 Eigen::Matrix<value_type, 1, 3> gradient () {
291 return out_of_bounds_vec;
295 Eigen::Matrix<value_type, 1, 64> coeff_vec;
298 for (ssize_t z = 0; z < 4; ++z) {
300 for (ssize_t y = 0; y < 4; ++y) {
302 for (ssize_t x = 0; x < 4; ++x) {
309 return coeff_vec * weights_matrix;
314 Eigen::Matrix<default_type, Eigen::Dynamic, Eigen::Dynamic> gradient_wrt_scanner() {
315 return gradient().template cast<default_type>() * wrt_scanner_transform;
319 Eigen::Matrix<value_type, Eigen::Dynamic, 3> gradient_row() {
321 return out_of_bounds_matrix;
324 assert (ImageType::ndim() == 4);
328 Eigen::Matrix<value_type, Eigen::Dynamic, 64> coeff_matrix (ImageType::size(3), 64);
331 for (ssize_t z = 0; z < 4; ++z) {
333 for (ssize_t y = 0; y < 4; ++y) {
335 for (ssize_t x = 0; x < 4; ++x) {
337 coeff_matrix.col (i++) = ImageType::row (3);
342 return coeff_matrix * weights_matrix;
347 Eigen::Matrix<default_type, Eigen::Dynamic, 3> gradient_row_wrt_scanner() {
348 return gradient_row().template cast<default_type>() * wrt_scanner_transform;
358 Eigen::Matrix<value_type, Eigen::Dynamic, 1> row() { }
359 value_type
value () { }
364 template <
class ImageType,
class SplineType>
366 public SplineInterpBase <ImageType, SplineType, Math::SplineProcessingType::ValueAndDerivative>
374 using SplineBase::clamp;
376 SplineInterp (
const ImageType& parent, value_type value_when_out_of_bounds = SplineBase::default_out_of_bounds_value()) :
380 if (ImageType::ndim() == 4) {
381 out_of_bounds_vec.resize(ImageType::size(3), 1);
382 out_of_bounds_matrix.resize(ImageType::size(3), 3);
384 out_of_bounds_vec.resize(1, 1);
385 out_of_bounds_matrix.resize(1, 3);
387 out_of_bounds_vec.fill(value_when_out_of_bounds);
388 out_of_bounds_matrix.fill(value_when_out_of_bounds);
393 template <
class VectorType>
399 template <
class VectorType>
406 template <
class VectorType>
407 bool voxel (
const VectorType& pos) {
412 for (
size_t i = 0; i < 3; ++i)
417 for (ssize_t z = 0; z < 4; ++z) {
418 for (ssize_t y = 0; y < 4; ++y) {
419 value_type partial_weight =
H[1].weights[y] *
H[2].weights[z];
420 value_type partial_weight_dy =
H[1].deriv_weights[y] *
H[2].weights[z];
421 value_type partial_weight_dz =
H[1].weights[y] *
H[2].deriv_weights[z];
423 for (ssize_t x = 0; x < 4; ++x) {
425 weights_matrix(i,0) =
H[0].deriv_weights[x] * partial_weight;
426 weights_matrix(i,1) =
H[0].weights[x] * partial_weight_dy;
427 weights_matrix(i,2) =
H[0].weights[x] * partial_weight_dz;
429 weights_matrix(i,3) =
H[0].weights[x] * partial_weight;
438 void value_and_gradient (value_type&
value, Eigen::Matrix<value_type, 1, 3>& gradient) {
440 value = out_of_bounds_vec(0);
441 gradient = out_of_bounds_matrix.row(0);
447 Eigen::Matrix<value_type, 1, 64> coeff_vec;
450 for (ssize_t z = 0; z < 4; ++z) {
452 for (ssize_t y = 0; y < 4; ++y) {
454 for (ssize_t x = 0; x < 4; ++x) {
460 Eigen::Matrix<value_type, 1, 4> grad_and_value (coeff_vec * weights_matrix);
462 gradient = grad_and_value.head(3);
463 value = grad_and_value[3];
466 void value_and_gradient_wrt_scanner (value_type&
value, Eigen::Matrix<value_type, 1, 3>& gradient) {
467 value_and_gradient(
value, gradient);
470 gradient = (gradient.template cast<default_type>() * wrt_scanner_transform).
eval();
474 void value_and_gradient_row (Eigen::Matrix<value_type, Eigen::Dynamic, 1>&
value, Eigen::Matrix<value_type, Eigen::Dynamic, 3>& gradient) {
476 value = out_of_bounds_vec;
477 gradient = out_of_bounds_matrix;
481 assert (ImageType::ndim() == 4);
485 Eigen::Matrix<value_type, Eigen::Dynamic, 64> coeff_matrix (ImageType::size(3), 64);
488 for (ssize_t z = 0; z < 4; ++z) {
490 for (ssize_t y = 0; y < 4; ++y) {
492 for (ssize_t x = 0; x < 4; ++x) {
494 coeff_matrix.col (i++) = ImageType::row (3);
498 Eigen::Matrix<value_type, Eigen::Dynamic, 4> grad_and_value (coeff_matrix * weights_matrix);
499 gradient = grad_and_value.block(0,0,ImageType::size(3),3);
500 value = grad_and_value.col(3);
503 void value_and_gradient_row_wrt_scanner (Eigen::Matrix<value_type, Eigen::Dynamic, 1>&
value, Eigen::Matrix<value_type, Eigen::Dynamic, 3>& gradient) {
504 value_and_gradient_row(
value, gradient);
508 gradient = (gradient.template cast<default_type>() * wrt_scanner_transform).
eval();
521 template <
typename ImageType>
524 template <
typename ImageType>
528 template <
class ImageType,
typename... Args>
This class defines the interface for classes that perform image interpolation.
Eigen::Vector3d intravoxel_offset(const VectorType &pos)
Eigen::Matrix< value_type, 64, 4 > weights_matrix
Eigen::Matrix< value_type, Eigen::Dynamic, 1 > out_of_bounds_vec
Eigen::Matrix< value_type, Eigen::Dynamic, 3 > out_of_bounds_matrix
const Eigen::Matrix< default_type, 3, 3 > wrt_scanner_transform
Eigen::Matrix< value_type, 64, 3 > weights_matrix
const Eigen::Matrix< default_type, 3, 3 > wrt_scanner_transform
Eigen::Matrix< value_type, Eigen::Dynamic, 3 > out_of_bounds_matrix
const Eigen::Matrix< value_type, 1, 3 > out_of_bounds_vec
Eigen::Matrix< value_type, 64, 1 > weights_vec
This class provides access to the voxel intensities of an image using cubic spline interpolation.
ssize_t clamp(ssize_t x, ssize_t dim) const
constexpr I floor(const T x)
template function with cast to different type
VectorType::Scalar value(const VectorType &coefs, typename VectorType::Scalar cos_elevation, typename VectorType::Scalar cos_azimuth, typename VectorType::Scalar sin_azimuth, int lmax)
Cubic< ImageType > make_cubic(const ImageType &parent, Args &&... args)
T eval(const double *coef, const int order, const T lower, const T upper, const T x)
MR::default_type value_type
void set(HeaderType &header, const List &stride)
set the strides of header from a vector<ssize_t>