BSplineBiasField.h
1 /*
2  * Developing brain Region Annotation With Expectation-Maximization (Draw-EM)
3  *
4  * Copyright 2013-2016 Imperial College London
5  * Copyright 2013-2016 Maria Murgasova
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 
21 #ifndef _MIRTKBSPLINEBIASFIELD_H
22 
23 #define _MIRTKBSPLINEBIASFIELD_H
24 
25 //#include "mirtk/Geometry.h"
26 #include "mirtk/BiasField.h"
27 
28 #define BIASLOOKUPTABLESIZE 1000
29 
30 namespace mirtk {
31 
32 class BSplineBiasField : public BiasField
33 {
34  mirtkObjectMacro(BSplineBiasField);
35 
36 protected:
37 
38  /// Returns the value of the first B-spline basis function
39  static double B0(double);
40 
41  /// Returns the value of the second B-spline basis function
42  static double B1(double);
43 
44  /// Returns the value of the third B-spline basis function
45  static double B2(double);
46 
47  /// Returns the value of the fourth B-spline basis function
48  static double B3(double);
49 
50  /// Returns the 1st derivative value of the first B-spline basis function
51  static double B0_I(double);
52 
53  /// Returns the 1st derivative value of the second B-spline basis function
54  static double B1_I(double);
55 
56  /// Returns the 1st derivative value of the third B-spline basis function
57  static double B2_I(double);
58 
59  /// Returns the 1st derivative value of the fourth B-spline basis function
60  static double B3_I(double);
61 
62  /// Returns the 2nd derivative value of the first B-spline basis function
63  static double B0_II(double);
64 
65  /// Returns the 2nd derivative value of the second B-spline basis function
66  static double B1_II(double);
67 
68  /// Returns the 2nd derivative value of the third B-spline basis function
69  static double B2_II(double);
70 
71  /// Returns the 2nd derivative value of the fourth B-spline basis function
72  static double B3_II(double);
73 
74  /// Subdivide FFD in 2D
75  virtual void Subdivide2D();
76 
77  /// Subdivide FFD in 3D
78  virtual void Subdivide3D();
79 
80  /// Initialize anti-causal coefficients
81  static double InitialAntiCausalCoefficient(double *, int, double z);
82 
83  /// Initialize causal coefficients
84  static double InitialCausalCoefficient(double *, int, double, double);
85 
86  /** Convert from displacement field values to B-spline coefficient values. */
87  static void ConvertToInterpolationCoefficients(double* c, int DataLength, double* z, int NbPoles, double Tolerance);
88 
89  /** Computes the B-spline coefficients needed to interpolate a bias
90  field. */
91  void ComputeCoefficients(double* dbias, RealImage& coeffs);
92 
93  /// Memory for lookup table for B-spline basis function values
94  static double LookupTable[BIASLOOKUPTABLESIZE][4];
95 
96  /* Memory for lookup table for first derivatives of B-spline basis
97  * function values */
98  static double LookupTable_I[BIASLOOKUPTABLESIZE][4];
99 
100  /* Memory for lookup table for second derivatives of B-spline basis
101  * function values */
102  static double LookupTable_II[BIASLOOKUPTABLESIZE][4];
103 
104 public:
105 
106  /// Returns the value of the i-th B-spline basis function with segment dependent parameter
107  static double B (int, double);
108 
109  /// Returns the value of the i-th B-spline basis function with global parameter
110  static double N(int i, double u, int L);
111 
112  /// Returns the 1st derivative value of the i-th B-spline basis function
113  static double B_I(int, double);
114 
115  /// Returns the 2nd derivative value of the i-th B-spline basis function
116  static double B_II(int, double);
117 
118  /// Constructor
119  BSplineBiasField();
120 
121  /// Constructor
122  BSplineBiasField(const GreyImage &image, double dx, double dy, double dz);
123 
124  /// Contructor
125  BSplineBiasField(const GreyImage &image, int x, int y, int z, bool bounding_box = false, int padding = -1);
126 
127  /// Copy Constructor
128  BSplineBiasField(const class BSplineBiasField &);
129 
130  /// Destructor
131  virtual ~BSplineBiasField();
132 
133  /// Returns the size of the B-spline lookup table
134  virtual int LUTSize() const;
135 
136  /** Approximate displacements: This function takes a set of points and a
137  set of displacements and find a FFD which approximates these
138  displacements. After approximatation the displacements replaced by
139  the residual displacement errors at the points */
140  virtual double Approximate(double *, double *, double *, double *, int);
141 
142  /// Calculate weighted least square fit of B-spline to data
143  virtual void WeightedLeastSquares(double *x1, double *y1, double *z1, double *bias, double *weights, int no);
144 
145  /** Interpolates displacements: This function takes a set of displacements
146  defined at the control points and finds a FFD which interpolates these
147  displacements.
148  \param dbias The bias at each control point. */
149  virtual void Interpolate(double* dbias);
150 
151  /// Subdivide FFD
152  virtual void Subdivide();
153 
154  /// Calculates the bias (for a point in FFD coordinates) with checks
155  virtual double FFD1(double, double, double) const;
156 
157  /// Calculates the bias (for a point in FFD coordinates) without checks
158  virtual double FFD2(double, double, double) const;
159 
160  /// Calculates the bias
161  virtual double Bias(double, double, double);
162 
163  /// Calculates the bias
164  virtual double Bias2(double, double, double);
165 
166  /// Reads FFD from file
167  virtual void Read (char *);
168 
169  /// Writes FFD to file
170  virtual void Write(char *);
171 
172  /// Print info
173  virtual void Print();
174 
175  /// Find index in matrix for calculating least square fit
176  virtual int Ind(int, int, int);
177 };
178 
179 inline int BSplineBiasField::Ind(int a, int b, int c)
180 {
181  if(a<0) return -1;
182  if(b<0) return -1;
183  if(c<0) return -1;
184  if(a>_x-1) return -1;
185  if(b>_y-1) return -1;
186  if(c>_z-1) return -1;
187 
188  return a+b*_x+c*_y*_x;
189 }
190 
191 inline double BSplineBiasField::B(int i, double t)
192 {
193  switch (i) {
194  case 0:
195  return (1-t)*(1-t)*(1-t)/6.0;
196  case 1:
197  return (3*t*t*t - 6*t*t + 4)/6.0;
198  case 2:
199  return (-3*t*t*t + 3*t*t + 3*t + 1)/6.0;
200  case 3:
201  return (t*t*t)/6.0;
202  }
203  return 0;
204 }
205 
206 /*inline double BSplineBiasField::N(int i, double u, int L)
207 {
208  if((i<0)||(i>L-1)) return 0;
209  if((u<0)||(u>L-1)) return 0;
210  int l= (int) floor(u);
211  if(l==L-1) l=L-2;
212  double t = u-l;
213  double t3=t*t*t, t2=t*t;
214 
215  if((l==0)&&(L>3))
216  {
217  switch (i-l+1) {
218  case 0:
219  return 0;
220  case 1:
221  return (9*t3 - 18*t2 + 12)/12.0;
222  case 2:
223  return (-11*t3 + 18*t2 )/12.0;
224  case 3:
225  return (t3)/6.0;
226  }
227  return 0;
228  }
229 
230  if((l==1)&&(L>4))
231  {
232  switch (i-l+1) {
233  case 0:
234  return (-3*t3 + 9*t2 -9*t +3)/12.0;
235  case 1:
236  return (7*t3 - 15*t2 + 3*t +7)/12.0;
237  case 2:
238  return (-6*t3 + 6*t2 + 6*t + 2 )/12.0;
239  case 3:
240  return (t3)/6.0;
241  }
242  return 0;
243  }
244 
245  if((l==L-2)&&(L>3))
246  {
247  switch (i-l+1) {
248  case 0:
249  return (-2*t3 + 6*t2 -6*t + 2)/12.0;;
250  case 1:
251  return (11*t3 - 15*t2 -3*t + 7)/12.0;
252  case 2:
253  return (-9*t3 + 9*t2 + 9*t + 3)/12.0;
254  case 3:
255  return 0;
256  }
257  return 0;
258  }
259 
260  if((l==L-3)&&(L>4))
261  {
262  switch (i-l+1) {
263  case 0:
264  return (-2*t3 + 6*t2 -6*t + 2)/12.0;;
265  case 1:
266  return (6*t3 - 12*t2 + 8)/12.0;
267  case 2:
268  return (-7*t3 + 6*t2 + 6*t + 2)/12.0;
269  case 3:
270  return (3*t3)/12.0;
271  }
272  return 0;
273  }
274  if((l==1)&&(L==4))
275  {
276  switch (i-l+1) {
277  case 0:
278  return (-3*t3 + 9*t2 -9*t + 3)/12.0;
279  case 1:
280  return (7*t3 - 15*t2 +3*t + 7)/12.0;
281  case 2:
282  return (-7*t3 + 6*t2 + 6*t + 2)/12.0;
283  case 3:
284  return (3*t3)/12.0;
285  }
286  return 0;
287  }
288 
289  if((l==0)&&(L==3))
290  {
291  switch (i-l+1) {
292  case 0:
293  return 0;
294  case 1:
295  return (3*t3 - 6*t2 + 4)/4.0;
296  case 2:
297  return (-4*t3 + 6*t2 )/4.0;
298  case 3:
299  return (t3)/4.0;
300  }
301  return 0;
302  }
303 
304  if((l==1)&&(L==3))
305  {
306  switch (i-l+1) {
307  case 0:
308  return (-1*t3 + 3*t2 - 3*t + 1)/4.0;
309  case 1:
310  return (4*t3 - 6*t2 + 2)/4.0;
311  case 2:
312  return (-3*t3 + 3*t2 + 3*t + 1)/4.0;
313  case 3:
314  return 0;
315  }
316  return 0;
317  }
318 
319  if((l==0)&&(L==2))
320  {
321  switch (i-l+1) {
322  case 0:
323  return 0;
324  case 1:
325  return 2*t3 - 3*t2 + 1;
326  case 2:
327  return -2*t3 + 3*t2;
328  case 3:
329  return 0;
330  }
331  return 0;
332  }
333 
334  if((l<L-3)&&(l>1))
335  {
336  switch (i-l+1) {
337  case 0:
338  return (-t3+3*t2-3*t+1)/6.0;
339  case 1:
340  return (3*t3 - 6*t2 + 4)/6.0;
341  case 2:
342  return (-3*t3 + 3*t2 + 3*t + 1)/6.0;
343  case 3:
344  return (t3)/6.0;
345  }
346  return 0;
347  }
348  return 0;
349  }
350  */
351 
352 inline double BSplineBiasField::B_I(int i, double t)
353 {
354  switch (i) {
355  case 0:
356  return -(1-t)*(1-t)/2.0;
357  case 1:
358  return (9*t*t - 12*t)/6.0;
359  case 2:
360  return (-9*t*t + 6*t + 3)/6.0;
361  case 3:
362  return (t*t)/2.0;
363  }
364  return 0;
365 }
366 
367 inline double BSplineBiasField::B_II(int i, double t)
368 {
369  switch (i) {
370  case 0:
371  return 1 - t;
372  case 1:
373  return 3*t - 2;
374  case 2:
375  return -3*t + 1;
376  case 3:
377  return t;
378  }
379  return 0;
380 }
381 
382 inline double BSplineBiasField::B0(double t)
383 {
384  return (1-t)*(1-t)*(1-t)/6.0;
385 }
386 
387 inline double BSplineBiasField::B1(double t)
388 {
389  return (3*t*t*t - 6*t*t + 4)/6.0;
390 }
391 
392 inline double BSplineBiasField::B2(double t)
393 {
394  return (-3*t*t*t + 3*t*t + 3*t + 1)/6.0;
395 }
396 
397 inline double BSplineBiasField::B3(double t)
398 {
399  return (t*t*t)/6.0;
400 }
401 
402 inline double BSplineBiasField::B0_I(double t)
403 {
404  return -(1-t)*(1-t)/2.0;
405 }
406 
407 inline double BSplineBiasField::B1_I(double t)
408 {
409  return (9*t*t - 12*t)/6.0;
410 }
411 
412 inline double BSplineBiasField::B2_I(double t)
413 {
414  return (-9*t*t + 6*t + 3)/6.0;
415 }
416 
417 inline double BSplineBiasField::B3_I(double t)
418 {
419  return (t*t)/2.0;
420 }
421 
422 inline double BSplineBiasField::B0_II(double t)
423 {
424  return 1 - t;
425 }
426 
427 inline double BSplineBiasField::B1_II(double t)
428 {
429  return 3*t - 2;
430 }
431 
432 inline double BSplineBiasField::B2_II(double t)
433 {
434  return -3*t + 1;
435 }
436 
437 inline double BSplineBiasField::B3_II(double t)
438 {
439  return t;
440 }
441 
442 inline int BSplineBiasField::LUTSize() const
443 {
444  return BIASLOOKUPTABLESIZE;
445 }
446 
447 inline double BSplineBiasField::Bias(double x, double y, double z)
448 {
449  double u, v, w;
450 
451  u = x;
452  v = y;
453  w = z;
454 
455  // Convert world coordinates in to FFD coordinates
456  this->WorldToLattice(u, v, w);
457 
458  // Calculate FFD
459  //return this->FFD1(u, v, w);
460  int i,j,k,l,m,n;
461 
462  l = (int)floor(u);
463  m = (int)floor(v);
464  n = (int)floor(w);
465  double value=0;
466  for (k = 0; k < 4; k++){
467  for (j = 0; j < 4; j++){
468  for (i = 0; i < 4; i++){
469  if(((i+l-1)>=0)&&((i+l-1)<_x)&&((j+m-1)>=0)&&((j+m-1)<_y)&&((k+n-1)>=0)&&((k+n-1)<_z))
470  value += N(i+l-1,u,_x) * N(j+m-1,v,_y) * N(k+n-1,w,_z)*_data[k+n-1][j+m-1][i+l-1];
471  }
472  }
473  }
474  return value;
475 
476 }
477 
478 inline double BSplineBiasField::Bias2(double x, double y, double z)
479 {
480  double u, v, w;
481 
482  u = x;
483  v = y;
484  w = z;
485 
486  // Convert world coordinates in to FFD coordinates
487  this->WorldToLattice(u, v, w);
488 
489  // Calculate FFD
490  return this->FFD2(u, v, w);
491 }
492 
493 }
494 
495 #endif
int Read(const char *name, UniquePtr< double[]> &data, int *dtype=nullptr, ImageAttributes *attr=nullptr, void *=nullptr, const char *scalars_name=nullptr, bool cell_data=false)
Read data sequence from any supported input file type.
Definition: IOConfig.h:41
std::ostream & Print(std::ostream &os, T value)
Print single argument to output stream.
Definition: String.h:259