NaryVoxelFunction.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2013-2015 Imperial College London
5  * Copyright 2013-2015 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_NaryVoxelFunction_H
21 #define MIRTK_NaryVoxelFunction_H
22 
23 #include "mirtk/VoxelFunction.h"
24 #include "mirtk/BaseImage.h"
25 #include "mirtk/InterpolateImageFunction.h"
26 
27 
28 namespace mirtk {
29 
30 
31 /**
32  * Namespace containing voxel functions with different number of arguments
33  *
34  * The voxel functions defined in this namespace may provide different overloads
35  * of the operator() for different number of image arguments to the ForEachVoxel
36  * template functions.
37  *
38  */
39 namespace NaryVoxelFunction {
40 
41 
42 // =============================================================================
43 // Stationary velocity fields
44 // =============================================================================
45 
46 // -----------------------------------------------------------------------------
47 /// Voxel function for exponentiation of 2D velocity field
48 template <class TInterpolator = InterpolateImageFunction>
50 {
51  const BaseImage *_VelocityField; ///< Velocity field
52  TInterpolator *_VelocityInterpolator; ///< Velocity field interpolator
53  int _NumberOfSteps; ///< Number of integration steps
54 
55  double _dt; ///< Temporal step length
56  static const int _x = 0; ///< Offset of x component
57  int _y; ///< Offset of y component
58 
59 
60  ExpVelocityFieldEuler2D(TInterpolator *v, int n = 100, double t = 1.0)
61  :
62  _VelocityField(v->Input()),
63  _VelocityInterpolator (v),
64  _NumberOfSteps(n),
65  _dt(t / _NumberOfSteps),
66  _y(_VelocityField->GetX() * _VelocityField->GetY())
67  {}
68 
69  template <class T>
70  void operator ()(int i, int j, int k, int, T *d)
71  {
72  double x, y, z, v[3]; // 2D vector field could have constant third component!
73  double x1 = i, y1 = j, z1 = k;
74  _VelocityField->ImageToWorld(x1, y1, z1);
75  double x2 = x1, y2 = y1;
76  for (int s = 0; s < _NumberOfSteps; ++s) {
77  x = x2, y = y2, z = z1;
78  _VelocityField ->WorldToImage(x, y, z);
79  _VelocityInterpolator->Evaluate(v, x, y, z);
80  x2 += v[0] * _dt;
81  y2 += v[1] * _dt;
82  }
83  d[_x] = static_cast<T>(x2 - x1);
84  d[_y] = static_cast<T>(y2 - y1);
85  }
86 
87  template <class T>
88  void operator ()(int i, int j, int k, int, const T *din, T *dout)
89  {
90  double x, y, z, v[3]; // 2D vector field could have constant third component!
91  double x1 = i, y1 = j, z1 = k;
92  _VelocityField->ImageToWorld(x1, y1, z1);
93  double x2 = x1 + din[_x];
94  double y2 = y1 + din[_y];
95  for (int s = 0; s < _NumberOfSteps; ++s) {
96  x = x2, y = y2, z = z1;
97  _VelocityField ->WorldToImage(x, y, z);
98  _VelocityInterpolator->Evaluate(v, x, y, z);
99  x2 += v[0] * _dt;
100  y2 += v[1] * _dt;
101  }
102  dout[_x] = static_cast<T>(x2 - x1);
103  dout[_y] = static_cast<T>(y2 - y1);
104  }
105 };
106 
107 // -----------------------------------------------------------------------------
108 /// Voxel function for exponentiation of 3D velocity field
109 template <class TInterpolator = InterpolateImageFunction>
111 {
112  const BaseImage *_VelocityField; ///< Velocity field
113  TInterpolator *_VelocityInterpolator; ///< Velocity field interpolator
114  int _NumberOfSteps; ///< Number of integration steps
115 
116  double _dt; ///< Temporal step length
117  static const int _x = 0; ///< Offset of x component
118  int _y, _z; ///< Offset of y and z components
119 
120 
121  ExpVelocityFieldEuler3D(TInterpolator *v, int n = 100, double t = 1.0)
122  :
123  _VelocityField(v->Input()),
124  _VelocityInterpolator (v),
125  _NumberOfSteps(n),
126  _dt(t / _NumberOfSteps),
127  _y(_VelocityField->X() * _VelocityField->Y() * _VelocityField->Z()),
128  _z(2 * _y)
129  {}
130 
131  template <class T>
132  void operator ()(int i, int j, int k, int, T *d)
133  {
134  double x, y, z, v[3];
135  double x1 = i, y1 = j, z1 = k;
136  _VelocityField->ImageToWorld(x1, y1, z1);
137  double x2 = x1, y2 = y1, z2 = z1;
138  for (int s = 0; s < _NumberOfSteps; ++s) {
139  x = x2, y = y2, z = z2;
140  _VelocityField ->WorldToImage(x, y, z);
141  _VelocityInterpolator->Evaluate(v, x, y, z);
142  x2 += v[0] * _dt;
143  y2 += v[1] * _dt;
144  z2 += v[2] * _dt;
145  }
146  d[_x] = static_cast<T>(x2 - x1);
147  d[_y] = static_cast<T>(y2 - y1);
148  d[_z] = static_cast<T>(z2 - z1);
149  }
150 
151  template <class T>
152  void operator ()(int i, int j, int k, int, const T *din, T *dout)
153  {
154  double x, y, z, v[3];
155  double x1 = i, y1 = j, z1 = k;
156  _VelocityField->ImageToWorld(x1, y1, z1);
157  double x2 = x1 + din[_x];
158  double y2 = y1 + din[_y];
159  double z2 = z1 + din[_z];
160  for (int s = 0; s < _NumberOfSteps; ++s) {
161  x = x2, y = y2, z = z2;
162  _VelocityField ->WorldToImage(x, y, z);
163  _VelocityInterpolator->Evaluate(v, x, y, z);
164  x2 += v[0] * _dt;
165  y2 += v[1] * _dt;
166  z2 += v[2] * _dt;
167  }
168  dout[_x] = static_cast<T>(x2 - x1);
169  dout[_y] = static_cast<T>(y2 - y1);
170  dout[_z] = static_cast<T>(z2 - z1);
171  }
172 };
173 
174 // -----------------------------------------------------------------------------
175 /// Compute voxel-wise weighted sum
177 {
178  const double *_Weight;
179 
180  template <class TImage, class T>
181  void operator()(const TImage &, int, const T *a, const T *b, T *out)
182  {
183  (*out) = static_cast<T>(_Weight[0] * (*a) + _Weight[1] * (*b));
184  }
185 
186  template <class TImage, class T>
187  void operator()(const TImage &, int, const T *a, const T *b, const T *c, T *out)
188  {
189  (*out) = static_cast<T>(_Weight[0] * (*a) + _Weight[1] * (*b) + _Weight[2] * (*c));
190  }
191 
192  template <class TImage, class T>
193  void operator()(const TImage &, int, const T *a, const T *b, const T *c, const T *d, T *out)
194  {
195  (*out) = static_cast<T>(_Weight[0] * (*a) + _Weight[1] * (*b) + _Weight[2] * (*c) + _Weight[3] * (*d));
196  }
197 
198  template <class TImage, class T>
199  void operator()(const TImage &, int, const T *a, const T *b, const T *c, const T *d, const T *e, T *out)
200  {
201  (*out) = static_cast<T>(_Weight[0] * (*a) + _Weight[1] * (*b) + _Weight[2] * (*c) + _Weight[3] * (*d) + _Weight[4] * (*e));
202  }
203 
204  template <class TImage, class T>
205  void operator()(const TImage &, int, const T *a, const T *b, const T *c, const T *d, const T *e, const T *f, T *out)
206  {
207  (*out) = static_cast<T>(_Weight[0] * (*a) + _Weight[1] * (*b) + _Weight[2] * (*c) + _Weight[3] * (*d) + _Weight[4] * (*e) + _Weight[5] * (*f));
208  }
209 
210  template <class TImage, class T>
211  void operator()(const TImage &, int, const T *a, const T *b, const T *c, const T *d, const T *e, const T *f, const T *g, T *out)
212  {
213  (*out) = static_cast<T>(_Weight[0] * (*a) + _Weight[1] * (*b) + _Weight[2] * (*c) + _Weight[3] * (*d) + _Weight[4] * (*e) + _Weight[5] * (*f) + _Weight[6] * (*g));
214  }
215 };
216 
217 // -----------------------------------------------------------------------------
218 /// Evaluate Baker-Campbell-Hausdorff (BCH) formula
220 {
221  template <class TImage, class T>
222  void operator()(const TImage &, int, const T *v, const T *d, T *out)
223  {
224  (*out) = (*v) + (*d);
225  }
226 
227  template <class TImage, class T>
228  void operator()(const TImage &, int, const T *v, const T *d, const T *l1, T *out)
229  {
230  (*out) = static_cast<T>((*v) + (*d) + (*l1) / 2.0);
231  }
232 
233  template <class TImage, class T>
234  void operator()(const TImage &, int, const T *v, const T *d, const T *l1, const T *l2, T *out)
235  {
236  (*out) = static_cast<T>((*v) + (*d) + (*l1) / 2.0 + (*l2) / 12.0);
237  }
238 
239  template <class TImage, class T>
240  void operator()(const TImage &, int, const T *v, const T *d, const T *l1, const T *l2, const T *l3, T *out)
241  {
242  (*out) = static_cast<T>((*v) + (*d) + (*l1) / 2.0 + (*l2) / 12.0 - (*l3) / 12.0);
243  }
244 
245  template <class TImage, class T>
246  void operator()(const TImage &, int, const T *v, const T *d, const T *l1, const T *l2, const T *l3, const T *l4, T *out)
247  {
248  (*out) = static_cast<T>((*v) + (*d) + (*l1) / 2.0 + (*l2) / 12.0 - (*l3) / 12.0 - (*l4) / 24.0);
249  }
250 };
251 
252 // -----------------------------------------------------------------------------
253 /// Evaluate velocity update using Baker-Campbell-Hausdorff (BCH) formula
255 {
256  template <class TImage, class T>
257  void operator()(const TImage &, int, const T *d, const T *l1, T *out)
258  {
259  (*out) = static_cast<T>((*d) + (*l1) / 2.0);
260  }
261 
262  template <class TImage, class T>
263  void operator()(const TImage &, int, const T *d, const T *l1, const T *l2, T *out)
264  {
265  (*out) = static_cast<T>((*d) + (*l1) / 2.0 + (*l2) / 12.0);
266  }
267 
268  template <class TImage, class T>
269  void operator()(const TImage &, int, const T *d, const T *l1, const T *l2, const T *l3, T *out)
270  {
271  (*out) = static_cast<T>((*d) + (*l1) / 2.0 + (*l2) / 12.0 - (*l3) / 12.0);
272  }
273 
274  template <class TImage, class T>
275  void operator()(const TImage &, int, const T *d, const T *l1, const T *l2, const T *l3, const T *l4, T *out)
276  {
277  (*out) = static_cast<T>((*d) + (*l1) / 2.0 + (*l2) / 12.0 - (*l3) / 12.0 - (*l4) / 24.0);
278  }
279 };
280 
281 
282 } } // namespace mirtk::NaryVoxelFunction
283 
284 #endif // MIRTK_NaryVoxelFunction_H
static const int _x
Offset of x component.
void WorldToImage(double &, double &) const
World to image coordinate conversion with two doubles.
Definition: BaseImage.h:1212
const BaseImage * _VelocityField
Velocity field.
int _NumberOfSteps
Number of integration steps.
int _NumberOfSteps
Number of integration steps.
Voxel function for exponentiation of 2D velocity field.
Definition: IOConfig.h:41
void ImageToWorld(double &, double &) const
Image to world coordinate conversion with two doubles.
Definition: BaseImage.h:1180
TInterpolator * _VelocityInterpolator
Velocity field interpolator.
const BaseImage * _VelocityField
Velocity field.
Evaluate velocity update using Baker-Campbell-Hausdorff (BCH) formula.
TInterpolator * _VelocityInterpolator
Velocity field interpolator.
Evaluate Baker-Campbell-Hausdorff (BCH) formula.
Voxel function for exponentiation of 3D velocity field.