00001
00002 #ifndef vgl_compute_similarity_3d_txx_
00003 #define vgl_compute_similarity_3d_txx_
00004
00005
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
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
00064
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
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_