core/vgl/algo/vgl_compute_similarity_3d.txx
Go to the documentation of this file.
00001 // This is core/vgl/algo/vgl_compute_similarity_3d.txx
00002 #ifndef vgl_compute_similarity_3d_txx_
00003 #define vgl_compute_similarity_3d_txx_
00004 //:
00005 // \file
00006 
00007 #include "vgl_compute_similarity_3d.h"
00008 #include <vgl/algo/vgl_norm_trans_3d.h>
00009 #include <vnl/vnl_double_4.h>
00010 #include <vnl/algo/vnl_svd.h>
00011 #include <vnl/algo/vnl_determinant.h>
00012 #include <vnl/vnl_matrix.h>
00013 #include <vcl_iostream.h>
00014 #include <vcl_cassert.h>
00015 
00016 template <class T>
00017 vgl_compute_similarity_3d<T>::
00018 vgl_compute_similarity_3d(vcl_vector<vgl_point_3d<T> > const& points1,
00019                           vcl_vector<vgl_point_3d<T> > const& points2)
00020 : points1_(points1),
00021   points2_(points2)
00022 {
00023   assert(points1.size() == points2.size());
00024 }
00025 
00026 template <class T>
00027 void vgl_compute_similarity_3d<T>::
00028 add_points(vgl_point_3d<T> const &p1, vgl_point_3d<T> const &p2)
00029 {
00030   points1_.push_back(p1);
00031   points2_.push_back(p2);
00032 }
00033 
00034 
00035 template <class T>
00036 void vgl_compute_similarity_3d<T>::clear()
00037 {
00038   points1_.clear();
00039   points2_.clear();
00040 }
00041 
00042 
00043 //: center all the points at the origin, and return the applied translation
00044 template <class T>
00045 void vgl_compute_similarity_3d<T>::
00046 center_points(vcl_vector<vgl_point_3d<T> >& pts,
00047               vgl_vector_3d<T>& t) const
00048 {
00049   t.set(0,0,0);
00050   vgl_point_3d<T> origin(0,0,0);
00051   for (unsigned i=0; i<pts.size(); ++i)
00052   {
00053     t += origin - pts[i];
00054   }
00055   t /= pts.size();
00056   for (unsigned i=0; i<pts.size(); ++i)
00057   {
00058     pts[i] += t;
00059   }
00060 }
00061 
00062 
00063 //: normalize the scale of the points, and return the applied scale
00064 //  The average distance from the origin will be sqrt(3)
00065 template <class T>
00066 void vgl_compute_similarity_3d<T>::
00067 scale_points(vcl_vector<vgl_point_3d<T> >& pts,
00068              T& s) const
00069 {
00070   s = 0.0;
00071   vgl_point_3d<T> origin(0,0,0);
00072   for (unsigned i=0; i<pts.size(); ++i)
00073   {
00074     s += (pts[i]-origin).length();
00075   }
00076   s = vcl_sqrt(3.0)*pts.size()/s;
00077   for (unsigned i=0; i<pts.size(); ++i)
00078   {
00079     vgl_point_3d<T>& p = pts[i];
00080     p.set(p.x()*s, p.y()*s, p.z()*s);
00081   }
00082 }
00083 
00084 
00085 template <class T>
00086 bool vgl_compute_similarity_3d<T>::estimate()
00087 {
00088   vgl_vector_3d<T> t1, t2;
00089   vcl_vector<vgl_point_3d<T> > pts1(points1_), pts2(points2_);
00090   center_points(pts1, t1);
00091   center_points(pts2, t2);
00092 
00093 
00094   T s1, s2;
00095   scale_points(pts1, s1);
00096   scale_points(pts2, s2);
00097   scale_ = s1/s2;
00098 
00099   // estimate rotation
00100   vnl_matrix<T> M(3,3,0.0);
00101   for (unsigned i=0; i<pts1.size(); ++i)
00102   {
00103     vgl_point_3d<T>& p1 = pts1[i];
00104     vgl_point_3d<T>& p2 = pts2[i];
00105     M(0,0) += p1.x()*p2.x();
00106     M(0,1) += p1.x()*p2.y();
00107     M(0,2) += p1.x()*p2.z();
00108     M(1,0) += p1.y()*p2.x();
00109     M(1,1) += p1.y()*p2.y();
00110     M(1,2) += p1.y()*p2.z();
00111     M(2,0) += p1.z()*p2.x();
00112     M(2,1) += p1.z()*p2.y();
00113     M(2,2) += p1.z()*p2.z();
00114   }
00115 
00116   vnl_matrix<T> N(4,4);
00117   N(0,0) =   M(0,0) - M(1,1) - M(2,2);
00118   N(1,1) = - M(0,0) + M(1,1) - M(2,2);
00119   N(2,2) = - M(0,0) - M(1,1) + M(2,2);
00120   N(3,3) =   M(0,0) + M(1,1) + M(2,2);
00121   N(0,1) = N(1,0) = M(0,1) + M(1,0);
00122   N(0,2) = N(2,0) = M(2,0) + M(0,2);
00123   N(1,2) = N(2,1) = M(1,2) + M(2,1);
00124   N(3,0) = N(0,3) = M(1,2) - M(2,1);
00125   N(3,1) = N(1,3) = M(2,0) - M(0,2);
00126   N(3,2) = N(2,3) = M(0,1) - M(1,0);
00127 
00128   vnl_svd<T> svd(N);
00129   vnl_double_4 q(svd.V().get_column(0));
00130   rotation_ = vgl_rotation_3d<T>(vnl_quaternion<T>(q));
00131   translation_ = (scale_*(rotation_*t1) - t2);
00132 
00133   return true;
00134 }
00135 
00136 //--------------------------------------------------------------------------
00137 #undef VGL_COMPUTE_SIMILARITY_3D_INSTANTIATE
00138 #define VGL_COMPUTE_SIMILARITY_3D_INSTANTIATE(T) \
00139 template class vgl_compute_similarity_3d<T >
00140 
00141 #endif // vgl_compute_similarity_3d_txx_