core/vgl/algo/vgl_fit_plane_3d.txx
Go to the documentation of this file.
00001 // This is core/vgl/algo/vgl_fit_plane_3d.txx
00002 #ifndef vgl_fit_plane_3d_txx_
00003 #define vgl_fit_plane_3d_txx_
00004 //:
00005 // \file
00006 
00007 #include "vgl_fit_plane_3d.h"
00008 #include <vgl/algo/vgl_norm_trans_3d.h>
00009 #include <vnl/algo/vnl_svd.h>
00010 #include <vnl/vnl_matrix.h>
00011 #include <vcl_iostream.h>
00012 
00013 template <class T>
00014 vgl_fit_plane_3d<T>::vgl_fit_plane_3d(vcl_vector<vgl_homg_point_3d<T> > points)
00015 : points_(points)
00016 {
00017 }
00018 
00019 template <class T>
00020 void vgl_fit_plane_3d<T>::add_point(vgl_homg_point_3d<T> const &p)
00021 {
00022   points_.push_back(p);
00023 }
00024 
00025 template <class T>
00026 void vgl_fit_plane_3d<T>::add_point(const T x, const T y, const T z)
00027 {
00028   points_.push_back(vgl_homg_point_3d<T> (x, y, z));
00029 }
00030 
00031  template <class T>
00032  void vgl_fit_plane_3d<T>::clear()
00033 {
00034   points_.clear();
00035 }
00036 
00037  template <class T>
00038  bool vgl_fit_plane_3d<T>::fit(const T error_marg, vcl_ostream* errstream/*=0*/)
00039 {
00040   // normalize the points
00041   vgl_norm_trans_3d<T> norm;
00042   if (!norm.compute_from_points(points_) && errstream) {
00043     *errstream << "there is a problem with norm transform\n";
00044   }
00045 
00046   // normalize the points
00047   for (unsigned i=0; i<points_.size(); i++) {
00048     vgl_homg_point_3d<T> p = points_[i];
00049     points_[i] = norm(p);
00050   }
00051 
00052   // compute the matrix A of Ax=b
00053   T A=0, B=0, C=0, D=0, E=0, F=0, G=0, H=0, I=0;
00054   unsigned n = points_.size();
00055   for (unsigned i=0; i<n; i++) {
00056     T x = points_[i].x()/points_[i].w();
00057     T y = points_[i].y()/points_[i].w();
00058     T z = points_[i].z()/points_[i].w();
00059     A += x;
00060     B += y;
00061     C += z;
00062     D += x*x;
00063     E += y*y;
00064     F += z*z;
00065     G += x*y;
00066     H += y*z;
00067     I += x*z;
00068   }
00069 
00070   vnl_matrix<T> coeff_matrix(4, 4);
00071   coeff_matrix(0, 0) = D;
00072   coeff_matrix(0, 1) = G;
00073   coeff_matrix(0, 2) = I;
00074   coeff_matrix(0, 3) = A;
00075 
00076   coeff_matrix(1, 0) = G;
00077   coeff_matrix(1, 1) = E;
00078   coeff_matrix(1, 2) = H;
00079   coeff_matrix(1, 3) = B;
00080 
00081   coeff_matrix(2, 0) = I;
00082   coeff_matrix(2, 1) = H;
00083   coeff_matrix(2, 2) = F;
00084   coeff_matrix(2, 3) = C;
00085 
00086   coeff_matrix(3, 0) = A;
00087   coeff_matrix(3, 1) = B;
00088   coeff_matrix(3, 2) = C;
00089   coeff_matrix(3, 3) = T(n);
00090 
00091   vnl_svd<T> svd(coeff_matrix);
00092   // check if the error_margin is achieved
00093   T min = svd.sigma_min();
00094   if (min > error_marg) {
00095     if (errstream) *errstream << "Error Margin " << error_marg << '<' << min << ". Could not fit the points to a plane\n";
00096     return false;
00097   }
00098 
00099   // null vector gives the solution to the linear equation where b=[0]
00100   vnl_vector<T> s = svd.nullvector();
00101 
00102   // re-transform the points back to the real world
00103   vnl_matrix_fixed<T,4,4> N=norm.get_matrix();
00104   vnl_matrix_fixed<T,4,4> N_transp = N.transpose();
00105   s = N_transp * s;
00106 
00107   T a, b, c, d;
00108   a = s.get(0);
00109   b = s.get(1);
00110   c = s.get(2);
00111   d = s.get(3);
00112   plane_ = vgl_homg_plane_3d<T> (a, b, c, d);
00113   return true;
00114 }
00115 
00116 //--------------------------------------------------------------------------
00117 #undef VGL_FIT_PLANE_3D_INSTANTIATE
00118 #define VGL_FIT_PLANE_3D_INSTANTIATE(T) \
00119 template class vgl_fit_plane_3d<T >
00120 
00121 #endif // vgl_fit_plane_3d_txx_