17#ifndef __registration_metric_difference_robust_h__
18#define __registration_metric_difference_robust_h__
26 namespace Registration
30 template<
class Estimator = L2>
36 template <
class Params>
38 const Eigen::Vector3d im1_point,
39 const Eigen::Vector3d im2_point,
40 const Eigen::Vector3d midway_point,
41 Eigen::Matrix<default_type, Eigen::Dynamic, 1>& gradient) {
43 assert (!this->
weighted &&
"FIXME: set_weights not implemented for 3D metric");
45 typename Params::Im1ValueType im1_value;
46 typename Params::Im2ValueType im2_value;
47 Eigen::Matrix<typename Params::Im1ValueType, 1, 3> im1_grad;
48 Eigen::Matrix<typename Params::Im2ValueType, 1, 3> im2_grad;
50 params.im1_image_interp->value_and_gradient_wrt_scanner (im1_value, im1_grad);
53 params.im2_image_interp->value_and_gradient_wrt_scanner (im2_value, im2_grad);
59 const auto jacobian_vec = params.transformation.get_jacobian_vector_wrt_params (midway_point);
60 const Eigen::Vector3d g = grad * (im1_grad + im2_grad);
61 gradient.segment<4>(0) += g(0) * jacobian_vec;
62 gradient.segment<4>(4) += g(1) * jacobian_vec;
63 gradient.segment<4>(8) += g(2) * jacobian_vec;
71 template<
class Im1Type,
class Im2Type,
class Estimator = L2>
78 im1_grad.resize(volumes, 3);
79 im2_grad.resize(volumes, 3);
80 im1_values.resize(volumes, 1);
81 im2_values.resize(volumes, 1);
82 diff_values.resize(volumes, 1);
88 using requires_initialisation = int;
90 void init (
const Im1Type& im1,
const Im2Type& im2) {
91 assert (im1.ndim() == 4);
92 assert (im2.ndim() == 4);
93 assert(im1.size(3) == im2.size(3));
94 if (volumes != im1.size(3)) {
95 volumes = im1.size(3);
96 im1_grad.resize(volumes, 3);
97 im2_grad.resize(volumes, 3);
98 im1_values.resize(volumes, 1);
99 im2_values.resize(volumes, 1);
100 diff_values.resize(volumes, 1);
104 template <
class Params>
106 const Eigen::Vector3d& im1_point,
107 const Eigen::Vector3d& im2_point,
108 const Eigen::Vector3d& midway_point,
109 Eigen::Matrix<default_type, Eigen::Dynamic, 1>& gradient) {
111 params.im1_image_interp->value_and_gradient_row_wrt_scanner (im1_values, im1_grad);
112 if (im1_values.hasNaN())
115 params.im2_image_interp->value_and_gradient_row_wrt_scanner (im2_values, im2_grad);
116 if (im2_values.hasNaN())
119 assert (volumes == im1_grad.rows() &&
"metric.init not called after image has been cropped?");
120 assert (volumes == im2_grad.rows() &&
"metric.init not called after image has been cropped?");
122 const Eigen::Matrix<default_type, 4, 1> jacobian_vec (params.transformation.get_jacobian_vector_wrt_params (midway_point));
123 diff_values = im1_values - im2_values;
126 diff_values.array() *= this->
mc_weights.array();
128 estimator (diff_values.template cast<default_type>(), residuals, grads);
130 Eigen::Matrix<default_type, 1, 3> g;
131 for (ssize_t i = 0; i < volumes; ++i) {
132 g = grads[i] * (im1_grad.row(i) + im2_grad.row(i));
133 gradient.segment<4>(0) += g(0) * jacobian_vec;
134 gradient.segment<4>(4) += g(1) * jacobian_vec;
135 gradient.segment<4>(8) += g(2) * jacobian_vec;
144 Eigen::Matrix<default_type, Eigen::Dynamic, 1> residuals, grads;
145 Eigen::Matrix<typename Im1Type::value_type, Eigen::Dynamic, 3> im1_grad;
146 Eigen::Matrix<typename Im2Type::value_type, Eigen::Dynamic, 3> im2_grad;
147 Eigen::Matrix<typename Im1Type::value_type, Eigen::Dynamic, 1> im1_values, diff_values;
148 Eigen::Matrix<typename Im2Type::value_type, Eigen::Dynamic, 1> im2_values;
Eigen::VectorXd mc_weights
double default_type
the default type used throughout MRtrix