Developer documentation
Version 3.0.3-105-gd3941f44
demons4D.h
Go to the documentation of this file.
1/* Copyright (c) 2008-2022 the MRtrix3 contributors.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 *
7 * Covered Software is provided under this License on an "as is"
8 * basis, without warranty of any kind, either expressed, implied, or
9 * statutory, including, without limitation, warranties that the
10 * Covered Software is free of defects, merchantable, fit for a
11 * particular purpose or non-infringing.
12 * See the Mozilla Public License v. 2.0 for more details.
13 *
14 * For more details, see http://www.mrtrix.org/.
15 */
16
17#ifndef __registration_metric_demons4D_h__
18#define __registration_metric_demons4D_h__
19
20#include <mutex>
21
22#include "image_helpers.h"
23#include "adapter/gradient3D.h"
25
26namespace MR
27{
28 namespace Registration
29 {
30 namespace Metric
31 {
32
33 template <class Im1ImageType, class Im2ImageType, class Im1MaskType, class Im2MaskType>
35 public:
36 Demons4D (default_type& global_energy, size_t& global_voxel_count,
37 const Im1ImageType& im1_image, const Im2ImageType& im2_image, const Im1MaskType im1_mask, const Im2MaskType im2_mask,
39 global_cost (global_energy),
41 thread_cost (0.0),
43 mutex (new std::mutex),
44 normaliser (0.0),
45 robustness_parameter (1.e-12), // MP: used to be -1.e12
48 im1_gradient (im1_image, true), im2_gradient (im2_image, true),
51 nvols (im1_image.size(3))
52 {
53 for (size_t d = 0; d < 3; ++d)
54 normaliser += im1_image.spacing(d) * im2_image.spacing(d);
55 normaliser /= 3.0;
56
57 weight.resize (nvols);
58 speed.resize (nvols);
59 speed_squared.resize (nvols);
60
61 if (contrast_settings and contrast_settings->size() > 1) {
62 for (const auto & mc : *contrast_settings)
63 weight.segment(mc.start,mc.nvols).fill(mc.weight);
64 } else
65 weight.fill(1.0);
66 DEBUG ("Demons4D weights: " + str(weight.transpose()));
67 }
68
69 ~Demons4D () {
70 std::lock_guard<std::mutex> lock (*mutex);
73 }
74
75 void set_im1_mask (const Image<float>& mask) {
76 im1_mask = mask;
77 }
78
79 void set_im2_mask (const Image<float>& mask) {
80 im2_mask = mask;
81 }
82
83
84 void operator() (Im1ImageType& im1_image,
85 Im2ImageType& im2_image,
86 Image<default_type>& im1_update,
87 Image<default_type>& im2_update) {
88 assert (im1_image.size(3) == nvols);
89 assert (im2_image.size(3) == nvols);
90
91 if (im1_image.index(0) == 0 || im1_image.index(0) == im1_image.size(0) - 1 ||
92 im1_image.index(1) == 0 || im1_image.index(1) == im1_image.size(1) - 1 ||
93 im1_image.index(2) == 0 || im1_image.index(2) == im1_image.size(2) - 1) {
94 im1_update.row(3) = 0.0;
95 im2_update.row(3) = 0.0;
96 return;
97 }
98
99
100 typename Im1MaskType::value_type im1_mask_value = 1.0;
101 if (im1_mask.valid()) {
102 assign_pos_of (im1_image, 0, 3).to (im1_mask);
103 im1_mask_value = im1_mask.value();
104 if (im1_mask_value < 0.1) {
105 im1_update.row(3) = 0.0;
106 im2_update.row(3) = 0.0;
107 return;
108 }
109 }
110
111 typename Im2MaskType::value_type im2_mask_value = 1.0;
112 if (im2_mask.valid()) {
113 assign_pos_of (im2_image, 0, 3).to (im2_mask);
114 im2_mask_value = im2_mask.value();
115 if (im2_mask_value < 0.1) {
116 im1_update.row(3) = 0.0;
117 im2_update.row(3) = 0.0;
118 return;
119 }
120 }
121
122 assign_pos_of (im1_image, 0, 3).to (im1_gradient, im2_gradient);
123
124 speed = im2_image.row(3);
125 speed -= im1_image.row(3);
126 // set speed to zero if abs(speed) < robustness_parameter
127 speed = (speed.array().abs() < robustness_parameter).select(0.0, speed);
128 speed_squared = speed.cwiseProduct(speed);
129
132
133 total_update.fill(0.0);
134 for (ssize_t vol = 0; vol < nvols; ++vol) {
136 continue;
137 im1_gradient.index(3) = vol;
138 im2_gradient.index(3) = vol;
139 grad = (im2_gradient.value() + im1_gradient.value()).array() / 2.0;
140
141 default_type denominator = speed_squared[vol] / normaliser + grad.squaredNorm();
142 if (denominator < denominator_threshold)
143 continue;
144 total_update += (weight[vol] * speed[vol] / denominator) * grad;
145 }
147
148 im1_update.row(3) = total_update;
149 im2_update.row(3) = -total_update;
150 }
151
152
153 protected:
158 std::shared_ptr<std::mutex> mutex;
163
166 Im1MaskType im1_mask;
167 Im2MaskType im2_mask;
168
170 const ssize_t nvols;
171 Eigen::VectorXd weight;
172
173 Eigen::Matrix<default_type, Eigen::Dynamic, 1> speed, speed_squared;
174 Eigen::Vector3d total_update;
175 Eigen::Matrix<default_type, 3, 1> grad;
176
177 };
178 }
179 }
180}
181#endif
const vector< MultiContrastSetting > * contrast_settings
Definition: demons4D.h:169
Eigen::Matrix< default_type, Eigen::Dynamic, 1 > speed
Definition: demons4D.h:173
const default_type intensity_difference_threshold
Definition: demons4D.h:161
const default_type robustness_parameter
Definition: demons4D.h:160
Eigen::Matrix< default_type, Eigen::Dynamic, 1 > speed_squared
Definition: demons4D.h:173
Adapter::Gradient3D< Im2ImageType > im2_gradient
Definition: demons4D.h:165
Eigen::Matrix< default_type, 3, 1 > grad
Definition: demons4D.h:175
Adapter::Gradient3D< Im1ImageType > im1_gradient
Definition: demons4D.h:164
const default_type denominator_threshold
Definition: demons4D.h:162
std::shared_ptr< std::mutex > mutex
Definition: demons4D.h:158
#define DEBUG(msg)
Definition: exception.h:75
constexpr double e
Definition: math.h:39
MR::default_type value_type
Definition: typedefs.h:33
Definition: base.h:24
double default_type
the default type used throughout MRtrix
Definition: types.h:228
constexpr std::enable_if< std::is_arithmetic< X >::value &&std::is_unsigned< X >::value, X >::type abs(X x)
Definition: types.h:297
std::string str(const T &value, int precision=0)
Definition: mrtrix.h:247