core/vgl/algo/vgl_norm_trans_2d.txx

Go to the documentation of this file.
00001 // This is core/vgl/algo/vgl_norm_trans_2d.txx
00002 #ifndef vgl_norm_trans_2d_txx_
00003 #define vgl_norm_trans_2d_txx_
00004 //:
00005 // \file
00006 
00007 #include "vgl_norm_trans_2d.h"
00008 #include <vgl/vgl_point_2d.h>
00009 #include <vcl_iostream.h>
00010 #include <vnl/vnl_math.h>
00011 
00012 //--------------------------------------------------------------
00013 //
00014 
00015 // Default constructor
00016 template <class T>
00017 vgl_norm_trans_2d<T>::vgl_norm_trans_2d() : vgl_h_matrix_2d<T>()
00018 {
00019 }
00020 
00021 // Copy constructor
00022 template <class T>
00023 vgl_norm_trans_2d<T>::vgl_norm_trans_2d(const vgl_norm_trans_2d<T>& M)
00024 : vgl_h_matrix_2d<T>(M)
00025 {
00026 }
00027 
00028 
00029 // Constructor from vcl_istream
00030 template <class T>
00031 vgl_norm_trans_2d<T>::vgl_norm_trans_2d(vcl_istream& s)
00032 : vgl_h_matrix_2d<T>(s)
00033 {
00034 }
00035 
00036 // Constructor from file
00037 template <class T>
00038 vgl_norm_trans_2d<T>::vgl_norm_trans_2d(char const* filename)
00039 : vgl_h_matrix_2d<T>(filename)
00040 {
00041 }
00042 
00043 //--------------------------------------------------------------
00044 // Constructor
00045 template <class T>
00046 vgl_norm_trans_2d<T>::vgl_norm_trans_2d(vnl_matrix_fixed<T,3,3> const& M)
00047 : vgl_h_matrix_2d<T>(M)
00048 {
00049 }
00050 
00051 //--------------------------------------------------------------
00052 // Constructor
00053 template <class T>
00054 vgl_norm_trans_2d<T>::vgl_norm_trans_2d(const T* H)
00055 : vgl_h_matrix_2d<T>(H)
00056 {
00057 }
00058 
00059 // Destructor
00060 template <class T>
00061 vgl_norm_trans_2d<T>::~vgl_norm_trans_2d()
00062 {
00063 }
00064 
00065 // == OPERATIONS ==
00066 //----------------------------------------------------------------
00067 //: Get the normalizing transform for a set of points
00068 // - Compute the center of gravity & form the normalizing transformation matrix
00069 // - Transform the point set to a temporary collection
00070 // - Compute the average point radius
00071 // - Complete the normalizing transform
00072 template <class T>
00073 bool vgl_norm_trans_2d<T>::
00074 compute_from_points(vcl_vector<vgl_homg_point_2d<T> > const& points,
00075                     bool isotropic)
00076 {
00077   T cx, cy;
00078   this->center_of_mass(points, cx, cy);
00079   this->t12_matrix_.set_identity();
00080   this->t12_matrix_.put(0,2, -cx);    this->t12_matrix_.put(1,2, -cy);
00081   vcl_vector<vgl_homg_point_2d<T> > temp;
00082   for (typename vcl_vector<vgl_homg_point_2d<T> >::const_iterator
00083        pit = points.begin(); pit != points.end(); pit++)
00084   {
00085     vgl_homg_point_2d<T> p((*this)(*pit));
00086     temp.push_back(p);
00087   }
00088 
00089   if (isotropic) {
00090     T radius = 1;
00091     //Points might be coincident
00092     if (!this->scale_xyroot2(temp, radius))
00093       return false;
00094     T scale = 1/radius;
00095     this->t12_matrix_.put(0,0, scale);
00096     this->t12_matrix_.put(1,1, scale);
00097     this->t12_matrix_.put(0,2, -cx*scale);
00098     this->t12_matrix_.put(1,2, -cy*scale);
00099     return true;
00100   }
00101   T sdx = 1, sdy = 1, c = 1, s = 0;
00102   if (!this->scale_aniostropic(temp, sdx, sdy, c, s))
00103     return false;
00104   T scx = 1/sdx, scy = 1/sdy;
00105   this->t12_matrix_.put(0, 0, c*scx);
00106   this->t12_matrix_.put(0, 1, -s*scx);
00107   this->t12_matrix_.put(0, 2, (-c*scx*cx+s*scx*cy));
00108   this->t12_matrix_.put(1, 0, s*scy);
00109   this->t12_matrix_.put(1, 1, c*scy);
00110   this->t12_matrix_.put(1, 2, (-s*scy*cx-c*scy*cy));
00111   return true;
00112 }
00113 
00114 //-----------------------------------------------------------------
00115 //:
00116 //  The normalizing transform for lines is computed from the
00117 //  set of points defined by the intersection of the perpendicular from
00118 //  the origin with the line.  Each such point is given by:
00119 //    $p = [-a*c, -b*c, \sqrt(a^2+b^2)]^T$
00120 //  If we assume the line is normalized then:
00121 //    $p = [-a*c, -b*c, 1]^T$
00122 //
00123 template <class T>
00124 bool vgl_norm_trans_2d<T>::
00125 compute_from_lines(vcl_vector<vgl_homg_line_2d<T> > const& lines,
00126                    bool isotropic)
00127 {
00128   vcl_vector<vgl_homg_point_2d<T> > points;
00129   for (typename vcl_vector<vgl_homg_line_2d<T> >::const_iterator lit=lines.begin();
00130        lit != lines.end(); lit++)
00131   {
00132     vgl_homg_line_2d<T> l = (*lit);
00133     vgl_homg_point_2d<T> p(-l.a()*l.c(), -l.b()*l.c(), l.a()*l.a()+l.b()*l.b());
00134     points.push_back(p);
00135   }
00136   return this->compute_from_points(points, isotropic);
00137 }
00138 
00139 //-----------------------------------------------------------------
00140 //:
00141 // The normalizing transform for points and lines is computed from the set of
00142 // points used by compute_from_points() & the one used by compute_from_lines().
00143 //
00144 template <class T>
00145 bool vgl_norm_trans_2d<T>::
00146 compute_from_points_and_lines(vcl_vector<vgl_homg_point_2d<T> > const& pts,
00147                               vcl_vector<vgl_homg_line_2d< T> > const& lines,
00148                               bool isotropic)
00149 {
00150   vcl_vector<vgl_homg_point_2d<T> > points = pts;
00151   for (typename vcl_vector<vgl_homg_line_2d<T> >::const_iterator lit=lines.begin();
00152        lit != lines.end(); lit++)
00153   {
00154     vgl_homg_line_2d<T> l = (*lit);
00155     vgl_homg_point_2d<T> p(-l.a()*l.c(), -l.b()*l.c(), l.a()*l.a()+l.b()*l.b());
00156     points.push_back(p);
00157   }
00158   return this->compute_from_points(points, isotropic);
00159 }
00160 
00161 //-------------------------------------------------------------------
00162 // Find the center of a point cloud
00163 //
00164 template <class T>
00165 void vgl_norm_trans_2d<T>::
00166 center_of_mass(vcl_vector<vgl_homg_point_2d<T> > const& in, T& cx, T& cy)
00167 {
00168   T cog_x = 0;
00169   T cog_y = 0;
00170   T cog_count = 0.0;
00171   T tol = static_cast<T>(1e-06);
00172   unsigned n = in.size();
00173   for (unsigned i = 0; i < n; ++i)
00174   {
00175     if (in[i].ideal(tol))
00176       continue;
00177     vgl_point_2d<T> p(in[i]);
00178     T x = p.x();
00179     T y = p.y();
00180     cog_x += x;
00181     cog_y += y;
00182     ++cog_count;
00183   }
00184   if (cog_count > 0)
00185   {
00186     cog_x /= cog_count;
00187     cog_y /= cog_count;
00188   }
00189   //output result
00190   cx = cog_x;
00191   cy = cog_y;
00192 }
00193 
00194 //-------------------------------------------------------------------
00195 // Find the mean distance of the input pointset. Assumed to have zero mean
00196 //
00197 template <class T>
00198 bool vgl_norm_trans_2d<T>::
00199 scale_xyroot2(vcl_vector<vgl_homg_point_2d<T> > const& in, T& radius)
00200 {
00201   T magnitude = T(0);
00202   int numfinite = 0;
00203   T tol = T(1e-06);
00204   radius = T(0);
00205   for (unsigned i = 0; i < in.size(); ++i)
00206   {
00207     if (in[i].ideal(tol))
00208       continue;
00209     vgl_point_2d<T> p(in[i]);
00210     magnitude += vnl_math_hypot(p.x(),p.y());
00211     ++numfinite;
00212   }
00213 
00214   if (numfinite > 0)
00215   {
00216     radius = T(magnitude / (numfinite*vnl_math::sqrt2));
00217     return radius>=tol;
00218   }
00219   return false;
00220 }
00221 
00222 //------------------------------------------------------------
00223 // Anisotropic scaling of the point set around the center of gravity.
00224 // Determines the principal axes and standard deviations along the principal
00225 // axes.  Assumes that the pointset has zero mean, so ::center_of_mass should
00226 // be removed before calling this function.
00227 template <class T>
00228 bool vgl_norm_trans_2d<T>::
00229 scale_aniostropic(vcl_vector<vgl_homg_point_2d<T> > const& in,
00230                   T& sdx, T& sdy, T& c, T& s)
00231 {
00232   T tol = T(1e-06);
00233   unsigned count = 0;
00234   unsigned n = in.size();
00235   //The point scatter matrix coefficients
00236   double Sx2=0, Sxy=0, Sy2=0;
00237   for (unsigned i = 0; i < n; ++i)
00238   {
00239     if (in[i].ideal(tol))
00240       continue;
00241     ++count;
00242     vgl_point_2d<T> p(in[i]);
00243     T x = p.x();
00244     T y = p.y();
00245     Sx2 += (double)x*x;
00246     Sxy += (double)x*y;
00247     Sy2 += (double)y*y;
00248   }
00249   if (!count)
00250     return false;
00251 
00252   double t =0.0;
00253   // Compute the rotation that makes Sxy zero
00254   if ( Sx2 != Sy2 )
00255     t = 0.5*vcl_atan( -2.0*Sxy/(Sx2-Sy2) );
00256 
00257   double dc = vcl_cos(t),  ds = vcl_sin(t);
00258 
00259   /* determine the standard deviations in the rotated frame */
00260   double sddx = vcl_sqrt( (dc*dc*Sx2-2.0*dc*ds*Sxy+ds*ds*Sy2)/count );
00261   double sddy = vcl_sqrt( (ds*ds*Sx2+2.0*dc*ds*Sxy+dc*dc*Sy2)/count );
00262 
00263   //cast back to T
00264   sdx = static_cast<T>(sddx);
00265   sdy = static_cast<T>(sddy);
00266   c = static_cast<T>(dc);
00267   s = static_cast<T>(ds);
00268   return sdx>tol && sdy >tol;
00269 }
00270 
00271 //----------------------------------------------------------------------------
00272 #undef VGL_NORM_TRANS_2D_INSTANTIATE
00273 #define VGL_NORM_TRANS_2D_INSTANTIATE(T) \
00274 template class vgl_norm_trans_2d<T >
00275 
00276 #endif // vgl_norm_trans_2d_txx_

Generated on Mon Mar 8 05:07:50 2010 for core/vgl by  doxygen 1.5.1