LieBracketImageFilter3D.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_LieBracketImageFilter3D_H
21 #define MIRTK_LieBracketImageFilter3D_H
22 
23 
24 #include "mirtk/LieBracketImageFilter.h"
25 
26 #include "mirtk/Matrix.h"
27 #include "mirtk/Parallel.h"
28 #include "mirtk/Profiling.h"
29 
30 
31 namespace mirtk {
32 
33 
34 /**
35  * Image filter for computation of Lie bracket of two 3D vector fields.
36  */
37 
38 template <class TVoxel>
40 {
41  mirtkImageFilterMacro(LieBracketImageFilter3D, TVoxel);
42 
43 public:
44 
45  /// Type of superclass of this concrete image filter
47 
48 protected:
49 
50  /// World to image matrix (excluding translation)
52 
53  /// Compute 1st order derivatives of given vector field
54  void Jacobian(Matrix &, const ImageType &, int, int, int);
55 
56  /// Initialize filter
57  virtual void Initialize();
58 
59 public:
60 
61  /// Constructor
63 
64  /// Destructor
65  virtual ~LieBracketImageFilter3D();
66 
67  // Import other overloads
68  using Superclass::Output;
69 
70  /// Set output
71  virtual void Output(ImageType *);
72 
73  /// Run filter on every voxel
74  virtual void Run();
75 
76  /// Run filter on single voxel
77  virtual void Run(double [3], int, int, int);
78 
79  /// Run filter on single voxel and component
80  virtual double Run(int, int, int, int);
81 
82 };
83 
84 ///////////////////////////////////////////////////////////////////////////////
85 // Inline definitions
86 ///////////////////////////////////////////////////////////////////////////////
87 
88 // --------------------------------------------------------------------------
89 template <class VoxelType>
91 :
92  _MatW2I(3, 3)
93 {
94  _MatW2I.Ident();
95 }
96 
97 // --------------------------------------------------------------------------
98 template <class VoxelType>
100 {
101 }
102 
103 // --------------------------------------------------------------------------
104 template <class VoxelType>
106 {
107  Superclass::Output(output);
108  _MatW2I = output->GetWorldToImageMatrix()(0, 0, 3, 3);
109 }
110 
111 // --------------------------------------------------------------------------
112 template <class VoxelType>
114 {
115  // Initialize base class
117 
118  // Ensure that input vector fields are 3D
119  // Note that base class already ensures that inputs and output have same attributes
120  // Accept also a 2D slice of a 3D vector field as input
121  if (this->GetInput(0)->T() != 3) {
122  cerr << this->NameOfClass() << "::Initialize: Input images are no 3D vector fields" << endl;
123  exit(1);
124  }
125 }
126 
127 // ---------------------------------------------------------------------------
128 // Note: Using NN extrapolation at boundary
129 template <class VoxelType>
131 ::Jacobian(Matrix &jac, const ImageType &v, int i, int j, int k)
132 {
133  int a, b;
134  // Finite difference in x dimension
135  if (i <= 0) {
136  a = i;
137  b = i + 1;
138  } else if (i >= v.GetX()-1) {
139  a = i - 1;
140  b = i;
141  } else {
142  a = i - 1;
143  b = i + 1;
144  }
145  jac(0, 0) = 0.5 * (v(b, j, k, 0) - v(a, j, k, 0));
146  jac(1, 0) = 0.5 * (v(b, j, k, 1) - v(a, j, k, 1));
147  jac(2, 0) = 0.5 * (v(b, j, k, 2) - v(a, j, k, 2));
148  // Finite difference in y dimension
149  if (j <= 0) {
150  a = j;
151  b = j + 1;
152  } else if (j >= v.GetY()-1) {
153  a = j - 1;
154  b = j;
155  } else {
156  a = j - 1;
157  b = j + 1;
158  }
159  jac(0, 1) = 0.5 * (v(i, b, k, 0) - v(i, a, k, 0));
160  jac(1, 1) = 0.5 * (v(i, b, k, 1) - v(i, a, k, 1));
161  jac(2, 1) = 0.5 * (v(i, b, k, 2) - v(i, a, k, 2));
162  // Finite difference in z dimension
163  if (k <= 0) {
164  a = k;
165  b = k + 1;
166  } else if(k >= v.GetZ()-1) {
167  a = k - 1;
168  b = k;
169  } else {
170  a = k - 1;
171  b = k + 1;
172  }
173  jac(0, 2) = 0.5 * (v(i, j, b, 0) - v(i, j, a, 0));
174  jac(1, 2) = 0.5 * (v(i, j, b, 1) - v(i, j, a, 1));
175  jac(2, 2) = 0.5 * (v(i, j, b, 2) - v(i, j, a, 2));
176  // Project derivative from image to world space
177  jac *= _MatW2I;
178 }
179 
180 // ---------------------------------------------------------------------------
181 template <class VoxelType>
182 double LieBracketImageFilter3D<VoxelType>::Run(int i, int j, int k, int t)
183 {
184  Matrix lJ(3, 3), rJ(3, 3);
185 
186  const ImageType &lv = *this->GetInput(0);
187  const ImageType &rv = *this->GetInput(1);
188 
189  const VoxelType &lx = lv(i, j, k, 0);
190  const VoxelType &ly = lv(i, j, k, 1);
191  const VoxelType &lz = lv(i, j, k, 2);
192  const VoxelType &rx = rv(i, j, k, 0);
193  const VoxelType &ry = rv(i, j, k, 1);
194  const VoxelType &rz = rv(i, j, k, 2);
195 
196  Jacobian(lJ, lv, i, j, k);
197  Jacobian(rJ, rv, i, j, k);
198 
199  return (lJ(t, 0) * rx - lx * rJ(t, 0)) +
200  (lJ(t, 1) * ry - ly * rJ(t, 1)) +
201  (lJ(t, 2) * rz - lz * rJ(t, 2));
202 }
203 
204 // ---------------------------------------------------------------------------
205 template <class VoxelType>
206 void LieBracketImageFilter3D<VoxelType>::Run(double vec[3], int i, int j, int k)
207 {
208  Matrix lJ(3, 3), rJ(3, 3);
209 
210  const ImageType &lv = *this->GetInput(0);
211  const ImageType &rv = *this->GetInput(1);
212 
213  const VoxelType &lx = lv(i, j, k, 0);
214  const VoxelType &ly = lv(i, j, k, 1);
215  const VoxelType &lz = lv(i, j, k, 2);
216  const VoxelType &rx = rv(i, j, k, 0);
217  const VoxelType &ry = rv(i, j, k, 1);
218  const VoxelType &rz = rv(i, j, k, 2);
219 
220  Jacobian(lJ, lv, i, j, k);
221  Jacobian(rJ, rv, i, j, k);
222 
223  vec[0] = (lJ(0, 0) * rx - lx * rJ(0, 0)) +
224  (lJ(0, 1) * ry - ly * rJ(0, 1)) +
225  (lJ(0, 2) * rz - lz * rJ(0, 2));
226 
227  vec[1] = (lJ(1, 0) * rx - lx * rJ(1, 0)) +
228  (lJ(1, 1) * ry - ly * rJ(1, 1)) +
229  (lJ(1, 2) * rz - lz * rJ(1, 2));
230 
231  vec[2] = (lJ(2, 0) * rx - lx * rJ(2, 0)) +
232  (lJ(2, 1) * ry - ly * rJ(2, 1)) +
233  (lJ(2, 2) * rz - lz * rJ(2, 2));
234 }
235 
236 namespace LieBracketImageFilter3DUtils {
237 
238 // ---------------------------------------------------------------------------
239 /// Parallelizable body of LieBracketImageFilter3D::Run.
240 template <class VoxelType>
241 class Run
242 {
243 private:
244 
246  typedef typename FilterType::ImageType ImageType;
247 
248  FilterType *_LieBracketFilter; ///< Lie bracket filter
249  ImageType *_Output; ///< Output vector field
250 
251 public:
252 
253  /// Constructor
254  Run(FilterType *filter, ImageType *output)
255  :
256  _LieBracketFilter(filter),
257  _Output(output)
258  {}
259 
260  /// Run Lie bracket filter for each voxel in specified range
261  void operator ()(const blocked_range3d<int> &r) const
262  {
263  double vec[3];
264  for (int k = r.pages().begin(); k != r.pages().end(); ++k)
265  for (int j = r.rows ().begin(); j != r.rows ().end(); ++j)
266  for (int i = r.cols ().begin(); i != r.cols ().end(); ++i) {
267  _LieBracketFilter->Run(vec, i, j, k);
268  _Output->PutAsDouble(i, j, k, 0, vec[0]);
269  _Output->PutAsDouble(i, j, k, 1, vec[1]);
270  _Output->PutAsDouble(i, j, k, 2, vec[2]);
271  }
272  }
273 };
274 
275 } // namespace LieBracketImageFilter3DUtils
276 
277 // ---------------------------------------------------------------------------
278 template <class VoxelType>
280 {
281  blocked_range3d<int> voxels(0, this->GetInput(0)->Z(),
282  0, this->GetInput(0)->Y(),
283  0, this->GetInput(0)->X());
285  MIRTK_START_TIMING();
286  this->Initialize();
287  parallel_for(voxels, run);
288  this->Finalize();
289  MIRTK_DEBUG_TIMING(2, "LieBracketImageFilter");
290 }
291 
292 
293 } // namespace mirtk
294 
295 #endif // MIRTK_LieBracketImageFilter3D_H
void Jacobian(Matrix &, const ImageType &, int, int, int)
Compute 1st order derivatives of given vector field.
Parallelizable body of LieBracketImageFilter3D::Run.
virtual const ImageType * GetInput(int) const
virtual void Output(ImageType *)
Set output.
Matrix & Ident()
Set to identity matrix.
Definition: IOConfig.h:41
Run(FilterType *filter, ImageType *output)
Constructor.
int GetX() const
Returns the number of voxels in the x-direction.
Definition: BaseImage.h:904
const Matrix & GetWorldToImageMatrix() const
Return transformation matrix for world to image coordinates.
Definition: BaseImage.h:1250
GenericImage< VoxelType > ImageType
Input/output image type.
Definition: ImageToImage.h:51
int GetY() const
Returns the number of voxels in the y-direction.
Definition: BaseImage.h:910
virtual void Initialize()
Initialize filter.
Three-dimensional range.
Definition: Parallel.h:197
virtual void Run()
Run filter on every voxel.
TVoxel VoxelType
Input/output image voxel type.
Definition: ImageToImage.h:48
virtual void Initialize()
Initialize filter.
virtual const char * NameOfClass() const =0
Get name of class, which this object is an instance of.
LieBracketImageFilter< TVoxel > Superclass
Type of superclass of this concrete image filter.
virtual ~LieBracketImageFilter3D()
Destructor.
Matrix _MatW2I
World to image matrix (excluding translation)
int GetZ() const
Returns the number of voxels in the z-direction.
Definition: BaseImage.h:916
void parallel_for(const Range &range, const Body &body)
parallel_for dummy template function which executes the body serially
Definition: Parallel.h:232
virtual void Finalize()