SLAMflex SE  0.1.0
SLAMflex provides detection and tracking of dominant planes for smartphone devices. This plane can then be used to show AR content relative to the plane orientation. The detection of plane is performed in the field of view of the smartphone camera. In subsequent frames it is tracked. The interface returns the plane position and orientation.
derivatives.h
Go to the documentation of this file.
1 #ifndef TOON_INCLUDE_DERIVATIVES_NUMERICAL_H
2 #define TOON_INCLUDE_DERIVATIVES_NUMERICAL_H
3 
4 #include "TooN.h"
5 #include <vector>
6 #include <cmath>
7 
8 using namespace std;
9 using namespace TooN;
10 
11 namespace TooN{
12  namespace Internal{
18  template<class F, class Precision> std::pair<Precision, Precision> extrapolate_to_zero(F& f)
19  {
20  using std::isfinite;
21  using std::max;
22  using std::isnan;
23  //Use points at c^0, c^-1, ... to extrapolate towards zero.
24  const Precision c = 1.1, t = 2;
25 
26  static const int Npts = 400;
27 
28  /* Neville's table is:
29  x_0 y_0 P_0
30  P_{01}
31  x_1 y_1 P_1 P_{012}
32  P_{12} P_{0123}
33  x_2 y_2 P_2 P_{123}
34  P_{23}
35  x_3 y_3 P_3
36 
37  In Matrix form, this is rearranged as:
38 
39 
40  x_0 y_0 P_0
41 
42  x_1 y_1 P_1 P_{01}
43 
44  x_2 y_2 P_2 P_{12} P_{012}
45 
46  x_3 y_3 P_3 P_{23} P_{123} P_{0123}
47 
48  This is rewritten further as:
49 
50  | 0 1 2 3
51  _____|___________________________________________________
52  0 | x_0 y_0 P^00
53  |
54  1 | x_1 y_1 P^10 P^11
55  |
56  2 | x_2 y_2 P^10 P^21 P^22
57  |
58  3 | x_3 y_3 P^10 P^31 P^23 P^33
59 
60  So, P^ij == P_{j-i...j}
61 
62  Finally, only the current and previous row are required. This reduces
63  the memory cost from quadratic to linear. The naming scheme is:
64 
65  P[i][j] -> P_i[j]
66  P[i-1][j] -> P_i_1[j]
67  */
68 
69  vector<Precision> P_i(1), P_i_1;
70 
71  Precision best_err = HUGE_VAL;
72  Precision best_point=HUGE_VAL;
73 
74  //The first tranche of points might be bad.
75  //Don't quit while no good points have ever happened.
76  bool ever_ok=0;
77 
78  //Compute f(x) as x goes from 1 towards zero and extrapolate to 0
79  Precision x=1;
80  for(int i=0; i < Npts; i++)
81  {
82  swap(P_i, P_i_1);
83  P_i.resize(i+2);
84 
85 
86  //P[i][0] = c^ -i;
87  P_i[0] = f(x);
88 
89  x /= c;
90 
91  //Compute the extrapolations
92  //cj id c^j
93  Precision cj = 1;
94  bool better=0; //Did we get better?
95  bool any_ok=0;
96  for(int j=1; j <= i; j++)
97  {
98  cj *= c;
99  //We have (from above) n = i and k = n - j
100  //n-k = i - (n - j) = i - i + j = j
101  //Therefore c^(n-k) is just c^j
102 
103  P_i[j] = (cj * P_i[j-1] - P_i_1[j-1]) / (cj - 1);
104 
105  if(any_ok || isfinite(P_i[j]))
106  ever_ok = 1;
107 
108  //Compute the difference between the current point (high order)
109  //and the corresponding lower order point at the current step size
110  Precision err1 = abs(P_i[j] - P_i[j-1]);
111 
112  //Compute the difference between two consecutive points at the
113  //corresponding lower order point at the larger stepsize
114  Precision err2 = abs(P_i[j] - P_i_1[j-1]);
115 
116  //The error is the larger of these.
117  Precision err = max(err1, err2);
118 
119  if(err < best_err && isfinite(err))
120  {
121  best_err = err;
122  best_point = P_i[j];
123  better=1;
124  }
125  }
126 
127  using namespace std;
128  //If the highest order point got worse, or went off the rails,
129  //and some good points have been seen, then break.
130  if(ever_ok && !better && i > 0 && (abs(P_i[i] - P_i_1[i-1]) > t * best_err|| isnan(P_i[i])))
131  break;
132  }
133 
134  return std::make_pair(best_point, best_err);
135  }
136 
140  template<class Functor, class Precision, int Size, class Base> struct CentralDifferenceGradient
141  {
144  const Functor& f;
145  int i;
146 
148  :v(v_),x(v),f(f_),i(0)
149  {}
150 
152  Precision operator()(Precision hh)
153  {
154  using std::max;
155  using std::abs;
156 
157  //Make the step size be on the scale of the value.
158  double h = hh * max(abs(v[i]) * 1e-3, 1e-3);
159 
160  x[i] = v[i] - h;
161  double f1 = f(x);
162  x[i] = v[i] + h;
163  double f2 = f(x);
164  x[i] = v[i];
165 
166  double d = (f2 - f1) / (2*h);
167  return d;
168  }
169  };
170 
174  template<class Functor, class Precision, int Size, class Base> struct CentralDifferenceSecond
175  {
178  const Functor& f;
179  int i;
180  const Precision central;
181 
183  :v(v_),x(v),f(f_),i(0),central(f(x))
184  {}
185 
187  Precision operator()(Precision hh)
188  {
189  using std::max;
190  using std::abs;
191 
192  //Make the step size be on the scale of the value.
193  double h = hh * max(abs(v[i]) * 1e-3, 1e-3);
194 
195  x[i] = v[i] - h;
196  double f1 = f(x);
197 
198  x[i] = v[i] + h;
199  double f2 = f(x);
200  x[i] = v[i];
201 
202  double d = (f2 - 2*central + f1) / (h*h);
203  return d;
204  }
205  };
206 
210  template<class Functor, class Precision, int Size, class Base> struct CentralCrossDifferenceSecond
211  {
214  const Functor& f;
215  int i;
216  int j;
217 
219  :v(v_),x(v),f(f_),i(0),j(0)
220  {}
221 
223  Precision operator()(Precision hh)
224  {
225  using std::max;
226  using std::abs;
227 
228  //Make the step size be on the scale of the value.
229  double h = hh * max(abs(v[i]) * 1e-3, 1e-3);
230 
231  x[i] = v[i] + h;
232  x[j] = v[j] + h;
233  double a = f(x);
234 
235  x[i] = v[i] - h;
236  x[j] = v[j] + h;
237  double b = f(x);
238 
239  x[i] = v[i] + h;
240  x[j] = v[j] - h;
241  double c = f(x);
242 
243 
244  x[i] = v[i] - h;
245  x[j] = v[j] - h;
246  double d = f(x);
247 
248  return (a-b-c+d) / (4*h*h);
249  }
250  };
251 
252  }
253 
254 
326  template<class F, int S, class P, class B> Vector<S, P> numerical_gradient(const F& f, const Vector<S, P, B>& x)
327  {
328  using namespace Internal;
329  Vector<S> grad(x.size());
330 
331  CentralDifferenceGradient<F, P, S, B> d(x, f);
332 
333  for(int i=0; i < x.size(); i++)
334  {
335  d.i = i;
336  grad[i] = extrapolate_to_zero<CentralDifferenceGradient<F, P, S, B>, P>(d).first;
337  }
338 
339  return grad;
340  }
341 
350  template<class F, int S, class P, class B> Matrix<S,2,P> numerical_gradient_with_errors(const F& f, const Vector<S, P, B>& x)
351  {
352  using namespace Internal;
353  Matrix<S,2> g(x.size(), 2);
354 
355  CentralDifferenceGradient<F, P, S, B> d(x, f);
356 
357  for(int i=0; i < x.size(); i++)
358  {
359  d.i = i;
360  pair<double, double> r= extrapolate_to_zero<CentralDifferenceGradient<F, P, S, B>, P>(d);
361  g[i][0] = r.first;
362  g[i][1] = r.second;
363  }
364 
365  return g;
366  }
367 
368 
380  template<class F, int S, class P, class B> pair<Matrix<S, S, P>, Matrix<S, S, P> > numerical_hessian_with_errors(const F& f, const Vector<S, P, B>& x)
381  {
382  using namespace Internal;
383  Matrix<S> hess(x.size(), x.size());
384  Matrix<S> errors(x.size(), x.size());
385 
386  CentralDifferenceSecond<F, P, S, B> curv(x, f);
387  CentralCrossDifferenceSecond<F, P, S, B> cross(x, f);
388 
389  //Perform the cross differencing.
390 
391  for(int r=0; r < x.size(); r++)
392  for(int c=r+1; c < x.size(); c++)
393  {
394  cross.i = r;
395  cross.j = c;
396  pair<double, double> e = extrapolate_to_zero<CentralCrossDifferenceSecond<F, P, S, B>, P >(cross);
397  hess[r][c] = hess[c][r] = e.first;
398  errors[r][c] = errors[c][r] = e.second;
399  }
400 
401  for(int i=0; i < x.size(); i++)
402  {
403  curv.i = i;
404  pair<double, double> e = extrapolate_to_zero<CentralDifferenceSecond<F, P, S, B>, P>(curv);
405  hess[i][i] = e.first;
406  errors[i][i] = e.second;
407  }
408 
409  return make_pair(hess, errors);
410  }
411 
418  template<class F, int S, class P, class B> Matrix<S, S, P> numerical_hessian(const F& f, const Vector<S, P, B>& x)
419  {
420  using namespace Internal;
421  Matrix<S> hess(x.size(), x.size());
422 
423  CentralDifferenceSecond<F, P, S, B> curv(x, f);
424  CentralCrossDifferenceSecond<F, P, S, B> cross(x, f);
425 
426  //Perform the cross differencing.
427  for(int r=0; r < x.size(); r++)
428  for(int c=r+1; c < x.size(); c++)
429  {
430  cross.i = r;
431  cross.j = c;
432  pair<double, double> e = extrapolate_to_zero<CentralCrossDifferenceSecond<F, P, S, B>, P >(cross);
433  hess[r][c] = hess[c][r] = e.first;
434  }
435 
436  for(int i=0; i < x.size(); i++)
437  {
438  curv.i = i;
439  pair<double, double> e = extrapolate_to_zero<CentralDifferenceSecond<F, P, S, B>, P>(curv);
440  hess[i][i] = e.first;
441  }
442 
443  return hess;
444  }
445 }
446 
447 #endif
448 
Vector< Size, Precision > x
Local copy of v.
Definition: derivatives.h:177
std::pair< Precision, Precision > extrapolate_to_zero(F &f)
Definition: derivatives.h:18
int i
Index to difference along.
Definition: derivatives.h:145
const Functor & f
Functor to evaluate.
Definition: derivatives.h:144
Everything lives inside this namespace.
Definition: allocator.hh:48
CentralDifferenceGradient(const Vector< Size, Precision, Base > &v_, const Functor &f_)
Definition: derivatives.h:147
bool isfinite(const Vector< S, P, B > &v)
Definition: helpers.h:297
Precision operator()(Precision hh)
Compute central difference.
Definition: derivatives.h:187
CentralCrossDifferenceSecond(const Vector< Size, Precision, Base > &v_, const Functor &f_)
Definition: derivatives.h:218
const Vector< Size, Precision, Base > & v
Point about which to compute differences.
Definition: derivatives.h:212
Vector< S, P > numerical_gradient(const F &f, const Vector< S, P, B > &x)
Definition: derivatives.h:326
T abs(T t)
Definition: abs.h:30
Precision operator()(Precision hh)
Compute central difference.
Definition: derivatives.h:152
Precision operator()(Precision hh)
Compute central difference.
Definition: derivatives.h:223
Matrix< S, S, P > numerical_hessian(const F &f, const Vector< S, P, B > &x)
Definition: derivatives.h:418
Vector< Size, Precision > x
Local copy of v.
Definition: derivatives.h:143
const Vector< Size, Precision, Base > & v
Point about which to compute differences.
Definition: derivatives.h:176
int i
Index to difference along.
Definition: derivatives.h:215
int j
Index to difference along.
Definition: derivatives.h:216
pair< Matrix< S, S, P >, Matrix< S, S, P > > numerical_hessian_with_errors(const F &f, const Vector< S, P, B > &x)
Definition: derivatives.h:380
CentralDifferenceSecond(const Vector< Size, Precision, Base > &v_, const Functor &f_)
Definition: derivatives.h:182
const Functor & f
Functor to evaluate.
Definition: derivatives.h:178
int i
Index to difference along.
Definition: derivatives.h:179
const Precision central
Central point.
Definition: derivatives.h:180
const Vector< Size, Precision, Base > & v
Point about which to compute differences.
Definition: derivatives.h:142
Vector< Size, Precision > x
Local copy of v.
Definition: derivatives.h:213
Matrix< S, 2, P > numerical_gradient_with_errors(const F &f, const Vector< S, P, B > &x)
Definition: derivatives.h:350
const Functor & f
Functor to evaluate.
Definition: derivatives.h:214
bool isnan(const Vector< S, P, B > &v)
Definition: helpers.h:308