VoxelFunction.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_VoxelFunction_H
21 #define MIRTK_VoxelFunction_H
22 
23 #include "mirtk/ImageAttributes.h"
24 #include "mirtk/VoxelDomain.h"
25 #include "mirtk/Parallel.h"
26 #include "mirtk/Stream.h"
27 
28 
29 namespace mirtk {
30 
31 
32 ////////////////////////////////////////////////////////////////////////////////
33 // Base classes
34 ////////////////////////////////////////////////////////////////////////////////
35 
36 // =============================================================================
37 // Base class for voxel functions
38 // =============================================================================
39 
40 /**
41  * Base class for voxel functions
42  *
43  * The basic voxel functions which are part of this library and included by the
44  * mirtkVoxelFunction.h module demonstrate the implementation and use of the
45  * ForEachVoxel function templates. These templates can be well optimized by the
46  * compiler and provide the fastest way of iterating over all voxels in a given
47  * image region (or the entire image) of one or more images. When processing
48  * multiple images at the same time, these must have the same image size.
49  *
50  * Example usage:
51  * \code
52  * // Determine intensity range of grayscale image
53  * GreyImage image(attr);
54  * UnaryVoxelFunction::GetMinMax minmax;
55  * ForEachVoxel(image, minmax);
56  * double min = minmax.GetMinAsDouble();
57  * double max = minmax.GetMaxAsDouble();
58  *
59  * // Add three images within a given region and store result in another
60  * NaryVoxelFunction::Sum sum;
61  * GreyImage input1(attr);
62  * GreyImage input2(attr);
63  * GreyImage input3(attr);
64  * GreyImage output(attr);
65  * blocked_range3d<int> region(1, 2, 0, attr._y, 0, attr._x);
66  * ForEachVoxel(region, input1, input2, input3, output, sum);
67  *
68  * // Subtract one image from another
69  * // Note: Voxel function passed in this case by copy instead of reference!
70  * // This is only possible if it is not a voxel reduction.
71  * GreyImage minuend (attr);
72  * GreyImage subtrahend(attr);
73  * ParallelForEachVoxel(BinaryVoxelFunction::Sub(), subtrahend, minuend);
74  * \endcode
75  *
76  * If a voxel function needs to consider also the intensities of neighboring
77  * voxels, it can access these by manipulating the given pointer to the current
78  * voxel to be processed. Useful helpers for this are the NeighborhoodOffsets
79  * and ImageRegion classes.
80  *
81  * \sa NeighborhoodOffsets, ImageRegion, ForEachVoxelDomain
82  */
84 {
85  /// Finite image domain of images processed by this voxel function
86  ///
87  /// Attributes of first image which should be identical to other images,
88  /// at least the number of voxels must be identical. This const pointer,
89  /// when not set before by the user of the voxel function or its constructor,
90  /// is set by the ForEachVoxelBody constructor called by the ForEachVoxel
91  /// and ParallelForEachVoxel template functions.
92  ///
93  /// These image attributes give access to commonly needed functions within
94  /// the voxel function operator() implementation such as:
95  /// - ImageAttributes::LatticeToWorld
96  /// - ImageAttributes::WorldToLattice
97  /// - ImageAttributes::IsBoundary
98  /// and of course the actual data members of the ImageAttributes structure.
100 
101  /// Default constructor
102  VoxelFunction() : _Domain(nullptr) {}
103 
104  /// Used by ParallelForEachVoxel to determine if voxel function has to
105  /// be executed using parallel_reduce
106  static bool IsReduction() { return false; }
107 
108  /// Split "constructor"
109  ///
110  /// \note A method is used instead of an actual split constructor such that
111  /// subclasses which are not used for reduction do not need to
112  /// implement such constructor.
113  void split(VoxelFunction &) {}
114 
115  /// Join results
116  void join(VoxelFunction &) {}
117 };
118 
119 
120 /**
121  * Base class for voxel functions which implement a reduction of voxel values
122  *
123  * Voxel functions derived from this base class are run by ParallelForEachVoxel
124  * using parallel_reduce instead of parallel_for. Typical voxel reduction
125  * functions are unary functions computing image statistics such as the min,
126  * max, mean, or variance of voxel values within an image region.
127  */
129 {
130  /// Used by ParallelForEachVoxel to determine if voxel function has to
131  /// be executed using parallel_reduce
132  static bool IsReduction() { return true; }
133 
134  /// Split "constructor"
136  {
137  cerr << "VoxelReduction::split must be overriden by each subclass!" << endl;
138  cerr << "Otherwise you should use VoxelFunction with parallel_for instead." << endl;
139  exit(1);
140  }
141 
142  /// Join results
144  {
145  cerr << "VoxelReduction::join must be overriden by each subclass!" << endl;
146  cerr << "Otherwise you should use VoxelFunction with parallel_for instead." << endl;
147  exit(1);
148  }
149 };
150 
151 // =============================================================================
152 // Base class for ForEachVoxel body with single voxel function
153 // =============================================================================
154 
155 /**
156  * Base class for ForEachVoxel template function body with single voxel
157  * function for each voxel
158  */
159 template <class VoxelFunc>
161 {
162  // ---------------------------------------------------------------------------
163  // Members
164 
165  VoxelFunc _VoxelFunc; ///< Functor executed for each voxel
166  int _k, _l; ///< Indices for fixed dimensions
167 
168  // ---------------------------------------------------------------------------
169  // Construction
170 
171  /// Constructor
172  ForEachVoxelBody(const VoxelFunc &vf, const ImageAttributes &attr)
173  :
174  _VoxelFunc(vf), _k(0), _l(0)
175  {
176  if (!_VoxelFunc.VoxelFunction::_Domain) {
177  _VoxelFunc.VoxelFunction::_Domain = &attr;
178  }
179  }
180 
181  /// Copy constructor
183  :
184  _VoxelFunc(o._VoxelFunc), _k(o._k), _l(o._l)
185  {}
186 
187  // ---------------------------------------------------------------------------
188  // Parallel reduction
189 
190  /// Split constructor
192  :
193  _VoxelFunc(o._VoxelFunc), _k(o._k), _l(o._l)
194  {
195  _VoxelFunc.split(o._VoxelFunc);
196  }
197 
198  /// Join results
200  {
201  _VoxelFunc.join(rhs._VoxelFunc);
202  }
203 };
204 
205 // =============================================================================
206 // Base class for ForEachVoxelIf body with separate inside/outside voxel functions
207 // =============================================================================
208 
209 /**
210  * Base class for ForEachVoxelIf template function body with separate voxel
211  * function for inside and outside voxels
212  */
213 template <class VoxelFunc, class OutsideFunc>
214 struct ForEachVoxelIfBody : public ForEachVoxelBody<VoxelFunc>
215 {
216  // ---------------------------------------------------------------------------
217  // Members
218 
219  OutsideFunc _OutsideFunc; ///< Functor executed for each background voxel
220 
221  // ---------------------------------------------------------------------------
222  // Construction
223 
224  /// Constructor
225  ForEachVoxelIfBody(const VoxelFunc &vf, const OutsideFunc &of, const ImageAttributes &attr)
226  :
227  ForEachVoxelBody<VoxelFunc>(vf, attr), _OutsideFunc(of)
228  {}
229 
230  /// Copy constructor
232  :
233  ForEachVoxelBody<VoxelFunc>(o), _OutsideFunc(o._OutsideFunc)
234  {}
235 
236  // ---------------------------------------------------------------------------
237  // Parallel reduction
238 
239  /// Split constructor
241  :
242  ForEachVoxelBody<VoxelFunc>(o, s),
243  _OutsideFunc(o._OutsideFunc)
244  {
245  _OutsideFunc.split(o._OutsideFunc);
246  }
247 
248  /// Join results
250  {
252  _OutsideFunc.join(rhs._OutsideFunc);
253  }
254 };
255 
256 // =============================================================================
257 // NOP voxel function
258 // =============================================================================
259 
260 namespace NaryVoxelFunction {
261 
262 
263 /**
264  * NOP voxel function, e.g., used as default outside function by ForEachVoxelIf
265  */
266 struct NOP : public VoxelFunction
267 {
268  /// Unary voxel function operator
269  template <class TImage>
270  void operator()(const TImage&, int, const void *) const {}
271  /// Unary voxel function operator
272  void operator()(int, int, int, int, const void *) const {}
273 
274  /// Binary voxel function operator
275  template <class TImage>
276  void operator()(const TImage&, int, const void *, const void *) const {}
277  /// Binary voxel function operator
278  void operator()(int, int, int, int, const void *, const void *) const {}
279 
280  /// Ternary voxel function operator
281  template <class TImage>
282  void operator()(const TImage&, int, const void *, const void *, const void *) const {}
283  /// Ternary voxel function operator
284  void operator()(int, int, int, int, const void *, const void *, const void *) const {}
285 
286  /// Quaternary voxel function operator
287  template <class TImage>
288  void operator()(const TImage&, int, const void *, const void *, const void *, const void *) const {}
289  /// Quaternary voxel function operator
290  void operator()(int, int, int, int, const void *, const void *, const void *, const void *) const {}
291 
292  /// Quinery voxel function operator
293  template <class TImage>
294  void operator()(const TImage&, int, const void *, const void *, const void *, const void *, const void *) const {}
295  /// Quinery voxel function operator
296  void operator()(int, int, int, int, const void *, const void *, const void *, const void *, const void *) const {}
297 
298  /// Senary voxel function operator
299  template <class TImage>
300  void operator()(const TImage&, int, const void *, const void *, const void *, const void *, const void *, const void *) const {}
301  /// Senary voxel function operator
302  void operator()(int, int, int, int, const void *, const void *, const void *, const void *, const void *, const void *) const {}
303 
304  /// Septenary voxel function operator
305  template <class TImage>
306  void operator()(const TImage&, int, const void *, const void *, const void *, const void *, const void *, const void *, const void *) const {}
307  /// Septenary voxel function operator
308  void operator()(int, int, int, int, const void *, const void *, const void *, const void *, const void *, const void *, const void *) const {}
309 
310  /// Octary voxel function operator
311  template <class TImage>
312  void operator()(const TImage&, int, const void *, const void *, const void *, const void *, const void *, const void *, const void *, const void *) const {}
313  /// Octary voxel function operator
314  void operator()(int, int, int, int, const void *, const void *, const void *, const void *, const void *, const void *, const void *, const void *) const {}
315 
316  /// Nonary voxel function operator
317  template <class TImage>
318  void operator()(const TImage&, int, const void *, const void *, const void *, const void *, const void *, const void *, const void *, const void *, const void *) const {}
319  /// Nonary voxel function operator
320  void operator()(int, int, int, int, const void *, const void *, const void *, const void *, const void *, const void *, const void *, const void *, const void *) const {}
321 };
322 
323 
324 } // namespace NaryVoxelFunction
325 } // namespace mirtk
326 
327 // =============================================================================
328 // ForEachVoxel template functions for various number of image arguments
329 // =============================================================================
330 
331 #include "mirtk/ForEachUnaryVoxelFunction.h"
332 #include "mirtk/ForEachBinaryVoxelFunction.h"
333 #include "mirtk/ForEachTernaryVoxelFunction.h"
334 #include "mirtk/ForEachQuaternaryVoxelFunction.h"
335 #include "mirtk/ForEachQuinaryVoxelFunction.h"
336 #include "mirtk/ForEachSenaryVoxelFunction.h"
337 #include "mirtk/ForEachSeptenaryVoxelFunction.h"
338 #include "mirtk/ForEachOctaryVoxelFunction.h"
339 #include "mirtk/ForEachNonaryVoxelFunction.h"
340 
341 
342 #endif // MIRTK_VoxelFunction_H
void operator()(const TImage &, int, const void *, const void *, const void *) const
Ternary voxel function operator.
void operator()(const TImage &, int, const void *, const void *, const void *, const void *, const void *, const void *, const void *, const void *, const void *) const
Nonary voxel function operator.
void operator()(int, int, int, int, const void *, const void *, const void *, const void *, const void *, const void *) const
Senary voxel function operator.
void operator()(int, int, int, int, const void *, const void *, const void *) const
Ternary voxel function operator.
void operator()(const TImage &, int, const void *, const void *) const
Binary voxel function operator.
ForEachVoxelIfBody(const VoxelFunc &vf, const OutsideFunc &of, const ImageAttributes &attr)
Constructor.
Dummy type used to distinguish split constructor from copy constructor.
Definition: Parallel.h:143
void operator()(int, int, int, int, const void *, const void *, const void *, const void *, const void *, const void *, const void *, const void *, const void *) const
Nonary voxel function operator.
void operator()(int, int, int, int, const void *, const void *, const void *, const void *) const
Quaternary voxel function operator.
void operator()(int, int, int, int, const void *, const void *) const
Binary voxel function operator.
ForEachVoxelIfBody(ForEachVoxelIfBody &o, split s)
Split constructor.
void operator()(int, int, int, int, const void *, const void *, const void *, const void *, const void *, const void *, const void *) const
Septenary voxel function operator.
ForEachVoxelBody(const ForEachVoxelBody &o)
Copy constructor.
void join(ForEachVoxelBody &rhs)
Join results.
ForEachVoxelIfBody(const ForEachVoxelIfBody &o)
Copy constructor.
VoxelFunction()
Default constructor.
const ImageAttributes * _Domain
Definition: VoxelFunction.h:99
void operator()(const TImage &, int, const void *, const void *, const void *, const void *) const
Quaternary voxel function operator.
VoxelFunc _VoxelFunc
Functor executed for each voxel.
ForEachVoxelBody(const VoxelFunc &vf, const ImageAttributes &attr)
Constructor.
static bool IsReduction()
void join(VoxelFunction &)
Join results.
Definition: IOConfig.h:41
void operator()(const TImage &, int, const void *, const void *, const void *, const void *, const void *, const void *) const
Senary voxel function operator.
void operator()(int, int, int, int, const void *) const
Unary voxel function operator.
int _l
Indices for fixed dimensions.
void join(VoxelFunction &)
Join results.
static bool IsReduction()
void operator()(const TImage &, int, const void *, const void *, const void *, const void *, const void *) const
Quinery voxel function operator.
OutsideFunc _OutsideFunc
Functor executed for each background voxel.
void operator()(int, int, int, int, const void *, const void *, const void *, const void *, const void *, const void *, const void *, const void *) const
Octary voxel function operator.
ForEachVoxelBody(ForEachVoxelBody &o, split s)
Split constructor.
void operator()(const TImage &, int, const void *) const
Unary voxel function operator.
void operator()(const TImage &, int, const void *, const void *, const void *, const void *, const void *, const void *, const void *) const
Septenary voxel function operator.
void join(ForEachVoxelIfBody &rhs)
Join results.
void operator()(const TImage &, int, const void *, const void *, const void *, const void *, const void *, const void *, const void *, const void *) const
Octary voxel function operator.
void split(VoxelFunction &)
void split(VoxelFunction &)
Split "constructor".
void operator()(int, int, int, int, const void *, const void *, const void *, const void *, const void *) const
Quinery voxel function operator.