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