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.
SVD.h
Go to the documentation of this file.
1 // -*- c++ -*-
2 
3 // Copyright (C) 2005,2009 Tom Drummond (twd20@cam.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 __SVD_H
31 #define __SVD_H
32 
33 #include "TooN.h"
34 #include "lapack.h"
35 
36 
37 namespace TooN {
38 
39  // TODO - should this depend on precision?
40 static const double condition_no=1e9; // GK HACK TO GLOBAL
41 
42 
43 
44 
45 
46 
47 
88 template<int Rows=Dynamic, int Cols=Rows, typename Precision=DefaultPrecision>
89 class SVD {
90  // this is the size of the diagonal
91  // NB works for semi-dynamic sizes because -1 < +ve ints
92  static const int Min_Dim = Rows<Cols?Rows:Cols;
93 
94 public:
95 
97  SVD() {}
98 
100  SVD(int rows, int cols)
101  : my_copy(rows,cols),
102  my_diagonal(std::min(rows,cols)),
103  my_square(std::min(rows,cols), std::min(rows,cols))
104  {}
105 
108  template <int R2, int C2, typename P2, typename B2>
110  : my_copy(m),
111  my_diagonal(std::min(m.num_rows(),m.num_cols())),
112  my_square(std::min(m.num_rows(),m.num_cols()),std::min(m.num_rows(),m.num_cols()))
113  {
114  do_compute();
115  }
116 
118  template <int R2, int C2, typename P2, typename B2>
119  void compute(const Matrix<R2,C2,P2,B2>& m){
120  my_copy=m;
121  do_compute();
122  }
123 
124  private:
125  void do_compute(){
126  Precision* const a = my_copy.my_data;
127  int lda = my_copy.num_cols();
128  int m = my_copy.num_cols();
129  int n = my_copy.num_rows();
130  Precision* const uorvt = my_square.my_data;
131  Precision* const s = my_diagonal.my_data;
132  int ldu;
133  int ldvt = lda;
134  int LWORK;
135  int INFO;
136  char JOBU;
137  char JOBVT;
138 
139  if(is_vertical()){ // u is a
140  JOBU='O';
141  JOBVT='S';
142  ldu = lda;
143  } else { // vt is a
144  JOBU='S';
145  JOBVT='O';
146  ldu = my_square.num_cols();
147  }
148 
149  Precision* wk;
150 
151  Precision size;
152  LWORK = -1;
153 
154  // arguments are scrambled because we use rowmajor and lapack uses colmajor
155  // thus u and vt play each other's roles.
156  dgesvd_( &JOBVT, &JOBU, &m, &n, a, &lda, s, uorvt,
157  &ldvt, uorvt, &ldu, &size, &LWORK, &INFO);
158 
159  LWORK = (long int)(size);
160  wk = new Precision[LWORK];
161 
162  dgesvd_( &JOBVT, &JOBU, &m, &n, a, &lda, s, uorvt,
163  &ldvt, uorvt, &ldu, wk, &LWORK, &INFO);
164 
165  delete[] wk;
166  }
167 
168  bool is_vertical(){
169  return (my_copy.num_rows() >= my_copy.num_cols());
170  }
171 
172  int min_dim(){ return std::min(my_copy.num_rows(), my_copy.num_cols()); }
173 
174  public:
175 
180  template <int Rows2, int Cols2, typename P2, typename B2>
182  backsub(const Matrix<Rows2,Cols2,P2,B2>& rhs, const Precision condition=condition_no)
183  {
184  Vector<Min_Dim> inv_diag(min_dim());
185  get_inv_diag(inv_diag,condition);
186  return (get_VT().T() * diagmult(inv_diag, (get_U().T() * rhs)));
187  }
188 
193  template <int Size, typename P2, typename B2>
195  backsub(const Vector<Size,P2,B2>& rhs, const Precision condition=condition_no)
196  {
197  Vector<Min_Dim> inv_diag(min_dim());
198  get_inv_diag(inv_diag,condition);
199  return (get_VT().T() * diagmult(inv_diag, (get_U().T() * rhs)));
200  }
201 
206  Matrix<Cols,Rows> get_pinv(const Precision condition = condition_no){
207  Vector<Min_Dim> inv_diag(min_dim());
208  get_inv_diag(inv_diag,condition);
209  return diagmult(get_VT().T(),inv_diag) * get_U().T();
210  }
211 
214  Precision determinant() {
215  Precision result = my_diagonal[0];
216  for(int i=1; i<my_diagonal.size(); i++){
217  result *= my_diagonal[i];
218  }
219  return result;
220  }
221 
224  int rank(const Precision condition = condition_no) {
225  if (my_diagonal[0] == 0) return 0;
226  int result=1;
227  for(int i=0; i<min_dim(); i++){
228  if(my_diagonal[i] * condition <= my_diagonal[0]){
229  result++;
230  }
231  }
232  return result;
233  }
234 
239  if(is_vertical()){
241  (my_copy.my_data,my_copy.num_rows(),my_copy.num_cols());
242  } else {
244  (my_square.my_data, my_square.num_rows(), my_square.num_cols());
245  }
246  }
247 
250 
255  if(is_vertical()){
257  (my_square.my_data, my_square.num_rows(), my_square.num_cols());
258  } else {
260  (my_copy.my_data,my_copy.num_rows(),my_copy.num_cols());
261  }
262  }
263 
269  void get_inv_diag(Vector<Min_Dim>& inv_diag, const Precision condition){
270  for(int i=0; i<min_dim(); i++){
271  if(my_diagonal[i] * condition <= my_diagonal[0]){
272  inv_diag[i]=0;
273  } else {
274  inv_diag[i]=static_cast<Precision>(1)/my_diagonal[i];
275  }
276  }
277  }
278 
279 private:
282  Matrix<Min_Dim,Min_Dim,Precision,RowMajor> my_square; // square matrix (U or V' depending on the shape of my_copy)
283 };
284 
285 
286 
287 
288 
289 
293 template<int Size, typename Precision>
294 struct SQSVD : public SVD<Size, Size, Precision> {
298  SQSVD() {}
299  SQSVD(int size) : SVD<Size,Size,Precision>(size, size) {}
300 
301  template <int R2, int C2, typename P2, typename B2>
302  SQSVD(const Matrix<R2,C2,P2,B2>& m) : SVD<Size,Size,Precision>(m) {}
304 };
305 
306 
307 }
308 
309 
310 #endif
SVD(const Matrix< R2, C2, P2, B2 > &m)
Definition: SVD.h:109
Precision determinant()
Definition: SVD.h:214
Matrix< Rows, Min_Dim, Precision, Reference::RowMajor > get_U()
Definition: SVD.h:238
SQSVD()
Definition: SVD.h:298
bool is_vertical()
Definition: SVD.h:168
SQSVD(const Matrix< R2, C2, P2, B2 > &m)
Definition: SVD.h:302
Matrix< Rows, Cols, Precision, RowMajor > my_copy
Definition: SVD.h:280
Everything lives inside this namespace.
Definition: allocator.hh:48
Matrix< Cols, Cols2, typename Internal::MultiplyType< Precision, P2 >::type > backsub(const Matrix< Rows2, Cols2, P2, B2 > &rhs, const Precision condition=condition_no)
Definition: SVD.h:182
Matrix< Min_Dim, Min_Dim, Precision, RowMajor > my_square
Definition: SVD.h:282
SVD()
default constructor for Rows>0 and Cols>0
Definition: SVD.h:97
int min_dim()
Definition: SVD.h:172
Matrix< Cols, Rows > get_pinv(const Precision condition=condition_no)
Definition: SVD.h:206
Vector< Min_Dim, Precision > & get_diagonal()
Return the singular values as a vector.
Definition: SVD.h:249
Definition: SVD.h:89
void compute(const Matrix< R2, C2, P2, B2 > &m)
Compute the SVD decomposition of M, typically used after the default constructor. ...
Definition: SVD.h:119
void get_inv_diag(Vector< Min_Dim > &inv_diag, const Precision condition)
Definition: SVD.h:269
static const int Min_Dim
Definition: SVD.h:92
Matrix< Min_Dim, Cols, Precision, Reference::RowMajor > get_VT()
Definition: SVD.h:254
Vector< Min_Dim, Precision > my_diagonal
Definition: SVD.h:281
SVD(int rows, int cols)
constructor for Rows=-1 or Cols=-1 (or both)
Definition: SVD.h:100
SQSVD(int size)
Definition: SVD.h:299
void do_compute()
Definition: SVD.h:125
int rank(const Precision condition=condition_no)
Definition: SVD.h:224
static const double condition_no
Definition: SVD.h:40
void dgesvd_(const char *JOBU, const char *JOBVT, int *M, int *N, double *A, int *lda, double *S, double *U, int *ldu, double *VT, int *ldvt, double *WORK, int *lwork, int *INFO)
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
Vector< Cols, typename Internal::MultiplyType< Precision, P2 >::type > backsub(const Vector< Size, P2, B2 > &rhs, const Precision condition=condition_no)
Definition: SVD.h:195