vgl_norm_trans_2d.hxx
Go to the documentation of this file.
1 // This is core/vgl/algo/vgl_norm_trans_2d.hxx
2 #ifndef vgl_norm_trans_2d_hxx_
3 #define vgl_norm_trans_2d_hxx_
4 //:
5 // \file
6 
7 #include <iostream>
8 #include "vgl_norm_trans_2d.h"
9 #include <vgl/vgl_point_2d.h>
10 #ifdef _MSC_VER
11 # include <vcl_msvc_warnings.h>
12 #endif
13 #include <vnl/vnl_math.h>
14 
15 //--------------------------------------------------------------
16 //
17 
18 // Default constructor
19 template <class T>
21 {
22 }
23 
24 // Copy constructor
25 template <class T>
27 : vgl_h_matrix_2d<T>(M)
28 {
29 }
30 
31 
32 // Constructor from std::istream
33 template <class T>
35 : vgl_h_matrix_2d<T>(s)
36 {
37 }
38 
39 // Constructor from file
40 template <class T>
42 : vgl_h_matrix_2d<T>(filename)
43 {
44 }
45 
46 //--------------------------------------------------------------
47 // Constructor
48 template <class T>
49 vgl_norm_trans_2d<T>::vgl_norm_trans_2d(vnl_matrix_fixed<T,3,3> const& M)
50 : vgl_h_matrix_2d<T>(M)
51 {
52 }
53 
54 //--------------------------------------------------------------
55 // Constructor
56 template <class T>
58 : vgl_h_matrix_2d<T>(H)
59 {
60 }
61 
62 // Destructor
63 template <class T>
65 
66 // == OPERATIONS ==
67 //----------------------------------------------------------------
68 //: Get the normalizing transform for a set of points
69 // - Compute the center of gravity & form the normalizing transformation matrix
70 // - Transform the point set to a temporary collection
71 // - Compute the average point radius
72 // - Complete the normalizing transform
73 template <class T>
75 compute_from_points(std::vector<vgl_homg_point_2d<T> > const& points,
76  bool isotropic)
77 {
78  T cx, cy;
79  this->center_of_mass(points, cx, cy);
81  std::vector<vgl_homg_point_2d<T> > temp;
82  for (typename std::vector<vgl_homg_point_2d<T> >::const_iterator
83  pit = points.begin(); pit != points.end(); pit++)
84  {
85  vgl_homg_point_2d<T> p((*this)(*pit));
86  temp.push_back(p);
87  }
88 
89  if (isotropic) {
90  T radius = T(1);
91  //Points might be coincident
92  if (!this->scale_xyroot2(temp, radius))
93  return false;
94  vgl_h_matrix_2d<T>::set_scale(T(1)/radius);
95  return true;
96  }
97  T sdx = 1, sdy = 1, c = 1, s = 0;
98  if (!this->scale_aniostropic(temp, sdx, sdy, c, s))
99  return false;
100  T scx = 1/sdx, scy = 1/sdy;
101  T data[] = { c*scx, -s*scx, -c*scx*cx +s*scx*cy,
102  s*scy, c*scy, -s*scy*cx -c*scy*cy };
103  vgl_h_matrix_2d<T>::set_affine(vnl_matrix_fixed<T,2,3>(data));
104  return true;
105 }
106 
107 //-----------------------------------------------------------------
108 //:
109 // The normalizing transform for lines is computed from the
110 // set of points defined by the intersection of the perpendicular from
111 // the origin with the line. Each such point is given by:
112 // $p = [-a*c, -b*c, \sqrt(a^2+b^2)]^T$
113 // If we assume the line is normalized then:
114 // $p = [-a*c, -b*c, 1]^T$
115 //
116 template <class T>
118 compute_from_lines(std::vector<vgl_homg_line_2d<T> > const& lines,
119  bool isotropic)
120 {
121  std::vector<vgl_homg_point_2d<T> > points;
122  for (typename std::vector<vgl_homg_line_2d<T> >::const_iterator lit=lines.begin();
123  lit != lines.end(); lit++)
124  {
125  vgl_homg_line_2d<T> l = (*lit);
126  vgl_homg_point_2d<T> p(-l.a()*l.c(), -l.b()*l.c(), l.a()*l.a()+l.b()*l.b());
127  points.push_back(p);
128  }
129  return this->compute_from_points(points, isotropic);
130 }
131 
132 //-----------------------------------------------------------------
133 //:
134 // The normalizing transform for points and lines is computed from the set of
135 // points used by compute_from_points() & the one used by compute_from_lines().
136 //
137 template <class T>
140  std::vector<vgl_homg_line_2d< T> > const& lines,
141  bool isotropic)
142 {
143  std::vector<vgl_homg_point_2d<T> > points = pts;
144  for (typename std::vector<vgl_homg_line_2d<T> >::const_iterator lit=lines.begin();
145  lit != lines.end(); lit++)
146  {
147  vgl_homg_line_2d<T> l = (*lit);
148  vgl_homg_point_2d<T> p(-l.a()*l.c(), -l.b()*l.c(), l.a()*l.a()+l.b()*l.b());
149  points.push_back(p);
150  }
151  return this->compute_from_points(points, isotropic);
152 }
153 
154 //-------------------------------------------------------------------
155 // Find the center of a point cloud
156 //
157 template <class T>
159 center_of_mass(std::vector<vgl_homg_point_2d<T> > const& in, T& cx, T& cy)
160 {
161  T cog_x = 0;
162  T cog_y = 0;
163  T cog_count = 0.0;
164  T tol = static_cast<T>(1e-06);
165  unsigned n = in.size();
166  for (unsigned i = 0; i < n; ++i)
167  {
168  if (in[i].ideal(tol))
169  continue;
170  vgl_point_2d<T> p(in[i]);
171  T x = p.x();
172  T y = p.y();
173  cog_x += x;
174  cog_y += y;
175  ++cog_count;
176  }
177  if (cog_count > 0)
178  {
179  cog_x /= cog_count;
180  cog_y /= cog_count;
181  }
182  //output result
183  cx = cog_x;
184  cy = cog_y;
185 }
186 
187 //-------------------------------------------------------------------
188 // Find the mean distance of the input pointset. Assumed to have zero mean
189 //
190 template <class T>
192 scale_xyroot2(std::vector<vgl_homg_point_2d<T> > const& in, T& radius)
193 {
194  T magnitude = T(0);
195  int numfinite = 0;
196  T tol = T(1e-06);
197  radius = T(0);
198  for (unsigned i = 0; i < in.size(); ++i)
199  {
200  if (in[i].ideal(tol))
201  continue;
202  vgl_point_2d<T> p(in[i]);
203  magnitude += vnl_math::hypot(p.x(),p.y());
204  ++numfinite;
205  }
206 
207  if (numfinite > 0)
208  {
209  radius = T(magnitude / (numfinite*vnl_math::sqrt2));
210  return radius>=tol;
211  }
212  return false;
213 }
214 
215 //------------------------------------------------------------
216 // Anisotropic scaling of the point set around the center of gravity.
217 // Determines the principal axes and standard deviations along the principal
218 // axes. Assumes that the pointset has zero mean, so ::center_of_mass should
219 // be removed before calling this function.
220 template <class T>
222 scale_aniostropic(std::vector<vgl_homg_point_2d<T> > const& in,
223  T& sdx, T& sdy, T& c, T& s)
224 {
225  T tol = T(1e-06);
226  unsigned count = 0;
227  unsigned n = in.size();
228  //The point scatter matrix coefficients
229  double Sx2=0, Sxy=0, Sy2=0;
230  for (unsigned i = 0; i < n; ++i)
231  {
232  if (in[i].ideal(tol))
233  continue;
234  ++count;
235  vgl_point_2d<T> p(in[i]);
236  T x = p.x();
237  T y = p.y();
238  Sx2 += (double)x*x;
239  Sxy += (double)x*y;
240  Sy2 += (double)y*y;
241  }
242  if (!count)
243  return false;
244 
245  double t =0.0;
246  // Compute the rotation that makes Sxy zero
247  if ( Sx2 != Sy2 )
248  t = 0.5*std::atan( -2.0*Sxy/(Sx2-Sy2) );
249 
250  double dc = std::cos(t), ds = std::sin(t);
251 
252  /* determine the standard deviations in the rotated frame */
253  double sddx = std::sqrt( (dc*dc*Sx2-2.0*dc*ds*Sxy+ds*ds*Sy2)/count );
254  double sddy = std::sqrt( (ds*ds*Sx2+2.0*dc*ds*Sxy+dc*dc*Sy2)/count );
255 
256  //cast back to T
257  sdx = static_cast<T>(sddx);
258  sdy = static_cast<T>(sddy);
259  c = static_cast<T>(dc);
260  s = static_cast<T>(ds);
261  return sdx>tol && sdy >tol;
262 }
263 
264 //----------------------------------------------------------------------------
265 #undef VGL_NORM_TRANS_2D_INSTANTIATE
266 #define VGL_NORM_TRANS_2D_INSTANTIATE(T) \
267 template class vgl_norm_trans_2d<T >
268 
269 #endif // vgl_norm_trans_2d_hxx_
A class to hold a plane-to-plane projective transformation matrix and to perform common operations us...
Definition: vgl_algo_fwd.h:11
a point in 2D nonhomogeneous space
Represents a homogeneous 2D line.
Definition: vgl_fwd.h:14
vgl_h_matrix_2d & set_affine(vnl_matrix_fixed< T, 2, 3 > const &M23)
set the transform to a general affine transform matrix.
static bool scale_aniostropic(std::vector< vgl_homg_point_2d< T > > const &in, T &sdx, T &sdy, T &c, T &s)
The similarity transform that normalizes a point set.
static void center_of_mass(std::vector< vgl_homg_point_2d< T > > const &points, T &cx, T &cy)
bool compute_from_lines(std::vector< vgl_homg_line_2d< T > > const &lines, bool isotropic=true)
The normalizing transform for lines is computed from the set of points defined by the intersection of...
Type & y()
Definition: vgl_point_2d.h:72
bool compute_from_points_and_lines(std::vector< vgl_homg_point_2d< T > > const &pts, std::vector< vgl_homg_line_2d< T > > const &lines, bool isotropic=true)
The normalizing transform for points and lines is computed from the set of points used by compute_fro...
bool compute_from_points(std::vector< vgl_homg_point_2d< T > > const &points, bool isotropic=true)
compute the normalizing transform.
#define l
vgl_h_matrix_2d & set_translation(T tx, T ty)
set H[0][2] = tx and H[1][2] = ty, other elements unaltered.
vgl_h_matrix_2d & set_scale(T scale)
compose the current transform with a uniform scaling transformation, S.
Represents a homogeneous 2D point.
Definition: vgl_fwd.h:8
vgl_h_matrix_2d & set_identity()
initialize the transformation to identity.
Type & x()
Definition: vgl_point_2d.h:71
static bool scale_xyroot2(std::vector< vgl_homg_point_2d< T > > const &in, T &radius)