00001 #include "rrel_quad_est.h"
00002
00003 #include <vnl/vnl_matrix.h>
00004 #include <vnl/vnl_vector.h>
00005 #include <vnl/algo/vnl_svd.h>
00006 #include <vgl/vgl_point_2d.h>
00007
00008 #include <vcl_iostream.h>
00009 #include <vcl_vector.h>
00010 #include <vcl_cassert.h>
00011 #include <vcl_algorithm.h>
00012
00013 rrel_quad_est::
00014 rrel_quad_est( const vcl_vector< vgl_point_2d<double> > & from_pts,
00015 const vcl_vector< vgl_point_2d<double> > & to_pts )
00016 : rrel_estimation_problem( 12, 6 )
00017 {
00018 assert( from_pts.size() == to_pts.size() );
00019
00020 const unsigned dim = 2;
00021 const unsigned size = from_pts.size();
00022
00023
00024 vnl_vector<double> pt( dim );
00025 for ( unsigned int i=0; i<size; ++i ) {
00026 pt[0] = from_pts[i].x();
00027 pt[1] = from_pts[i].y();
00028 from_pts_[i] = pt;
00029 pt[0] = to_pts[i].x();
00030 pt[1] = to_pts[i].y();
00031 to_pts_[i] = pt;
00032 }
00033
00034 dim_ = dim;
00035 quad_dof_ = (dim+1)*dim;
00036 min_num_pts_ = dim+1;
00037 num_samples_ = size;
00038 }
00039
00040 rrel_quad_est::
00041 rrel_quad_est( const vcl_vector< vnl_vector<double> > & from_pts,
00042 const vcl_vector< vnl_vector<double> > & to_pts,
00043 unsigned int dim )
00044 : rrel_estimation_problem( ((dim+3)*dim/2+1)*dim ,
00045 ((dim+3)*dim/2+1) ),
00046 from_pts_( from_pts ), to_pts_( to_pts )
00047 {
00048
00049 assert( dim == 2 );
00050 assert( from_pts.size() == to_pts.size() );
00051 const unsigned size = from_pts.size();
00052
00053 dim_ = dim;
00054 quad_dof_ = ((dim+3)*dim/2+1)*dim;
00055 min_num_pts_ = (dim+3)*dim/2+1;
00056 num_samples_ = size;
00057 }
00058
00059 rrel_quad_est::~rrel_quad_est()
00060 {
00061 }
00062
00063
00064 unsigned int
00065 rrel_quad_est::num_samples( ) const
00066 {
00067 return num_samples_;
00068 }
00069
00070 inline
00071 void expand_quad( const vnl_vector<double>& s,
00072 vnl_vector<double>& des,
00073 unsigned ind=0)
00074 {
00075
00076 des(ind++) = 1.0;
00077
00078
00079 for ( unsigned int i=0; i<s.size(); ++i )
00080 des(ind++) = s(i);
00081
00082
00083 for ( unsigned int i=0; i<s.size()-1; ++i )
00084 for ( unsigned int j=i+1; j<s.size(); ++j )
00085 des(ind++) = s(i) * s(j);
00086
00087
00088 for ( unsigned int i=0; i<s.size(); ++i )
00089 des(ind++) = s(i)*s(i);
00090 }
00091
00092 inline
00093 void copy_to_nth_pos( vnl_vector<double>& des, unsigned c,
00094 const vnl_vector<double> s )
00095 {
00096 for ( unsigned int i=0; i<s.size(); ++i )
00097 des(c+i) = s(i);
00098 }
00099
00100 vnl_matrix<double>
00101 rrel_quad_est::
00102 A( const vnl_vector<double>& params ) const
00103 {
00104 vnl_matrix<double> A( dim_, min_num_pts_, 0.0 );
00105 for ( unsigned ind=0,i=0; i<min_num_pts_; ++i )
00106 for ( unsigned j=0; j<dim_; ++j )
00107 A(j, i) = params(ind++);
00108 return A;
00109 }
00110
00111 vnl_vector<double>
00112 rrel_quad_est::
00113 trans( const vnl_vector<double>& params ) const
00114 {
00115 vnl_vector<double> trans( dim_, 0.0 );
00116 for ( unsigned int i=0; i<dim_; ++i ) {
00117 trans[i] = params( i );
00118 }
00119 return trans;
00120 }
00121
00122
00123
00124
00125
00126
00127 bool
00128 rrel_quad_est::
00129 fit_from_minimal_set( const vcl_vector<int>& point_indices,
00130 vnl_vector<double>& params ) const
00131 {
00132 if ( point_indices.size() != min_num_pts_ ) {
00133 vcl_cerr << "rrel_quad_est::fit_from_minimal_sample The number of point "
00134 << "indices must agree with the fit degrees of freedom.\n";
00135 return false;
00136 }
00137
00138 vnl_matrix<double> A( min_num_pts_, min_num_pts_, 1.0 );
00139 vnl_matrix<double> bs( min_num_pts_, dim_, 0.0 );
00140 vnl_vector<double> expanded( min_num_pts_ );
00141 for ( unsigned int i=0; i<min_num_pts_; ++i ) {
00142 int index = point_indices[i];
00143 expand_quad( from_pts_[index], expanded );
00144 A.set_row( i, expanded );
00145
00146 const vnl_vector<double>& one_to = to_pts_[index];
00147 for ( unsigned int j=0; j<dim_; ++j )
00148 bs[i][j] = one_to[j];
00149 }
00150
00151 vnl_svd<double> svd( A, 1.0e-8 );
00152 if ( (unsigned int)svd.rank() < min_num_pts_ ) {
00153 return false;
00154 }
00155 else {
00156 params.set_size( quad_dof_ );
00157 vnl_matrix<double> sol;
00158 sol = svd.inverse() * bs;
00159 for ( unsigned int j=0; j<min_num_pts_; ++j )
00160 copy_to_nth_pos( params, j*dim_, sol.get_row(j) );
00161 return true;
00162 }
00163 }
00164
00165
00166 void
00167 rrel_quad_est::compute_residuals( const vnl_vector<double>& params,
00168 vcl_vector<double>& residuals ) const
00169 {
00170 assert( residuals.size() == num_samples_ );
00171
00172 vnl_matrix<double> A( dim_, min_num_pts_ );
00173 for ( unsigned ind=0,i=0; i<min_num_pts_; ++i )
00174 for ( unsigned j=0; j<dim_; ++j )
00175 A(j, i) = params(ind++);
00176
00177 vnl_vector<double> diff;
00178 vnl_vector<double> expanded( min_num_pts_, 0.0 );
00179 for ( unsigned int i=0; i<num_samples_; ++i ) {
00180 expand_quad( from_pts_[i], expanded );
00181 diff = A * expanded;
00182 diff -= to_pts_[i];
00183 residuals[i] = diff.two_norm();
00184 }
00185 }
00186
00187
00188 bool
00189 rrel_quad_est::
00190 weighted_least_squares_fit( vnl_vector<double>& params,
00191 vnl_matrix<double>& norm_covar,
00192 const vcl_vector<double>* weights ) const
00193 {
00194 vnl_matrix<double> sumProds(min_num_pts_, min_num_pts_, 0.0);
00195 vnl_matrix<double> sumDists(min_num_pts_, dim_, 0.0);
00196
00197 vcl_vector<double> tmp_wgts;
00198 if ( !weights ) {
00199
00200 tmp_wgts.resize( num_samples_ );
00201 vcl_fill( tmp_wgts.begin(), tmp_wgts.end(), 1.0 );
00202 weights = &tmp_wgts;
00203 }
00204
00205
00206 vnl_vector<double> ind_vars( min_num_pts_, 1.0 );
00207 for ( unsigned int i=0; i<num_samples_; ++i ) {
00208
00209 expand_quad( from_pts_[i], ind_vars );
00210 for ( unsigned int j=0; j<min_num_pts_; ++j ) {
00211 for ( unsigned int k=j; k<min_num_pts_; k++ )
00212 sumProds(j,k) += ind_vars[j] * ind_vars[k] * (*weights)[i];
00213
00214
00215 for ( unsigned int k=0; k<dim_; ++k )
00216 sumDists(j,k) += ind_vars[j] * to_pts_[i][k] * (*weights)[i];
00217 }
00218 }
00219
00220 for ( unsigned int j=1; j<min_num_pts_; j++ )
00221 for ( unsigned int k=0; k<j; k++ )
00222 sumProds(j,k) = sumProds(k,j);
00223
00224 vnl_svd<double> svd( sumProds, 1.0e-8 );
00225 if ( (unsigned int)svd.rank() < min_num_pts_ ) {
00226 vcl_cerr << "rrel_quad_est::WeightedLeastSquaresFit --- singularity!\n";
00227 return false;
00228 }
00229 else {
00230 vnl_matrix<double> sumP_inv( svd.inverse() );
00231 vnl_matrix<double> int_result = sumP_inv * sumDists;
00232 norm_covar = sumP_inv;
00233
00234 params.set_size( quad_dof_ );
00235 for ( unsigned int j=0; j<min_num_pts_; ++j )
00236 copy_to_nth_pos( params, j*dim_, int_result.get_row(j) );
00237 return true;
00238 }
00239 }