TooN Algorithm Library - tag  0.2
absorient.h
Go to the documentation of this file.
1 #ifndef TAG_ABSORIENT_H_
2 #define TAG_ABSORIENT_H_
3 
4 #include <vector>
5 #ifdef WIN32
6 #include <tuple>
7 #else
8 #include <tr1/tuple>
9 #endif
10 
11 #include <TooN/TooN.h>
12 #include <TooN/sim2.h>
13 #include <TooN/sim3.h>
14 #include <TooN/SVD.h>
15 
16 namespace tag {
17 
22 
23 namespace Internal {
24 
25 template <int D>
26 std::pair<TooN::Matrix<D>, TooN::DefaultPrecision> computeOrientationScale( const std::vector<TooN::Vector<D> > & a, const std::vector<TooN::Vector<D> > & b ){
27  TooN::SizeMismatch<D,D>::test(a.front().size(), b.front().size());
28  const int DIM = a.front().size();
29  const size_t N = std::min(a.size(), b.size());
30 
31  // compute cross correlations
32  TooN::Matrix<D> s(DIM,DIM);
33  s = TooN::Zeros;
34  for( size_t i = 0; i < N; i++){
35  s += b[i].as_col() * a[i].as_row();
36  }
37  s /= N;
38 
39  // SVD of cross correlation matrix
40  TooN::SVD<D> svd(s);
41 
42  // build S for rotation matrix
43  TooN::Vector<D> S(DIM);
44  S = TooN::Ones;
45 
46  const TooN::DefaultPrecision eps = 1e-8;
47  const TooN::DefaultPrecision ds = determinant_gaussian_elimination(s);
48  if(ds < -eps){
49  S[DIM-1] = -1;
50  } else if(ds < eps) { // close to 0 let U * VT decide
51  const TooN::DefaultPrecision duv = TooN::determinant_gaussian_elimination(svd.get_U())
52  * TooN::determinant_gaussian_elimination(svd.get_VT());
53  if(duv < 0)
54  S[DIM-1] = -1;
55  }
56 
57  // compute trace(DS)
58  TooN::DefaultPrecision scale = 0;
59  for(int i = 0; i < DIM; ++i)
60  scale += svd.get_diagonal()[i] * S[i];
61 
62  return std::make_pair(svd.get_U() * S.as_diagonal() * svd.get_VT(), scale);
63 }
64 
65 }
66 
75 template <int D>
76 inline TooN::Matrix<D> computeRotation( const std::vector<TooN::Vector<D> > & a, const std::vector<TooN::Vector<D> > & b ){
77  std::pair<TooN::Matrix<D>, TooN::DefaultPrecision> Rs = Internal::computeOrientationScale( a, b );
78  return Rs.first;
79 }
80 
89 inline TooN::SO3<> computeOrientation( const std::vector<TooN::Vector<3> > & a, const std::vector<TooN::Vector<3> > & b ){
90  std::pair<TooN::Matrix<3>, TooN::DefaultPrecision> result = Internal::computeOrientationScale( a, b );
91  return TooN::SO3<>(result.first);
92 }
93 
102 inline TooN::SO2<> computeOrientation( const std::vector<TooN::Vector<2> > & a, const std::vector<TooN::Vector<2> > & b ){
103  std::pair<TooN::Matrix<2>, TooN::DefaultPrecision> result = Internal::computeOrientationScale( a, b );
104  return TooN::SO2<>(result.first);
105 }
106 
115 TooN::SO3<> computeOrientation( const TooN::Vector<3> & a1, const TooN::Vector<3> & b1, const TooN::Vector<3> & a2, const TooN::Vector<3> & b2 );
116 
126 template <int D>
127 std::pair<TooN::Matrix<D>, TooN::Vector<D> > computeAbsoluteOrientation( const std::vector<TooN::Vector<D> > & a, const std::vector<TooN::Vector<D> > & b){
128  TooN::SizeMismatch<D,D>::test(a.front().size(), b.front().size());
129  const int DIM = a.front().size();
130  const size_t N = std::min(a.size(), b.size());
131 
132  if(N == 1){ // quick special case
133  TooN::Matrix<D> R(DIM, DIM);
134  R = TooN::Identity;
135  return std::make_pair(R, b.front() - a.front());
136  }
137 
138  // compute centroids
139  // Strictly speaking, it is not necessary to remove the centroids from both sets,
140  // one set is enough. However, we do it nevertheless to improve the conditioning
141  // of the rotation/scale estimation.
142  TooN::Vector<D> ma = TooN::Zeros(DIM), mb = TooN::Zeros(DIM);
143  for(unsigned i = 0; i < N; ++i){
144  ma += a[i];
145  mb += b[i];
146  }
147  ma /= N;
148  mb /= N;
149 
150  // compute shifted locations
151  std::vector<TooN::Vector<D> > ap(N), bp(N);
152  for( unsigned i = 0; i < N; ++i){
153  ap[i] = a[i] - ma;
154  bp[i] = b[i] - mb;
155  }
156 
157  // put resulting transformation together
158  std::pair<TooN::Matrix<D>, TooN::DefaultPrecision> Rs = Internal::computeOrientationScale( ap, bp );
159  return std::make_pair(Rs.first, mb - Rs.first * ma);
160 }
161 
168 inline TooN::SE3<> computeAbsoluteOrientation( const std::vector<TooN::Vector<3> > & a, const std::vector<TooN::Vector<3> > & b){
169  std::pair<TooN::Matrix<3>, TooN::Vector<3> > Rt = computeAbsoluteOrientation<3>( a, b );
170  return TooN::SE3<>(Rt.first, Rt.second);
171 }
172 
179 inline TooN::SE2<> computeAbsoluteOrientation( const std::vector<TooN::Vector<2> > & a, const std::vector<TooN::Vector<2> > & b){
180  std::pair<TooN::Matrix<2>, TooN::Vector<2> > Rt = computeAbsoluteOrientation<2>( a, b );
181  return TooN::SE2<>(Rt.first, Rt.second);
182 }
183 
193 template <int D>
194 std::tr1::tuple<TooN::Matrix<D>, TooN::Vector<D>, TooN::DefaultPrecision > computeSimilarity( const std::vector<TooN::Vector<D> > & a, const std::vector<TooN::Vector<D> > & b){
195  TooN::SizeMismatch<D,D>::test(a.front().size(), b.front().size());
196  const int DIM = a.front().size();
197  const size_t N = std::min(a.size(), b.size());
198 
199  if(N == 1){ // quick special case
200  TooN::Matrix<D> R(DIM, DIM);
201  R = TooN::Identity;
202  return std::tr1::make_tuple(R, b.front() - a.front(), 1);
203  }
204 
205  // compute centroids
206  // Strictly speaking, it is not necessary to remove the centroids from both sets,
207  // one set is enough. However, we do it nevertheless to improve the conditioning
208  // of the rotation/scale estimation.
209  TooN::Vector<D> ma = TooN::Zeros(DIM), mb = TooN::Zeros(DIM);
210  for(unsigned i = 0; i < N; ++i){
211  ma += a[i];
212  mb += b[i];
213  }
214  ma /= N;
215  mb /= N;
216 
217  // compute shifted locations
218  std::vector<TooN::Vector<D> > ap(N), bp(N);
219  for( unsigned i = 0; i < N; ++i){
220  ap[i] = a[i] - ma;
221  bp[i] = b[i] - mb;
222  }
223 
224  // put resulting transformation together
225  std::pair<TooN::Matrix<D>, TooN::DefaultPrecision> Rs = Internal::computeOrientationScale( ap, bp );
226  // compute scale
227  TooN::DefaultPrecision sa = 0;
228  for( unsigned int i = 0; i < N; ++i){
229  sa += TooN::norm_sq(ap[i]);
230  }
231  sa /= N;
232  const TooN::DefaultPrecision scale = Rs.second / sa;
233  return std::tr1::make_tuple(Rs.first, mb - Rs.first * (scale * ma), scale);
234 }
235 
242 inline TooN::SIM3<> computeSimilarity( const std::vector<TooN::Vector<3> > & a, const std::vector<TooN::Vector<3> > & b){
243  std::tr1::tuple<TooN::Matrix<3>, TooN::Vector<3>, TooN::DefaultPrecision > Rts = computeSimilarity<3>(a,b);
244  return TooN::SIM3<>(TooN::SO3<>(std::tr1::get<0>(Rts)), std::tr1::get<1>(Rts), std::tr1::get<2>(Rts));
245 }
246 
253 inline TooN::SIM2<> computeSimilarity( const std::vector<TooN::Vector<2> > & a, const std::vector<TooN::Vector<2> > & b){
254  std::tr1::tuple<TooN::Matrix<2>, TooN::Vector<2>, TooN::DefaultPrecision > Rts = computeSimilarity<2>(a,b);
255  return TooN::SIM2<>(TooN::SO2<>(std::tr1::get<0>(Rts)), std::tr1::get<1>(Rts), std::tr1::get<2>(Rts));
256 }
257 
262 TooN::SO3<> computeMeanOrientation( const std::vector<TooN::SO3<> > & r);
263 
269 TooN::Matrix<3> quaternionToMatrix( const TooN::Vector<4> & q );
270 
271 } // namespace tag
272 
273 #endif // TAG_ABSORIENT_H_