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.
downhill_simplex.h
Go to the documentation of this file.
1 #ifndef TOON_DOWNHILL_SIMPLEX_H
2 #define TOON_DOWNHILL_SIMPLEX_H
3 #include "TooN.h"
4 #include "helpers.h"
5 #include <algorithm>
6 #include <cstdlib>
7 
8 namespace TooN
9 {
10 
77 template<int N=-1, typename Precision=double> class DownhillSimplex
78 {
79  static const int Vertices = (N==-1?-1:N+1);
82 
83  public:
92  template<class Function> DownhillSimplex(const Function& func, const Vector<N>& c, Precision spread=1)
93  :simplex(c.size()+1, c.size()),values(c.size()+1)
94  {
95  alpha = 1.0;
96  rho = 2.0;
97  gamma = 0.5;
98  sigma = 0.5;
99 
100  epsilon = sqrt(numeric_limits<Precision>::epsilon());
101  zero_epsilon = 1e-20;
102 
103  restart(func, c, spread);
104  }
105 
112  template<class Function> void restart(const Function& func, const Vector<N>& c, Precision spread)
113  {
114  for(int i=0; i < simplex.num_rows(); i++)
115  simplex[i] = c;
116 
117  for(int i=0; i < simplex.num_cols(); i++)
118  simplex[i][i] += spread;
119 
120  for(int i=0; i < values.size(); i++)
121  values[i] = func(simplex[i]);
122  }
123 
129  bool finished()
130  {
131  Precision span = norm(simplex[get_best()] - simplex[get_worst()]);
132  Precision scale = norm(simplex[get_best()]);
133 
134  if(span/scale < epsilon || span < zero_epsilon)
135  return 1;
136  else
137  return 0;
138  }
139 
144  template<class Function> void restart(const Function& func, Precision spread)
145  {
146  restart(func, simplex[get_best()], spread);
147  }
148 
150  const Simplex& get_simplex() const
151  {
152  return simplex;
153  }
154 
156  const Values& get_values() const
157  {
158  return values;
159  }
160 
162  int get_best() const
163  {
164  return std::min_element(&values[0], &values[0] + values.size()) - &values[0];
165  }
166 
168  int get_worst() const
169  {
170  return std::max_element(&values[0], &values[0] + values.size()) - &values[0];
171  }
172 
175  template<class Function> void find_next_point(const Function& func)
176  {
177  //Find various things:
178  // - The worst point
179  // - The second worst point
180  // - The best point
181  // - The centroid of all the points but the worst
182  int worst = get_worst();
183  Precision second_worst_val=-HUGE_VAL, bestval = HUGE_VAL, worst_val = values[worst];
184  int best=0;
185  Vector<N> x0 = Zeros(simplex.num_cols());
186 
187 
188  for(int i=0; i < simplex.num_rows(); i++)
189  {
190  if(values[i] < bestval)
191  {
192  bestval = values[i];
193  best = i;
194  }
195 
196  if(i != worst)
197  {
198  if(values[i] > second_worst_val)
199  second_worst_val = values[i];
200 
201  //Compute the centroid of the non-worst points;
202  x0 += simplex[i];
203  }
204  }
205  x0 *= 1.0 / simplex.num_cols();
206 
207 
208  //Reflect the worst point about the centroid.
209  Vector<N> xr = (1 + alpha) * x0 - alpha * simplex[worst];
210  Precision fr = func(xr);
211 
212  if(fr < bestval)
213  {
214  //If the new point is better than the smallest, then try expanding the simplex.
215  Vector<N> xe = rho * xr + (1-rho) * x0;
216  Precision fe = func(xe);
217 
218  //Keep whichever is best
219  if(fe < fr)
220  {
221  simplex[worst] = xe;
222  values[worst] = fe;
223  }
224  else
225  {
226  simplex[worst] = xr;
227  values[worst] = fr;
228  }
229 
230  return;
231  }
232 
233  //Otherwise, if the new point lies between the other points
234  //then keep it and move on to the next iteration.
235  if(fr < second_worst_val)
236  {
237  simplex[worst] = xr;
238  values[worst] = fr;
239  return;
240  }
241 
242 
243  //Otherwise, if the new point is a bit better than the worst point,
244  //(ie, it's got just a little bit better) then contract the simplex
245  //a bit.
246  if(fr < worst_val)
247  {
248  Vector<N> xc = (1 + gamma) * x0 - gamma * simplex[worst];
249  Precision fc = func(xc);
250 
251  //If this helped, use it
252  if(fc <= fr)
253  {
254  simplex[worst] = xc;
255  values[worst] = fc;
256  return;
257  }
258  }
259 
260  //Otherwise, fr is worse than the worst point, or the fc was worse
261  //than fr. So shrink the whole simplex around the best point.
262  for(int i=0; i < simplex.num_rows(); i++)
263  if(i != best)
264  {
265  simplex[i] = simplex[best] + sigma * (simplex[i] - simplex[best]);
266  values[i] = func(simplex[i]);
267  }
268  }
269 
273  template<class Function> bool iterate(const Function& func)
274  {
275  find_next_point(func);
276  return !finished();
277  }
278 
279  Precision alpha;
280  Precision rho;
281  Precision gamma;
282  Precision sigma;
283  Precision epsilon;
284  Precision zero_epsilon;
285 
286  private:
287 
288  //Each row is a simplex vertex
289  Simplex simplex;
290 
291  //Function values for each vertex
292  Values values;
293 
294 
295 };
296 }
297 #endif
std::pair< Precision, int > min_element(const Vector< Size, Precision, Base > &v)
Definition: helpers.h:709
Vector< Vertices, Precision > Values
const Simplex & get_simplex() const
Return the simplex.
bool iterate(const Function &func)
Precision alpha
Reflected size. Defaults to 1.
Everything lives inside this namespace.
Definition: allocator.hh:48
Matrix< Vertices, N, Precision > Simplex
int get_worst() const
Get the index of the worst vertex.
const Values & get_values() const
Return the score at the vertices.
void restart(const Function &func, const Vector< N > &c, Precision spread)
Precision norm(const Vector< Size, Precision, Base > &v)
Definition: helpers.h:70
static const int Vertices
void restart(const Function &func, Precision spread)
Precision rho
Expansion ratio. Defaults to 2.
Precision gamma
Contraction ratio. Defaults to .5.
Precision sigma
Shrink ratio. Defaults to .5.
std::pair< Precision, int > max_element(const Vector< Size, Precision, Base > &v)
Definition: helpers.h:717
int get_best() const
Get the index of the best vertex.
Precision epsilon
Tolerance used to determine if the optimization is complete. Defaults to square root of machine preci...
void find_next_point(const Function &func)
DownhillSimplex(const Function &func, const Vector< N > &c, Precision spread=1)
static Operator< Internal::Zero > Zeros
Definition: objects.h:727
Precision zero_epsilon
Additive term in tolerance to prevent excessive iterations if . Known as ZEPS in numerical recipies...