vgl_line_2d_regression.hxx
Go to the documentation of this file.
1 // This is core/vgl/algo/vgl_line_2d_regression.hxx
2 #ifndef vgl_line_2d_regression_hxx_
3 #define vgl_line_2d_regression_hxx_
4 //:
5 // \file
6 
7 #include <cmath>
8 #include <iostream>
10 #ifdef _MSC_VER
11 # include <vcl_msvc_warnings.h>
12 #endif
13 #include <vgl/vgl_distance.h>
14 #include <vnl/vnl_matrix_fixed.h>
15 #include <vnl/algo/vnl_symmetric_eigensystem.h>
16 #include <cassert>
17 
18 //: Constructor
19 template <class T>
21 {
22  this->clear();
23 }
24 
25 //: Add a point to the current regression sums
26 template <class T>
28 {
29  Sx_ += x;
30  Sy_ += y;
31  Sxx_ += x*x;
32  Sxy_ += x*y;
33  Syy_ += y*y;
34  ++npts_;
35 }
36 
37 //: Remove a point from the current regression sums
38 template <class T>
40 {
41  assert(npts_!=0);
42  Sx_ -= x;
43  Sy_ -= y;
44  Sxx_ -= x*x;
45  Sxy_ -= x*y;
46  Syy_ -= y*y;
47  --npts_;
48 }
49 
50 //: Clear the regression sums
51 template <class T>
53 {
54  Sx_ = 0;
55  Sy_ = 0;
56  Sxx_ = 0;
57  Sxy_ = 0;
58  Syy_ = 0;
59  npts_=0;
60  squared_error_=0;
61 }
62 
63 //: Fit a line to the current regression data
64 template <class T>
66 {
67  if (npts_<2)
68  return false;
69 
70  vnl_matrix_fixed<T, 2, 2> M;
71  M(0, 0) = Sxx_-Sx_*Sx_/npts_;
72  M(0, 1) = M(1, 0) = Sxy_-Sx_*Sy_/npts_;
73  M(1, 1) = Syy_-Sy_*Sy_/npts_;
74 
75  vnl_symmetric_eigensystem<T> sym(M.as_ref()); // size 2x2
76  T a = sym.V(0,0);
77  T b = sym.V(1,0);
78  T c = -(a*Sx_/npts_ + b*Sy_/npts_);
79  line_= vgl_line_2d<T>(a,b,c);
80 
81  return true;
82 }
83 
84 template <class T>
86 {
87  if (npts_<1)
88  {
89  std::cout << "In vgl_line_2d_regression<T>::fit_constrained() - less than 1 point\n";
90  return false;
91  }
92  vnl_matrix_fixed<T, 2, 2> M;
93  M(0, 0) = Sxx_-2*Sx_*x +npts_*x*x;
94  M(0, 1) = M(1, 0) = Sxy_-Sx_*y-x*Sy_+npts_*x*y;
95  M(1, 1) = Syy_-2*Sy_*y+npts_*y*y;
96  vnl_symmetric_eigensystem<T> sym(M.as_ref()); // size 2x2
97  T a = sym.V(0,0);
98  T b = sym.V(1,0);
99  T c = -(a*x + b*y);
100  line_= vgl_line_2d<T>(a,b,c);
101  return true;
102 }
103 
104 template <class T>
105 double vgl_line_2d_regression<T>::get_rms_error(const T a, const T b, const T c)
106 {
107  if (npts_==0)
108  return 0;
109  double t0 = Sxx_*a*a + 2*Sxy_*a*b + Syy_*b*b;
110  double t1 = 2*Sx_*a*c + 2*Sy_*b*c + npts_*c*c;
111  double rms = std::sqrt(std::fabs(t0+t1)/((a*a+b*b)*npts_));
112  return rms;
113 }
114 
115 template <class T>
117 {
118  return this->get_rms_error(line_.a(), line_.b(), line_.c());
119 }
120 
121 //==================================================================
122 //:
123 // We want to add points to the regression until it is likely that
124 // the fitting error has been exceeded.
125 //
126 // \verbatim
127 // squared_error_ = squared_error_ + d^2
128 // ---------------------
129 // npts_+1
130 // \endverbatim
131 //===================================================================
132 // Initialize the recursive estimation of fitting error
133 template <class T>
135 {
136  squared_error_ = this->get_rms_error();
137  squared_error_ *=squared_error_;
138  squared_error_ *= npts_;
139 }
140 
141 //: estimate of the fitting error if a new point is added.
142 // Worst case is distance from the point, (x, y) to the current line.
143 // Add the error to the accumulating estimation sum.
144 template <class T>
146  bool increment)
147 {
148  if (npts_==0)
149  return 0;
150  double d = vgl_distance(p, line_);
151  double ds = d*d;
152  if (increment)
153  squared_error_ = squared_error_ + ds;
154  return std::sqrt(squared_error_/(npts_+1));
155 }
156 
157 //----------------------------------------------------------------------------
158 #undef VGL_LINE_2D_REGRESSION_INSTANTIATE
159 #define VGL_LINE_2D_REGRESSION_INSTANTIATE(T) \
160 template class vgl_line_2d_regression<T >
161 
162 #endif // vgl_line_2d_regression_hxx_
bool fit()
Fit a line to the current point set.
double get_rms_error_est(vgl_point_2d< T > const &p, bool increment=true)
Get estimated fitting error if the point (x, y) were added to the fit.
void increment_partial_sums(const T x, const T y)
Add a point to the 2d_regression.
void init_rms_error_est()
Initialize estimated fitting error.
void clear()
Clear 2d_regression sums.
void decrement_partial_sums(const T x, const T y)
Remove a point from the 2d_regression.
double get_rms_error()
Get fitting error for current fitted line.
A helper class for line fitting.
bool fit_constrained(T x, T y)
Fit a line to the current point set constrained to pass through (x,y).
double vgl_distance(vgl_point_2d< T >const &p1, vgl_point_2d< T >const &p2)
return the distance between two points.
Definition: vgl_distance.h:104
Set of distance functions.