Developer documentation
Version 3.0.3-105-gd3941f44
demons_cc.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
18#ifndef __registration_metric_demons_cc_h__
19#define __registration_metric_demons_cc_h__
20
21
22#include <mutex>
23
24#include "image_helpers.h"
25#include "adapter/gradient3D.h"
26
27namespace MR
28{
29 namespace Registration
30 {
31 namespace Metric
32 {
33
34 template <class Im1ImageType, class Im2ImageType, class Im1MaskType, class Im2MaskType>
36 public:
37 DemonsCC (default_type& global_energy, size_t& global_voxel_count,
38 const Im1ImageType& im1_meansubtracted, const Im2ImageType& im2_meansubtracted, 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),
48 im1_gradient (im1_meansubtracted, true), im2_gradient (im2_meansubtracted, true),
50 {
51 for (size_t d = 0; d < 3; ++d)
52 normaliser += im1_meansubtracted.spacing(d) * im2_meansubtracted.spacing(d);
53 normaliser /= 3.0;
54 }
55
56 ~DemonsCC () {
57 std::lock_guard<std::mutex> lock (*mutex);
60 }
61
62 void set_im1_mask (const Image<float>& mask) {
63 im1_mask = mask;
64 }
65
66 void set_im2_mask (const Image<float>& mask) {
67 im2_mask = mask;
68 }
69
70 void operator() (const Im1ImageType& im1_meansubtracted,
71 const Im2ImageType& im2_meansubtracted,
72 const Im2ImageType& A,
73 const Im2ImageType& B,
74 const Im2ImageType& C,
75 Image<default_type>& im1_update,
76 Image<default_type>& im2_update) {
77
78 if (im1_meansubtracted.index(0) == 0 || im1_meansubtracted.index(0) == im1_meansubtracted.size(0) - 1 ||
79 im1_meansubtracted.index(1) == 0 || im1_meansubtracted.index(1) == im1_meansubtracted.size(1) - 1 ||
80 im1_meansubtracted.index(2) == 0 || im1_meansubtracted.index(2) == im1_meansubtracted.size(2) - 1) {
81 im1_update.row(3) = 0.0;
82 im2_update.row(3) = 0.0;
83 return;
84 }
85
86 typename Im1MaskType::value_type im1_mask_value = 1.0;
87 if (im1_mask.valid()) {
88 assign_pos_of (im1_meansubtracted, 0, 3).to (im1_mask);
89 im1_mask_value = im1_mask.value();
90 if (im1_mask_value < 0.1) {
91 im1_update.row(3) = 0.0;
92 im2_update.row(3) = 0.0;
93 return;
94 }
95 }
96
97 typename Im2MaskType::value_type im2_mask_value = 1.0;
98 if (im2_mask.valid()) {
99 assign_pos_of (im2_meansubtracted, 0, 3).to (im2_mask);
100 im2_mask_value = im2_mask.value();
101 if (im2_mask_value < 0.1) {
102 im1_update.row(3) = 0.0;
103 im2_update.row(3) = 0.0;
104 return;
105 }
106 }
107
108 default_type sfm = A.value();
109 default_type smm = B.value();
110 default_type sff = C.value();
111 default_type asq = sfm * sfm;
112
113 default_type denom = smm * sff;
114 if (std::isnan(sfm) || std::isnan(denom) || MR::abs (denom) < denominator_threshold) {
115 // if (std::abs (asq) > robustness_parameter)
116 // thread_voxel_count++; // TODO to count or not to count?
117 im1_update.row(3) = 0.0;
118 im2_update.row(3) = 0.0;
119 return;
120 }
121
122 default_type lcc = asq / denom;
123 thread_cost -= lcc;
125
126 assign_pos_of (im1_meansubtracted, 0, 3).to (im1_gradient, im2_gradient);
127
128 default_type i1 = im1_meansubtracted.value();
129 default_type i2 = im2_meansubtracted.value();
130
131 // Avants eq. 6 and 7
132 Eigen::Matrix<typename Im1ImageType::value_type, 3, 1> grad = 2.0 * sfm / (sff * smm) * (
133 (i2 - sfm / smm * i1 ) * im1_gradient.value() - (i1 - sfm / sff * i2 ) * im2_gradient.value());
134 // TODO: add det(jacobian(Phi)))
135
136 im1_update.row(3) = grad * 40.0; // TODO: normalise the update?
137 im2_update.row(3) = -grad * 40.0;
138 }
139
140 protected:
145 std::shared_ptr<std::mutex> mutex;
150
153 Im1MaskType im1_mask;
154 Im2MaskType im2_mask;
155
156 };
157 }
158 }
159}
160#endif
Adapter::Gradient3D< Im1ImageType > im1_gradient
Definition: demons_cc.h:151
const default_type intensity_difference_threshold
Definition: demons_cc.h:148
std::shared_ptr< std::mutex > mutex
Definition: demons_cc.h:145
const default_type denominator_threshold
Definition: demons_cc.h:149
Adapter::Gradient3D< Im2ImageType > im2_gradient
Definition: demons_cc.h:152
const default_type robustness_parameter
Definition: demons_cc.h:147
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