toon-members
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Toon-members] tag tag/absorient.h src/absorient.cpp test/sim.cpp


From: Gerhard Reitmayr
Subject: [Toon-members] tag tag/absorient.h src/absorient.cpp test/sim.cpp
Date: Wed, 29 Jun 2011 20:34:45 +0000

CVSROOT:        /cvsroot/toon
Module name:    tag
Changes by:     Gerhard Reitmayr <gerhard>      11/06/29 20:34:45

Modified files:
        tag            : absorient.h 
        src            : absorient.cpp 
        test           : sim.cpp 

Log message:
        made the N-dim absolute pose algorithm accessible, use new SIM{2,3} 
objects from TooN for 2D and 3D

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/tag/tag/absorient.h?cvsroot=toon&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/tag/src/absorient.cpp?cvsroot=toon&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/tag/test/sim.cpp?cvsroot=toon&r1=1.2&r2=1.3

Patches:
Index: tag/absorient.h
===================================================================
RCS file: /cvsroot/toon/tag/tag/absorient.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- tag/absorient.h     27 Jun 2011 14:56:24 -0000      1.6
+++ tag/absorient.h     29 Jun 2011 20:34:45 -0000      1.7
@@ -2,27 +2,103 @@
 #define TAG_ABSORIENT_H_
 
 #include <vector>
+#include <tr1/tuple>
 
 #include <TooN/TooN.h>
-#include <TooN/se3.h>
+#include <TooN/sim2.h>
+#include <TooN/sim3.h>
+#include <TooN/svd.h>
 
 namespace tag {
 
 /// @defgroup absorient Absolute Orientation
 /// contains various functions to calculate rotations and rigid transformations
-/// between sets of 3D correspondences.
+/// between sets of D-dim correspondences. There are special case functions
+/// for 2D and 3D points sets that directly return SO2, SO3, SE2 and SE3 
objects.
 
-/// computes the rotation between two sets of points maximizing b * Ta
-/// this function is part of the absolute orientation algorithm after 
+namespace Internal {
+
+template <int D>
+std::pair<TooN::Matrix<D>, TooN::DefaultPrecision> computeOrientationScale( 
const std::vector<TooN::Vector<D> > & a, const std::vector<TooN::Vector<D> > & 
b ){
+       TooN::SizeMismatch<D,D>::test(a.front().size(), b.front().size());
+       const int DIM = a.front().size();
+       const size_t N = std::min(a.size(), b.size());
+
+       // compute cross correlations
+       TooN::Matrix<D> s(DIM,DIM); 
+       s = TooN::Zeros;
+       for( size_t i = 0; i < N; i++){
+               s += b[i].as_col() * a[i].as_row();
+       }
+       s /= N;
+
+       // SVD of cross correlation matrix
+       TooN::SVD<D> svd(s);
+
+       // build S for rotation matrix
+       TooN::Vector<D> S(DIM);
+       S = TooN::Ones;
+
+       const TooN::DefaultPrecision eps = 1e-8;
+       const TooN::DefaultPrecision ds = determinant_gaussian_elimination(s);
+       if(ds < -eps){
+               S[DIM-1] = -1;
+       } else if(ds < eps) { // close to 0 let U * VT decide
+               const TooN::DefaultPrecision duv = 
TooN::determinant_gaussian_elimination(svd.get_U()) 
+                                                                               
* TooN::determinant_gaussian_elimination(svd.get_VT());
+               if(duv <  0)
+                       S[DIM-1] = -1;
+       }
+
+       // compute trace(DS)
+       TooN::DefaultPrecision scale = 0;
+       for(int i = 0; i < DIM; ++i)
+               scale += svd.get_diagonal()[i] * S[i];
+
+       return std::make_pair(svd.get_U() * S.as_diagonal() * svd.get_VT(), 
scale);
+}
+
+}
+
+/// computes the rotation between two sets of D-dim points maximizing b * Ta
+/// This function returns only the rotation matrix computed after
+/// Shinji Umeyama, Least-squares estimation of transformation parameters 
+/// between two point patterns. IEEE PAMI, 13(4):376-380, 1991.
+/// @param[in] a vector of D-dim points
+/// @param[in] b vector of D-dim points
+/// @return DxD matrix R describing the rotation such that b = R a
+/// @ingroup absorient
+template <int D>
+inline TooN::Matrix<D> computeRotation( const std::vector<TooN::Vector<D> > & 
a, const std::vector<TooN::Vector<D> > & b ){
+       std::pair<TooN::Matrix<D>, TooN::DefaultPrecision> Rs = 
Internal::computeOrientationScale( a, b );
+       return Rs.first;
+}
+
+/// computes the rotation between two sets of 3D points maximizing b * Ta
+/// This function returns only the rotation matrix as an SO3<> computed after
 /// Shinji Umeyama, Least-squares estimation of transformation parameters 
 /// between two point patterns. IEEE PAMI, 13(4):376-380, 1991.
-/// @ref computeAbsoluteOrientation and @ref computeSimilarity functions use 
this
-/// function.
 /// @param[in] a vector of 3D points
 /// @param[in] b vector of 3D points
 /// @return TooN::SO3 containing the rotation such that b = T a
 /// @ingroup absorient
-TooN::SO3<> computeOrientation( const std::vector<TooN::Vector<3> > & a, const 
std::vector<TooN::Vector<3> > & b );
+inline TooN::SO3<> computeOrientation( const std::vector<TooN::Vector<3> > & 
a, const std::vector<TooN::Vector<3> > & b ){
+       std::pair<TooN::Matrix<3>, TooN::DefaultPrecision> result = 
Internal::computeOrientationScale( a, b );
+       return TooN::SO3<>(result.first);
+}
+
+/// computes the rotation between two sets of 2D points maximizing b * Ta
+/// This function returns only the rotation matrix as an SO3<> computed after
+/// Shinji Umeyama, Least-squares estimation of transformation parameters 
+/// between two point patterns. IEEE PAMI, 13(4):376-380, 1991.
+/// @param[in] a vector of 2D points
+/// @param[in] b vector of 2D points
+/// @return TooN::SO3 containing the rotation such that b = T a
+/// @ingroup absorient
+inline TooN::SO2<> computeOrientation( const std::vector<TooN::Vector<2> > & 
a, const std::vector<TooN::Vector<2> > & b ){
+       std::pair<TooN::Matrix<2>, TooN::DefaultPrecision> result = 
Internal::computeOrientationScale( a, b );
+       return TooN::SO2<>(result.first);
+}
 
 /// directly computes a rotation between two pairs of rays in space maximizing 
b * T a
 /// its about 8x faster then using the general computeOrientation for 2 
correspondences.
@@ -34,25 +110,140 @@
 /// @ingroup absorient
 TooN::SO3<> computeOrientation( const TooN::Vector<3> & a1, const 
TooN::Vector<3> & b1, const TooN::Vector<3> & a2, const TooN::Vector<3> & b2 );
 
-/// computes the rigid transformation between two corresponding point sets 
after 
+/// computes the rigid transformation between two corresponding D dimensional 
point sets after 
 /// Shinji Umeyama, Least-squares estimation of transformation parameters 
 /// between two point patterns. IEEE PAMI, 13(4):376-380, 1991.
-/// The result is an SE3 that maps points from vector a to points from vector 
b : b[i] = SE3 * a[i]
+/// The result is a rotation matrix R and a translation vector t
+/// that map points from vector a to points from vector b : b[i] = R * a[i] + t
+/// @param[in] a vector of D-dim points
+/// @param[in] b vector of D-dim points
+/// @return std::pair containing R and t such that b[i] = R * a[i] + t
+/// @ingroup absorient
+template <int D>
+std::pair<TooN::Matrix<D>, TooN::Vector<D> > computeAbsoluteOrientation( const 
std::vector<TooN::Vector<D> > & a, const std::vector<TooN::Vector<D> > & b){
+       TooN::SizeMismatch<D,D>::test(a.front().size(), b.front().size());
+       const int DIM = a.front().size();
+       const size_t N = std::min(a.size(), b.size());
+       
+       if(N == 1){    // quick special case
+               TooN::Matrix<D> R(DIM, DIM);
+               R = TooN::Identity;
+               return std::make_pair(R, b.front() - a.front());
+       }
+
+       // compute centroids
+       TooN::Vector<D> ma = TooN::Zeros(DIM), mb = TooN::Zeros(DIM);
+       for(unsigned i = 0; i < N; ++i){
+               ma += a[i];
+               mb += b[i];
+       }
+       ma /= N;
+       mb /= N;
+
+       // compute shifted locations
+       std::vector<TooN::Vector<D> > ap(N), bp(N);
+       for( unsigned i = 0; i < N; ++i){
+               ap[i] = a[i] - ma;
+               bp[i] = b[i] - ma;
+       }
+       
+       // put resulting transformation together
+       std::pair<TooN::Matrix<D>, TooN::DefaultPrecision> Rs = 
Internal::computeOrientationScale( ap, bp );
+       return std::make_pair(Rs.first, mb - Rs.first * ma);
+}
+
+/// overload of @ref computeAbsoluteOrientation that computes the rigid 
transformation between two corresponding 3D point sets 
+/// as an SE3 that maps points from vector a to points from vector b : b[i] = 
SE3 * a[i]
 /// @param[in] a vector of 3D points
 /// @param[in] b vector of 3D points
-/// @return TooN::SE3 containing the transformation such that b = T a
+/// @return TooN::SE3 T containing the transformation such that b = T a
 /// @ingroup absorient
-TooN::SE3<> computeAbsoluteOrientation( const std::vector<TooN::Vector<3> > & 
a, const std::vector<TooN::Vector<3> > & b);
+inline TooN::SE3<> computeAbsoluteOrientation( const 
std::vector<TooN::Vector<3> > & a, const std::vector<TooN::Vector<3> > & b){
+       std::pair<TooN::Matrix<3>, TooN::Vector<3> > Rt = 
computeAbsoluteOrientation<3>( a, b );
+       return TooN::SE3<>(Rt.first, Rt.second);
+}
+
+/// overload of @ref computeAbsoluteOrientation that computes the rigid 
transformation between two corresponding 2D point sets 
+/// as an SE2 that maps points from vector a to points from vector b : b[i] = 
SE2 * a[i]
+/// @param[in] a vector of 2D points
+/// @param[in] b vector of 2D points
+/// @return TooN::SE2 T containing the transformation such that b = T a
+/// @ingroup absorient
+inline TooN::SE2<> computeAbsoluteOrientation( const 
std::vector<TooN::Vector<2> > & a, const std::vector<TooN::Vector<2> > & b){
+       std::pair<TooN::Matrix<2>, TooN::Vector<2> > Rt = 
computeAbsoluteOrientation<2>( a, b );
+       return TooN::SE2<>(Rt.first, Rt.second);
+}
 
-/// computes a similarity transformation between two corresponding point sets 
after
+/// computes the rigid transformation between two corresponding D dimensional 
point sets after 
 /// Shinji Umeyama, Least-squares estimation of transformation parameters 
 /// between two point patterns. IEEE PAMI, 13(4):376-380, 1991.
-/// The result is an SE3 and a scale S that maps points from vector a to 
points from vector b : b[i] = SE3 * S * a[i]
+/// The result is a rotation matrix R, a scale factor s and a translation 
vector t
+/// that map points from vector a to points from vector b : b[i] = s * R * 
a[i] + t
+/// @param[in] a vector of D-dim points
+/// @param[in] b vector of D-dim points
+/// @return std::tuple containing R, t and s such that b[i] = s * R * a[i] + t
+/// @ingroup absorient
+template <int D>
+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){
+       TooN::SizeMismatch<D,D>::test(a.front().size(), b.front().size());
+       const int DIM = a.front().size();
+       const size_t N = std::min(a.size(), b.size());
+       
+       if(N == 1){    // quick special case
+               TooN::Matrix<D> R(DIM, DIM);
+               R = TooN::Identity;
+               return std::tr1::make_tuple(R, b.front() - a.front(), 1);
+       }
+
+       // compute centroids
+       TooN::Vector<D> ma = TooN::Zeros(DIM), mb = TooN::Zeros(DIM);
+       for(unsigned i = 0; i < N; ++i){
+               ma += a[i];
+               mb += b[i];
+       }
+       ma /= N;
+       mb /= N;
+
+       // compute shifted locations
+       std::vector<TooN::Vector<D> > ap(N), bp(N);
+       for( unsigned i = 0; i < N; ++i){
+               ap[i] = a[i] - ma;
+               bp[i] = b[i] - ma;
+       }
+       
+       // put resulting transformation together
+       std::pair<TooN::Matrix<D>, TooN::DefaultPrecision> Rs = 
Internal::computeOrientationScale( ap, bp );
+               // compute scale
+       TooN::DefaultPrecision sa = 0;
+       for( unsigned int i = 0; i < N; ++i){
+               sa += TooN::norm_sq(ap[i]);
+       }
+       sa /= N;
+       const TooN::DefaultPrecision scale = Rs.second / sa;
+       return std::tr1::make_tuple(Rs.first, mb - Rs.first * (scale * ma), 
scale);
+}
+
+/// overload of @ref computeSimilarity that computes the rigid transformation 
between two corresponding 3D point sets 
+/// as an SE3 and a scale S that maps points from vector a to points from 
vector b : b[i] = SE3 * S * a[i]
 /// @param[in] a vector of 3D points
 /// @param[in] b vector of 3D points
 /// @return a pair consisting of a TooN::SE3 T and a double S containing the 
transformation such that b = T * S * a
 /// @ingroup absorient
-std::pair<TooN::SE3<>, TooN::DefaultPrecision> computeSimilarity( const 
std::vector<TooN::Vector<3> > & a, const std::vector<TooN::Vector<3> > & b);
+inline TooN::SIM3<> computeSimilarity( const std::vector<TooN::Vector<3> > & 
a, const std::vector<TooN::Vector<3> > & b){
+       std::tr1::tuple<TooN::Matrix<3>, TooN::Vector<3>, 
TooN::DefaultPrecision > Rts = computeSimilarity<3>(a,b);
+       return TooN::SIM3<>(TooN::SO3<>(std::tr1::get<0>(Rts)), 
std::tr1::get<1>(Rts), std::tr1::get<2>(Rts));
+}
+
+/// overload of @ref computeSimilarity that computes the rigid transformation 
between two corresponding 2D point sets 
+/// as an SE2 and a scale S that maps points from vector a to points from 
vector b : b[i] = SE2 * S * a[i]
+/// @param[in] a vector of 2D points
+/// @param[in] b vector of 2D points
+/// @return a pair consisting of a TooN::SE2 T and a double S containing the 
transformation such that b = T * S * a
+/// @ingroup absorient
+inline TooN::SIM2<> computeSimilarity( const std::vector<TooN::Vector<2> > & 
a, const std::vector<TooN::Vector<2> > & b){
+       std::tr1::tuple<TooN::Matrix<2>, TooN::Vector<2>, 
TooN::DefaultPrecision > Rts = computeSimilarity<2>(a,b);
+       return TooN::SIM2<>(TooN::SO2<>(std::tr1::get<0>(Rts)), 
std::tr1::get<1>(Rts), std::tr1::get<2>(Rts));
+}
 
 /// computes the mean rotation of a set of rotations. This is the rotation R 
such that R^{-1} * R_i is minimal for all R_i.
 /// @param[in] r a vector of rotations

Index: src/absorient.cpp
===================================================================
RCS file: /cvsroot/toon/tag/src/absorient.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- src/absorient.cpp   27 Jun 2011 14:56:24 -0000      1.11
+++ src/absorient.cpp   29 Jun 2011 20:34:45 -0000      1.12
@@ -2,14 +2,11 @@
 
 #include <cassert>
 
-#include <TooN/svd.h>
 #include <TooN/helpers.h>
 #include <TooN/determinant.h>
 
 namespace tag {
 
-static const TooN::DefaultPrecision eps = 1e-8;
-
 TooN::Matrix<3> quaternionToMatrix( const TooN::Vector<4> & q ){
     TooN::Matrix<3> result;
     const int w = 0, x = 1, y = 2, z = 3;
@@ -25,44 +22,6 @@
     return result;
 }
 
-static std::pair<TooN::SO3<>, TooN::DefaultPrecision> computeOrientationScale( 
const std::vector<TooN::Vector<3> > & a, const std::vector<TooN::Vector<3> > & 
b ){
-       const size_t N = a.size();
-       // compute cross correlations
-       TooN::Matrix<3> s = TooN::Zeros;
-       for( size_t i = 0; i < N; i++){
-               s += b[i].as_col() * a[i].as_row();
-       }
-       s /= N;
-
-       // SVD of cross correlation matrix
-       TooN::SVD<3> svd(s);
-
-       // build S for rotation matrix
-       TooN::Matrix<3> S = TooN::Identity;
-
-       const TooN::DefaultPrecision ds = determinant_gaussian_elimination(s);
-       if(ds < -eps){
-               S(2,2) = -1;
-       } else if(ds < eps) { // close to 0 let U * VT decide
-               const TooN::DefaultPrecision duv = 
determinant_gaussian_elimination(svd.get_U()) 
-                                                                               
* determinant_gaussian_elimination(svd.get_VT());
-               if(duv <  0)
-                       S(2,2) = -1;
-       }
-
-       // compute trace(DS)
-       TooN::DefaultPrecision scale = 0;
-       for(int i = 0; i < 3; ++i)
-               scale += svd.get_diagonal()[i] * S(i,i);
-
-       return std::make_pair(TooN::SO3<>(svd.get_U() * S * svd.get_VT()), 
scale);
-}
-
-TooN::SO3<> computeOrientation( const std::vector<TooN::Vector<3> > & a, const 
std::vector<TooN::Vector<3> > & b ){
-       std::pair<TooN::SO3<>, TooN::DefaultPrecision> result = 
computeOrientationScale( a, b );
-       return result.first;
-}
-
 // computes the orientation from (e1,e2,e3) -> (a,(a^b)^a,a^b), which means 
that b the second vector is in the a, b plane
 static inline TooN::SO3<>  canonicalOrientation( const TooN::Vector<3> & a, 
const TooN::Vector<3> & b ){
     TooN::Vector<3> n = a ^ b;
@@ -86,82 +45,6 @@
     return TooN::SO3<> ::exp(diff.ln() * 0.5) * rAB;
 }
 
-TooN::SE3<> computeAbsoluteOrientation( const std::vector<TooN::Vector<3> > & 
a, const std::vector<TooN::Vector<3> > & b){
-       assert(a.size() <= b.size());
-    const size_t N = a.size();
-
-       if(N == 1){    // quick special case
-               return TooN::SE3<>(TooN::SO3<>(), b[0] - a[0]);
-       }
-
-    TooN::Vector<3> ma = TooN::Zeros, mb = TooN::Zeros;
-
-    // compute centroids
-    for(unsigned int i = 0; i < N; i++){
-        ma += a[i];
-        mb += b[i];
-    }
-    ma /= N;
-    mb /= N;
-
-    // compute shifted locations
-    std::vector<TooN::Vector<3> > ap(N), bp(N);
-    for( unsigned int i = 0; i < N; i++){
-        ap[i] = a[i] - ma;
-        bp[i] = b[i] - ma;
-    }
-
-    // put resulting transformation together
-    TooN::SE3<>  result;
-    result.get_rotation() = computeOrientation( ap, bp );
-    result.get_translation() = mb - result.get_rotation() * ma;
-    return result;
-}
-
-std::pair<TooN::SE3<>, TooN::DefaultPrecision> computeSimilarity( const 
std::vector<TooN::Vector<3> > & a, const std::vector<TooN::Vector<3> > & b){
-       assert(a.size() <= b.size());
-       const size_t N = a.size();
-       
-       if(N == 1){    // quick special case
-               return std::make_pair(TooN::SE3<>(TooN::SO3<>(), b[0] - a[0]), 
1);
-       }
-       
-       TooN::Vector<3> ma = TooN::Zeros, mb = TooN::Zeros;
-       
-       // compute centroids
-       for(unsigned int i = 0; i < N; ++i){
-               ma += a[i];
-               mb += b[i];
-       }
-       ma /= N;
-       mb /= N;
-       
-       // compute shifted locations
-       std::vector<TooN::Vector<3> > ap(N), bp(N);
-       for( unsigned int i = 0; i < N; ++i){
-               ap[i] = a[i] - ma;
-               bp[i] = b[i] - ma;
-       }
-       
-       // put resulting transformation together 
-       TooN::SE3<>  result;
-       std::pair<TooN::SO3<>, TooN::DefaultPrecision> rs = 
computeOrientationScale( ap, bp );
-       result.get_rotation() = rs.first;
-       
-       std::cout << rs.second << std::endl;
-       
-       // compute scale
-       TooN::DefaultPrecision sa = 0;
-       for( unsigned int i = 0; i < N; ++i){
-               sa += norm_sq(ap[i]);
-       }
-       sa /= N;
-       const TooN::DefaultPrecision scale = rs.second / sa;
-       
-       result.get_translation() = mb - result.get_rotation() * (scale * ma);
-       return std::make_pair(result, scale);
-}
-
 TooN::SO3<>  computeMeanOrientation( const std::vector<TooN::SO3<> > & r){
     const size_t N = r.size();
     std::vector<TooN::SO3<> > rt(N);

Index: test/sim.cpp
===================================================================
RCS file: /cvsroot/toon/tag/test/sim.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- test/sim.cpp        25 Jun 2011 09:14:57 -0000      1.2
+++ test/sim.cpp        29 Jun 2011 20:34:45 -0000      1.3
@@ -8,7 +8,6 @@
 using namespace tag;
 
 typedef vector<Vector<3> > Points;
-typedef pair<SE3<>, double> Sim;
 
 double inline rand_u(){
     return (double)rand()/RAND_MAX;
@@ -32,28 +31,28 @@
 
     Points a(N), b(N), c(N);
     
-    SE3<> pose(makeVector(1,2,3,2,1,0.5));
-    const double scale = 0.37;
+    SIM3<> pose(makeVector(1,2,3,2,1,0.5, 0.37));
     
     for( unsigned i = 0; i < N; ++i ){
         a[i] = rand_vect<3>(-10, 10);
-        b[i] = pose * (scale * a[i]);
+        b[i] = pose * a[i];
         c[i] = b[i] + rand_vect<3>(-0.01, 0.01);
     }
 
-    Sim sb = computeSimilarity(a,b);
-    Sim sc = computeSimilarity(a,c);
+    SIM3<> sb = computeSimilarity(a,b);
+    SIM3<> sc = computeSimilarity(a,c);
 
     double eb = 0, ec = 0;
     for( unsigned i = 0; i < N; ++i){
-        eb += norm_sq(b[i] - sb.first * (sb.second * a[i]));
-        ec += norm_sq(c[i] - sc.first * (sc.second * a[i]));
+        eb += norm_sq(b[i] - sb * a[i]);
+        ec += norm_sq(c[i] - sc * a[i]);
     }
+    eb = sqrt(eb/N);
+    ec = sqrt(ec/N);
     
-    
-    cout << "test\t" << pose.ln() << "\t" << scale << "\n";
-    cout << "exact\t" << sb.first.ln() << "\t" << sb.second << "\t" << sqrt( 
eb ) << "\n"
-         << "noisy\t" << sc.first.ln() << "\t" << sc.second << "\t" << sqrt( 
ec ) << endl;
+    cout << "test\t" << pose.ln() << "\n";
+    cout << "exact\t" << sb.ln()  << "\t" << eb << "\n"
+         << "noisy\t" << sc.ln() << "\t" << ec << endl;
 
     return 0;
 }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]