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.
GR_SVD.h
Go to the documentation of this file.
1 // -*- c++ -*-
2 
3 // Copyright (C) 2009 Georg Klein (gk@robots.ox.ac.uk)
4 //
5 // This file is part of the TooN Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING. If not, write to the Free
18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 // USA.
20 
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction. Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License. This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
29 
30 #ifndef __GR_SVD_H
31 #define __GR_SVD_H
32 
33 #include "TooN.h"
34 #include <cmath>
35 #include <vector>
36 #include <algorithm>
37 
38 namespace TooN
39 {
40 
59  template<int M, int N, class Precision = DefaultPrecision, bool WANT_U = 1, bool WANT_V = 1>
60  class GR_SVD
61  {
62  public:
63 
64  template<class Precision2, class Base> GR_SVD(const Matrix<M, N, Precision2, Base> &A);
65 
66  static const int BigDim = M>N?M:N;
67  static const int SmallDim = M<N?M:N;
68 
69  const Matrix<M,N,Precision>& get_U() { if(!WANT_U) throw(0); return mU;}
70  const Matrix<N,N,Precision>& get_V() { if(!WANT_V) throw(0); return mV;}
72 
73  Precision get_largest_singular_value();
74  Precision get_smallest_singular_value();
76 
82  void get_inv_diag(Vector<N>& inv_diag, const Precision condition)
83  {
84  Precision dMax = get_largest_singular_value();
85  for(int i=0; i<N; ++i)
86  inv_diag[i] = (vDiagonal[i] * condition > dMax) ?
87  static_cast<Precision>(1)/vDiagonal[i] : 0;
88  }
89 
94  template <int Rows2, int Cols2, typename P2, typename B2>
96  backsub(const Matrix<Rows2,Cols2,P2,B2>& rhs, const Precision condition=1e9)
97  {
98  Vector<N,Precision> inv_diag;
99  get_inv_diag(inv_diag,condition);
100  return (get_V() * diagmult(inv_diag, (get_U().T() * rhs)));
101  }
102 
107  template <int Size, typename P2, typename B2>
109  backsub(const Vector<Size,P2,B2>& rhs, const Precision condition=1e9)
110  {
111  Vector<N,Precision> inv_diag;
112  get_inv_diag(inv_diag,condition);
113  return (get_V() * diagmult(inv_diag, (get_U().T() * rhs)));
114  }
115 
117  Matrix<N,M,Precision> get_pinv(const Precision condition=1e9)
118  {
119  Vector<N,Precision> inv_diag(N);
120  get_inv_diag(inv_diag,condition);
121  return diagmult(get_V(),inv_diag) * get_U().T();
122  }
123 
125  void reorder();
126 
127  protected:
128  void Bidiagonalize();
129  void Accumulate_RHS();
130  void Accumulate_LHS();
131  void Diagonalize();
132  bool Diagonalize_SubLoop(int k, Precision &z);
133 
138 
139  int nError;
141  Precision anorm;
142  };
143 
144 
145 
146  template<int M, int N, class Precision, bool WANT_U, bool WANT_V>
147  template<class Precision2, class Base>
149  {
150  nError = 0;
151  mU = mA;
152  Bidiagonalize();
153  Accumulate_RHS();
154  Accumulate_LHS();
155  Diagonalize();
156  };
157 
158  template<int M, int N, class Precision, bool WANT_U, bool WANT_V>
160  {
161  using std::abs;
162  using std::max;
163  // ------------ Householder reduction to bidiagonal form
164  Precision g = 0.0;
165  Precision scale = 0.0;
166  anorm = 0.0;
167  for(int i=0; i<N; ++i) // 300
168  {
169  const int l = i+1;
170  vOffDiagonal[i] = scale * g;
171  g = 0.0;
172  Precision s = 0.0;
173  scale = 0.0;
174  if( i < M )
175  {
176  for(int k=i; k<M; ++k)
177  scale += abs(mU[k][i]);
178  if(scale != 0.0)
179  {
180  for(int k=i; k<M; ++k)
181  {
182  mU[k][i] /= scale;
183  s += mU[k][i] * mU[k][i];
184  }
185  Precision f = mU[i][i];
186  g = -(f>=0?sqrt(s):-sqrt(s));
187  Precision h = f * g - s;
188  mU[i][i] = f - g;
189  if(i!=(N-1))
190  {
191  for(int j=l; j<N; ++j)
192  {
193  s = 0.0;
194  for(int k=i; k<M; ++k)
195  s += mU[k][i] * mU[k][j];
196  f = s / h;
197  for(int k=i; k<M; ++k)
198  mU[k][j] += f * mU[k][i];
199  } // 150
200  }// 190
201  for(int k=i; k<M; ++k)
202  mU[k][i] *= scale;
203  } // 210
204  } // 210
205  vDiagonal[i] = scale * g;
206  g = 0.0;
207  s = 0.0;
208  scale = 0.0;
209  if(!(i >= M || i == (N-1)))
210  {
211  for(int k=l; k<N; ++k)
212  scale += abs(mU[i][k]);
213  if(scale != 0.0)
214  {
215  for(int k=l; k<N; k++)
216  {
217  mU[i][k] /= scale;
218  s += mU[i][k] * mU[i][k];
219  }
220  Precision f = mU[i][l];
221  g = -(f>=0?sqrt(s):-sqrt(s));
222  Precision h = f * g - s;
223  mU[i][l] = f - g;
224  for(int k=l; k<N; ++k)
225  vOffDiagonal[k] = mU[i][k] / h;
226  if(i != (M-1)) // 270
227  {
228  for(int j=l; j<M; ++j)
229  {
230  s = 0.0;
231  for(int k=l; k<N; ++k)
232  s += mU[j][k] * mU[i][k];
233  for(int k=l; k<N; ++k)
234  mU[j][k] += s * vOffDiagonal[k];
235  } // 260
236  } // 270
237  for(int k=l; k<N; ++k)
238  mU[i][k] *= scale;
239  } // 290
240  } // 290
241  anorm = max(anorm, abs(vDiagonal[i]) + abs(vOffDiagonal[i]));
242  } // 300
243 
244  // Accumulation of right-hand transformations
245  }
246 
247  template<int M, int N, class Precision, bool WANT_U, bool WANT_V>
249  {
250  // Get rid of fakey loop over ii, do a loop over i directly
251  // This here would happen on the first run of the loop with
252  // i = N-1
253  mV[N-1][N-1] = static_cast<Precision>(1);
254  Precision g = vOffDiagonal[N-1];
255 
256  // The loop
257  for(int i=N-2; i>=0; --i) // 400
258  {
259  const int l = i + 1;
260  if( g!=0) // 360
261  {
262  for(int j=l; j<N; ++j)
263  mV[j][i] = (mU[i][j] / mU[i][l]) / g; // double division avoids possible underflow
264  for(int j=l; j<N; ++j)
265  { // 350
266  Precision s = 0;
267  for(int k=l; k<N; ++k)
268  s += mU[i][k] * mV[k][j];
269  for(int k=l; k<N; ++k)
270  mV[k][j] += s * mV[k][i];
271  } // 350
272  } // 360
273  for(int j=l; j<N; ++j)
274  mV[i][j] = mV[j][i] = 0;
275  mV[i][i] = static_cast<Precision>(1);
276  g = vOffDiagonal[i];
277  } // 400
278  }
279 
280  template<int M, int N, class Precision, bool WANT_U, bool WANT_V>
282  {
283  // Same thing; remove loop over dummy ii and do straight over i
284  // Some implementations start from N here (??)
285  for(int i=SmallDim-1; i>=0; --i)
286  { // 500
287  const int l = i+1;
288  Precision g = vDiagonal[i];
289  // SqSVD here uses i<N ?
290  if(i != (N-1))
291  for(int j=l; j<N; ++j)
292  mU[i][j] = 0.0;
293  if(g == 0.0)
294  for(int j=i; j<M; ++j)
295  mU[j][i] = 0.0;
296  else
297  { // 475
298  // Can pre-divide g here
299  Precision inv_g = static_cast<Precision>(1) / g;
300  if(i != (SmallDim-1))
301  { // 460
302  for(int j=l; j<N; ++j)
303  { // 450
304  Precision s = 0;
305  for(int k=l; k<M; ++k)
306  s += mU[k][i] * mU[k][j];
307  Precision f = (s / mU[i][i]) * inv_g; // double division
308  for(int k=i; k<M; ++k)
309  mU[k][j] += f * mU[k][i];
310  } // 450
311  } // 460
312  for(int j=i; j<M; ++j)
313  mU[j][i] *= inv_g;
314  } // 475
315  mU[i][i] += static_cast<Precision>(1);
316  } // 500
317  }
318 
319  template<int M, int N, class Precision,bool WANT_U, bool WANT_V>
321  {
322  // Loop directly over descending k
323  for(int k=N-1; k>=0; --k)
324  { // 700
325  nIterations = 0;
326  Precision z;
327  bool bConverged_Or_Error = false;
328  do
329  bConverged_Or_Error = Diagonalize_SubLoop(k, z);
330  while(!bConverged_Or_Error);
331 
332  if(nError)
333  return;
334 
335  if(z < 0)
336  {
337  vDiagonal[k] = -z;
338  if(WANT_V)
339  for(int j=0; j<N; ++j)
340  mV[j][k] = -mV[j][k];
341  }
342  } // 700
343  };
344 
345 
346  template<int M, int N, class Precision, bool WANT_U, bool WANT_V>
348  {
349  using std::abs;
350  const int k1 = k-1;
351  // 520 is here!
352  for(int l=k; l>=0; --l)
353  { // 530
354  const int l1 = l-1;
355  const bool rv1_test = ((abs(vOffDiagonal[l]) + anorm) == anorm);
356  const bool w_test = ((abs(vDiagonal[l1]) + anorm) == anorm);
357  if(!rv1_test && w_test) // 540 to 565
358  {
359  Precision c = 0;
360  Precision s = 1.0;
361  for(int i=l; i<=k; ++i)
362  { // 560
363  Precision f = s * vOffDiagonal[i];
364  vOffDiagonal[i] *= c;
365  if((abs(f) + anorm) == anorm)
366  break; // goto 565, effectively
367  Precision g = vDiagonal[i];
368  Precision h = sqrt(f * f + g * g); // Other implementations do this bit better
369  vDiagonal[i] = h;
370  c = g / h;
371  s = -f / h;
372  if(WANT_U)
373  for(int j=0; j<M; ++j)
374  {
375  Precision y = mU[j][l1];
376  Precision z = mU[j][i];
377  mU[j][l1] = y*c + z*s;
378  mU[j][i] = -y*s + z*c;
379  }
380  } // 560
381  }
382  if(rv1_test || w_test) // line 565
383  {
384  // Check for convergence..
385  z = vDiagonal[k];
386  if(l == k)
387  return true; // convergence.
388  if(nIterations == 30)
389  {
390  nError = k;
391  return true;
392  }
393  ++nIterations;
394  Precision x = vDiagonal[l];
395  Precision y = vDiagonal[k1];
396  Precision g = vOffDiagonal[k1];
397  Precision h = vOffDiagonal[k];
398  Precision f = ((y-z)*(y+z) + (g-h)*(g+h)) / (2.0*h*y);
399  g = sqrt(f*f + 1.0);
400  Precision signed_g = (f>=0)?g:-g;
401  f = ((x-z)*(x+z) + h*(y/(f + signed_g) - h)) / x;
402 
403  // Next QR transformation
404  Precision c = 1.0;
405  Precision s = 1.0;
406  for(int i1 = l; i1<=k1; ++i1)
407  { // 600
408  const int i=i1+1;
409  g = vOffDiagonal[i];
410  y = vDiagonal[i];
411  h = s*g;
412  g = c*g;
413  z = sqrt(f*f + h*h);
414  vOffDiagonal[i1] = z;
415  c = f/z;
416  s = h/z;
417  f = x*c + g*s;
418  g = -x*s + g*c;
419  h = y*s;
420  y *= c;
421  if(WANT_V)
422  for(int j=0; j<N; ++j)
423  {
424  Precision xx = mV[j][i1];
425  Precision zz = mV[j][i];
426  mV[j][i1] = xx*c + zz*s;
427  mV[j][i] = -xx*s + zz*c;
428  }
429  z = sqrt(f*f + h*h);
430  vDiagonal[i1] = z;
431  if(z!=0)
432  {
433  c = f/z;
434  s = h/z;
435  }
436  f = c*g + s*y;
437  x = -s*g + c*y;
438  if(WANT_U)
439  for(int j=0; j<M; ++j)
440  {
441  Precision yy = mU[j][i1];
442  Precision zz = mU[j][i];
443  mU[j][i1] = yy*c + zz*s;
444  mU[j][i] = -yy*s + zz*c;
445  }
446  } // 600
447  vOffDiagonal[l] = 0;
448  vOffDiagonal[k] = f;
449  vDiagonal[k] = x;
450  return false;
451  // EO IF NOT CONVERGED CHUNK
452  } // EO IF TESTS HOLD
453  } // 530
454  // Code should never get here!
455  throw(0);
456  return false;
457  }
458 
459 
460  template<int M, int N, class Precision, bool WANT_U, bool WANT_V>
462  {
463  using std::max;
464  Precision d = vDiagonal[0];
465  for(int i=1; i<N; ++i) d = max(d, vDiagonal[i]);
466  return d;
467  }
468 
469  template<int M, int N, class Precision, bool WANT_U, bool WANT_V>
471  {
472  using std::min;
473  Precision d = vDiagonal[0];
474  for(int i=1; i<N; ++i) d = min(d, vDiagonal[i]);
475  return d;
476  }
477 
478  template<int M, int N, class Precision, bool WANT_U, bool WANT_V>
480  {
481  using std::min;
482  int nMin=0;
483  Precision d = vDiagonal[0];
484  for(int i=1; i<N; ++i)
485  if(vDiagonal[i] < d)
486  {
487  d = vDiagonal[i];
488  nMin = i;
489  }
490  return nMin;
491  }
492 
493  template<int M, int N, class Precision, bool WANT_U, bool WANT_V>
495  {
496  std::vector<std::pair<Precision, unsigned int> > vSort;
497  vSort.reserve(N);
498  for(unsigned int i=0; i<N; ++i)
499  vSort.push_back(std::make_pair(-vDiagonal[i], i));
500  std::sort(vSort.begin(), vSort.end());
501  for(unsigned int i=0; i<N; ++i)
502  vDiagonal[i] = -vSort[i].first;
503  if(WANT_U)
504  {
505  Matrix<M, N, Precision> mU_copy = mU;
506  for(unsigned int i=0; i<N; ++i)
507  mU.T()[i] = mU_copy.T()[vSort[i].second];
508  }
509  if(WANT_V)
510  {
511  Matrix<N, N, Precision> mV_copy = mV;
512  for(unsigned int i=0; i<N; ++i)
513  mV.T()[i] = mV_copy.T()[vSort[i].second];
514  }
515  }
516 
517 }
518 #endif
519 
520 
521 
522 
523 
524 
Vector< BigDim, Precision > vOffDiagonal
Definition: GR_SVD.h:135
static const int BigDim
Definition: GR_SVD.h:66
Matrix< N, M, Precision > get_pinv(const Precision condition=1e9)
Get the pseudo-inverse .
Definition: GR_SVD.h:117
Precision anorm
Definition: GR_SVD.h:141
static const int SmallDim
Definition: GR_SVD.h:67
Everything lives inside this namespace.
Definition: allocator.hh:48
void Accumulate_RHS()
Definition: GR_SVD.h:248
void reorder()
Reorder the components so the singular values are in descending order.
Definition: GR_SVD.h:494
int nIterations
Definition: GR_SVD.h:140
Matrix< N, Cols2, typename Internal::MultiplyType< Precision, P2 >::type > backsub(const Matrix< Rows2, Cols2, P2, B2 > &rhs, const Precision condition=1e9)
Definition: GR_SVD.h:96
Precision get_smallest_singular_value()
Definition: GR_SVD.h:470
T abs(T t)
Definition: abs.h:30
void get_inv_diag(Vector< N > &inv_diag, const Precision condition)
Definition: GR_SVD.h:82
const Matrix< N, N, Precision > & get_V()
Definition: GR_SVD.h:70
int get_smallest_singular_value_index()
Definition: GR_SVD.h:479
bool Diagonalize_SubLoop(int k, Precision &z)
Definition: GR_SVD.h:347
Matrix< M, N, Precision > mU
Definition: GR_SVD.h:136
GR_SVD(const Matrix< M, N, Precision2, Base > &A)
Definition: GR_SVD.h:148
const Matrix< M, N, Precision > & get_U()
Definition: GR_SVD.h:69
void Accumulate_LHS()
Definition: GR_SVD.h:281
Matrix< N, N, Precision > mV
Definition: GR_SVD.h:137
Precision get_largest_singular_value()
Definition: GR_SVD.h:461
Vector< N, typename Internal::MultiplyType< Precision, P2 >::type > backsub(const Vector< Size, P2, B2 > &rhs, const Precision condition=1e9)
Definition: GR_SVD.h:109
const Vector< N, Precision > & get_diagonal()
Definition: GR_SVD.h:71
int nError
Definition: GR_SVD.h:139
Vector< N, Precision > vDiagonal
Definition: GR_SVD.h:134
void Diagonalize()
Definition: GR_SVD.h:320
void Bidiagonalize()
Definition: GR_SVD.h:159
Vector< Internal::Sizer< S1, S2 >::size, typename Internal::MultiplyType< P1, P2 >::type > diagmult(const Vector< S1, P1, B1 > &v1, const Vector< S2, P2, B2 > &v2)
Definition: operators.hh:149