00001
00002 #ifndef vgl_conic_2d_regression_txx_
00003 #define vgl_conic_2d_regression_txx_
00004
00005
00006
00007 #include "vgl_conic_2d_regression.h"
00008 #include <vcl_iostream.h>
00009 #include <vcl_algorithm.h>
00010 #include <vnl/vnl_vector_fixed.h>
00011 #include <vnl/vnl_inverse.h>
00012 #include <vnl/vnl_numeric_traits.h>
00013 #include <vnl/algo/vnl_svd.h>
00014 #include <vgl/vgl_distance.h>
00015 #include <vgl/algo/vgl_homg_operators_2d.h>
00016
00017 template <class T>
00018 void vgl_conic_2d_regression<T>::init()
00019 {
00020 partial_sums_.resize(14, 0.0);
00021 npts_ = 0;
00022 Dinv_.fill(0.0);
00023 Dinv_.put(0,0,0.5); Dinv_.put(1,1,1.0); Dinv_.put(2,2,0.5);
00024 cost_ = 0;
00025 sampson_error_ = 0;
00026 }
00027
00028
00029
00030
00031 template <class T>
00032 vgl_conic_2d_regression<T>::vgl_conic_2d_regression()
00033 {
00034 this->init();
00035 }
00036
00037
00038
00039 template <class T>
00040 void vgl_conic_2d_regression<T>::clear_points()
00041 {
00042 points_.clear();
00043 npts_ = 0;
00044 }
00045
00046
00047 template <class T>
00048 T vgl_conic_2d_regression<T>::get_rms_error_est(vgl_point_2d<T> const& p) const
00049 {
00050 vgl_homg_point_2d<T> hp(p);
00051 vgl_homg_point_2d<T> hc = vgl_homg_operators_2d<T>::closest_point(conic_, p);
00052 return static_cast<T>(vgl_distance(hp, hc));
00053 }
00054
00055
00056
00057 template <class T>
00058 void vgl_conic_2d_regression<T>::set_sampson_error(T a, T b, T c, T d, T e, T f)
00059 {
00060 T sum = 0;
00061
00062 typename vcl_vector<vgl_point_2d<T> >::iterator pit;
00063 for (pit = points_.begin(); pit != points_.end(); ++pit)
00064 {
00065 T x = pit->x(), y = pit->y();
00066 T alg_dist = (a*x + b*y + d)*x + (c*y + e)*y + f;
00067 T two = static_cast<T>(2);
00068 T dx = two*a*x + b*y + d;
00069 T dy = two*c*y + b*x + e;
00070 T grad_mag_sqrd = dx*dx+dy*dy;
00071 sum += (alg_dist*alg_dist)/grad_mag_sqrd;
00072 }
00073 if (npts_)
00074 {
00075 sampson_error_ = static_cast<T>(vcl_sqrt(sum/npts_));
00076 return;
00077 }
00078 sampson_error_ = vnl_numeric_traits<T>::maxval;
00079 }
00080
00081 template <class T>
00082 void vgl_conic_2d_regression<T>::add_point(vgl_point_2d<T> const& p)
00083 {
00084 points_.push_back(p);
00085 ++npts_;
00086 }
00087
00088 template <class T>
00089 void vgl_conic_2d_regression<T>::remove_point(vgl_point_2d<T> const& p)
00090 {
00091
00092 typename vcl_vector<vgl_point_2d<T> >::iterator result;
00093 result = vcl_find(points_.begin(), points_.end(), p);
00094 if (result != points_.end())
00095 points_.erase(result);
00096 if (npts_>0)
00097 --npts_;
00098 }
00099
00100
00101 template <class T>
00102 T vgl_conic_2d_regression<T>::get_rms_algebraic_error() const
00103 {
00104 return cost_;
00105 }
00106
00107 template <class T>
00108 void vgl_conic_2d_regression<T>::compute_partial_sums()
00109 {
00110 hnorm_points_.clear();
00111
00112 vcl_vector<vgl_homg_point_2d<T> > hpoints;
00113
00114 typename vcl_vector<vgl_point_2d<T> >::iterator pit;
00115 for (pit = points_.begin(); pit != points_.end(); ++pit)
00116 {
00117 hpoints.push_back(vgl_homg_point_2d<T>(*pit));
00118 }
00119 trans_.compute_from_points(hpoints, false);
00120
00121
00122 for (typename vcl_vector<vgl_homg_point_2d<T> >::iterator pit = hpoints.begin();
00123 pit != hpoints.end(); ++pit)
00124 hnorm_points_.push_back(trans_(*pit));
00125
00126 for (typename vcl_vector<T>::iterator dit = partial_sums_.begin();
00127 dit != partial_sums_.end(); ++dit)
00128 (*dit)=0;
00129
00130 T x2,y2,x3,y3;
00131 for (typename vcl_vector<vgl_homg_point_2d<T> >::iterator pit = hnorm_points_.begin();
00132 pit != hnorm_points_.end(); ++pit)
00133 {
00134 T x = pit->x()/pit->w(),
00135 y = pit->y()/pit->w();
00136
00137 x2 = x*x; x3 = x2*x; y2 = y*y; y3 = y2*y;
00138 partial_sums_[0] += x3*x; partial_sums_[1] += x3*y;
00139 partial_sums_[2] += x2*y2; partial_sums_[3] += x*y3;
00140 partial_sums_[4] += y3*y; partial_sums_[5] += x3;
00141 partial_sums_[6] += x2*y; partial_sums_[7] += x*y2;
00142 partial_sums_[8] += y3; partial_sums_[9] += x2;
00143 partial_sums_[10] += x*y; partial_sums_[11] += y2;
00144 partial_sums_[12] += x; partial_sums_[13] += y;
00145 }
00146 }
00147
00148 template <class T>
00149 void vgl_conic_2d_regression<T>::fill_scatter_matrix()
00150 {
00151 S11_.put(0,0,partial_sums_[0]);
00152 S11_.put(0,1,partial_sums_[1]);
00153 S11_.put(0,2,partial_sums_[2]);
00154 S11_.put(1,0,partial_sums_[1]);
00155 S11_.put(1,1,partial_sums_[2]);
00156 S11_.put(1,2,partial_sums_[3]);
00157 S11_.put(2,0,partial_sums_[2]);
00158 S11_.put(2,1,partial_sums_[3]);
00159 S11_.put(2,2,partial_sums_[4]);
00160
00161 S12_.put(0,0,partial_sums_[5]);
00162 S12_.put(0,1,partial_sums_[6]);
00163 S12_.put(0,2,partial_sums_[9]);
00164 S12_.put(1,0,partial_sums_[6]);
00165 S12_.put(1,1,partial_sums_[7]);
00166 S12_.put(1,2,partial_sums_[10]);
00167 S12_.put(2,0,partial_sums_[7]);
00168 S12_.put(2,1,partial_sums_[8]);
00169 S12_.put(2,2,partial_sums_[11]);
00170
00171 S22_.put(0,0,partial_sums_[9]);
00172 S22_.put(0,1,partial_sums_[10]);
00173 S22_.put(0,2,partial_sums_[12]);
00174 S22_.put(1,0,partial_sums_[10]);
00175 S22_.put(1,1,partial_sums_[11]);
00176 S22_.put(1,2,partial_sums_[13]);
00177 S22_.put(2,0,partial_sums_[12]);
00178 S22_.put(2,1,partial_sums_[13]);
00179 T npts = static_cast<T>(npts_);
00180 S22_.put(2,2,npts);
00181 }
00182
00183 template <class T>
00184 bool vgl_conic_2d_regression<T>::fit()
00185 {
00186
00187 if (this->get_n_pts()<5)
00188 return false;
00189
00190
00191 this->compute_partial_sums();
00192
00193
00194 this->fill_scatter_matrix();
00195
00196
00197 T det = vnl_det(S22_);
00198 if (det == static_cast<T>(0))
00199 {
00200 vcl_cout << "Singular S22 Matrix in vgl_conic_2d_regression::fit()\n";
00201 return false;
00202 }
00203
00204 vnl_matrix_fixed<T,3,3> S12_T = S12_.transpose();
00205 vnl_matrix_fixed<T,3,3> S_lambda =
00206 Dinv_*(S11_- S12_*(vnl_inverse(S22_)*S12_T));
00207
00208 vnl_svd<T> svd(S_lambda.as_ref());
00209 cost_ = svd.sigma_min();
00210 vnl_vector_fixed<T,3> v1 = svd.nullvector();
00211 vnl_vector_fixed<T,3> v2 = - vnl_inverse(S22_)*S12_T*v1;
00212 vgl_conic<T> nc(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2]);
00213
00214
00215
00216
00217
00218
00219
00220
00221 conic_ = trans_(nc);
00222
00223
00224 this->set_sampson_error(conic_.a(), conic_.b(), conic_.c(),
00225 conic_.d(), conic_.e(), conic_.f());
00226
00227 return true;
00228 }
00229
00230 template <class T>
00231 void vgl_conic_2d_regression<T>::print_pointset(vcl_ostream& str)
00232 {
00233 str << "Current Pointset has " << npts_ << " points\n";
00234
00235 typename vcl_vector<vgl_point_2d<T> >::iterator pit;
00236 for (pit = points_.begin(); pit != points_.end(); ++pit)
00237 str << *pit << '\n';
00238 }
00239
00240
00241 #undef VGL_CONIC_2D_REGRESSION_INSTANTIATE
00242 #define VGL_CONIC_2D_REGRESSION_INSTANTIATE(T) \
00243 template class vgl_conic_2d_regression<T >
00244
00245 #endif // vgl_conic_2d_regression_txx_