17#ifndef __registration_metric_params_h__
18#define __registration_metric_params_h__
28 namespace Registration
33 template <
class TransformType,
36 class MidwayImageType,
39 class Im1ImageInterpType,
40 class Im2ImageInterpType,
41 class Im1MaskInterpolatorType,
42 class Im2MaskInterpolatorType,
43 class ProcImageType = Image<default_type>,
44 class ProcImageInterpolatorType = Interp::Linear<Image<default_type>>,
45 class ProcMaskType = Image<bool>,
46 class ProcessedMaskInterpolatorType = Interp::Nearest<Image<bool>>>
48 MEMALIGN (
Params<TransformType,Im1ImageType,Im2ImageType,MidwayImageType,
49 Im1MaskType,Im2MaskType,Im1ImageInterpType,Im2ImageInterpType,
50 Im1MaskInterpolatorType,Im2MaskInterpolatorType,ProcImageType,ProcImageInterpolatorType,
51 ProcMaskType,ProcessedMaskInterpolatorType>)
54 using TransformParamType =
typename TransformType::ParameterType;
57 using Im1InterpType = Im1ImageInterpType;
58 using Im2InterpType = Im2ImageInterpType;
59 using Mask1InterpolatorType = Im1MaskInterpolatorType;
60 using Mask2InterpolatorType = Im2MaskInterpolatorType;
62 using ProcessedImageType = ProcImageType;
63 using ProcessedMaskType = ProcMaskType;
64 using ProcessedImageInterpType = ProcImageInterpolatorType;
65 using ProcessedMaskInterpType = ProcessedMaskInterpolatorType;
67 Params (TransformType& transform,
68 Im1ImageType& im1_image,
69 Im2ImageType& im2_image,
70 MidwayImageType& midway_image,
71 Im1MaskType& im1_mask,
72 Im2MaskType& im2_mask) :
73 transformation (transform),
74 im1_image (im1_image),
75 im2_image (im2_image),
76 midway_image (midway_image),
80 control_point_exent (10.0, 10.0, 10.0),
81 robust_estimate_subset (
false),
82 robust_estimate_use_score (
false) {
83 im1_image_interp.reset (
new Im1ImageInterpType (im1_image));
84 im2_image_interp.reset (
new Im2ImageInterpType (im2_image));
86 im1_mask_interp.reset (
new Im1MaskInterpolatorType (im1_mask));
88 im2_mask_interp.reset (
new Im2MaskInterpolatorType (im2_mask));
89 update_control_points();
92 void set_extent (
vector<size_t> extent_vector) { extent=std::move(extent_vector); }
95 mc_settings = mc_vector;
99 for (
const auto& mc : mc_settings)
103 mc_weights = Eigen::Matrix<default_type, Eigen::Dynamic, 1>();
107 mc_weights.resize (nvols);
108 for (
const auto& mc : mc_settings) {
109 mc_weights.segment(mc.start,mc.nvols).fill(mc.weight);
112 if ((mc_weights.array() == 1.0).all())
113 mc_weights = Eigen::Matrix<default_type, Eigen::Dynamic, 1>();
116 Eigen::VectorXd get_weights ()
const {
120 template <
class VectorType>
121 void set_control_points_extent(
const VectorType& extent) {
122 control_point_exent = extent;
123 update_control_points();
126 void set_im1_iterpolator (Im1ImageType& im1_image) {
127 im1_image_interp.reset (
new Im1ImageInterpType (im1_image));
129 void set_im2_iterpolator (Im1ImageType& im2_image) {
130 im2_image_interp.reset (
new Im2ImageInterpType (im2_image));
133 void update_control_points () {
134 const Eigen::Vector3d centre = transformation.get_centre();
135 control_points.resize(4, 4);
137 control_points << 1.0, -1.0, -1.0, 1.0,
138 1.0, 1.0, -1.0, -1.0,
139 1.0, -1.0, 1.0, -1.0,
141 for (
size_t i = 0; i < 3; ++i)
142 control_points.row(i) *= control_point_exent[i];
143 control_points.block<3,4>(0,0).colwise() += centre;
148 template <
class OptimiserType>
149 void optimiser_update (OptimiserType& optim,
const ssize_t overlap_count) {
150 DEBUG (
"gradient descent ran using " +
str(optim.function_evaluations()) +
" cost function evaluations.");
152 CONSOLE (
"last valid transformation:");
153 transformation.debug();
154 CONSOLE (
"last optimisation step ran using " +
str(optim.function_evaluations()) +
" cost function evaluations.");
155 if (overlap_count == 0)
156 WARN (
"linear registration failed because (masked) images do not overlap.");
157 throw Exception (
"Linear registration failed, transformation parameters are NaN.");
159 transformation.set_parameter_vector (optim.state());
160 update_control_points();
163 void make_diagnostics_image (
const std::basic_string<char>& image_path,
bool masked =
true) {
164 Header header (midway_image);
169 auto trafo1 = transformation.get_transform_half();
170 auto trafo2 = transformation.get_transform_half_inverse();
172 header.keyval()[
"control_points"] =
str(control_points);
173 header.keyval()[
"trafo1"] =
str(trafo1.matrix());
174 header.keyval()[
"trafo2"] =
str(trafo2.matrix());
179 im1_image, midway_image, trafo1, no_oversampling, NAN);
181 im2_image, midway_image, trafo2, no_oversampling, NAN);
184 Eigen::Vector3d midway_point, voxel_pos, im1_point, im2_point;
186 for (
auto i =
Loop (midway_image) (
check, im1_reslicer, im2_reslicer); i; ++i) {
188 midway_point = T * voxel_pos;
191 check.value() = im1_reslicer.value();
192 if (masked and im1_mask_interp) {
193 transformation.transform_half (im1_point, midway_point);
194 im1_mask_interp->scanner (im1_point);
195 if (im1_mask_interp->value() < 0.5)
200 check.value() = im2_reslicer.value();
201 if (masked and im2_mask_interp) {
202 transformation.transform_half_inverse (im2_point, midway_point);
203 im2_mask_interp->scanner (im2_point);
204 if (im2_mask_interp->value() < 0.5)
207 if (robust_estimate_score1_interp) {
209 transformation.transform_half (im1_point, midway_point);
210 robust_estimate_score1_interp->scanner (im1_point);
211 transformation.transform_half_inverse (im2_point, midway_point);
212 robust_estimate_score2_interp->scanner (im2_point);
213 if (robust_estimate_score1_interp->value() >= 0.5 && robust_estimate_score2_interp->value() >= 0.5)
225 INFO(
"diagnostics image written");
229 TransformType& transformation;
230 Im1ImageType im1_image;
231 Im2ImageType im2_image;
232 MidwayImageType midway_image;
235 Im1MaskType im1_mask;
236 Im2MaskType im2_mask;
240 Eigen::Vector3d control_point_exent;
242 bool robust_estimate_subset;
243 bool robust_estimate_use_score;
246 Image<float> robust_estimate_score1, robust_estimate_score2;
250 Eigen::Matrix<default_type, Eigen::Dynamic, Eigen::Dynamic> control_points;
254 ProcImageType processed_image;
256 ProcMaskType processed_mask;
261 Eigen::Matrix<default_type, Eigen::Dynamic, 1> mc_weights;
an Image providing interpolated values from another Image
static constexpr uint8_t Float64
static Image create(const std::string &image_name, const Header &template_header, bool add_to_command_history=true)
bool is_finite(const Eigen::MatrixBase< Derived > &x)
check if all elements of an Eigen MatrixBase object are finite
FORCE_INLINE LoopAlongAxes Loop()
bool check(int VERSION, Header &H, const size_t num_axes, const vector< std::string > &suffixes)
MR::default_type value_type
double default_type
the default type used throughout MRtrix
std::string str(const T &value, int precision=0)
constexpr default_type NaN