00001
00002 #include "vpgl_bundle_adjust_lsqr.h"
00003
00004
00005
00006 #include <vnl/vnl_vector_ref.h>
00007 #include <vnl/vnl_double_3.h>
00008
00009 #include <vcl_iostream.h>
00010 #include <vcl_algorithm.h>
00011 #include <vcl_cassert.h>
00012
00013
00014
00015 vpgl_bundle_adjust_lsqr::
00016 vpgl_bundle_adjust_lsqr(unsigned int num_params_per_a,
00017 unsigned int num_params_per_b,
00018 unsigned int num_params_c,
00019 const vcl_vector<vgl_point_2d<double> >& image_points,
00020 const vcl_vector<vcl_vector<bool> >& mask)
00021 : vnl_sparse_lst_sqr_function(mask.size(),num_params_per_a,
00022 mask[0].size(),num_params_per_b,
00023 num_params_c,mask,2,use_gradient,use_weights),
00024 image_points_(image_points),
00025 use_covars_(false),
00026 scale2_(1.0),
00027 iteration_count_(0)
00028 {
00029 }
00030
00031
00032
00033
00034
00035
00036 vpgl_bundle_adjust_lsqr::
00037 vpgl_bundle_adjust_lsqr(unsigned int num_params_per_a,
00038 unsigned int num_params_per_b,
00039 unsigned int num_params_c,
00040 const vcl_vector<vgl_point_2d<double> >& image_points,
00041 const vcl_vector<vnl_matrix<double> >& inv_covars,
00042 const vcl_vector<vcl_vector<bool> >& mask)
00043 : vnl_sparse_lst_sqr_function(mask.size(),num_params_per_a,
00044 mask[0].size(),num_params_per_b,
00045 num_params_c,mask,2,use_gradient,use_weights),
00046 image_points_(image_points),
00047 use_covars_(true),
00048 scale2_(1.0),
00049 iteration_count_(0)
00050 {
00051 assert(image_points.size() == inv_covars.size());
00052 vnl_matrix<double> U(2,2,0.0);
00053 for (unsigned i=0; i<inv_covars.size(); ++i)
00054 {
00055 const vnl_matrix<double>& S = inv_covars[i];
00056 if (S(0,0) > 0.0) {
00057 U(0,0) = vcl_sqrt(S(0,0));
00058 U(0,1) = S(0,1)/U(0,0);
00059 double U11 = S(1,1)-S(0,1)*S(0,1)/S(0,0);
00060 U(1,1) = (U11>0.0)?vcl_sqrt(U11):0.0;
00061 }
00062 else if (S(1,1) > 0.0) {
00063 assert(S(0,1) == 0.0);
00064 U(0,0) = 0.0;
00065 U(0,1) = 0.0;
00066 U(1,1) = vcl_sqrt(S(1,1));
00067 }
00068 else {
00069 vcl_cout << "warning: not positive definite"<<vcl_endl;
00070 U.fill(0.0);
00071 }
00072 factored_inv_covars_.push_back(U);
00073 }
00074 }
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 void
00085 vpgl_bundle_adjust_lsqr::f(vnl_vector<double> const& a,
00086 vnl_vector<double> const& b,
00087 vnl_vector<double> const& c,
00088 vnl_vector<double>& e)
00089 {
00090 typedef vnl_crs_index::sparse_vector::iterator sv_itr;
00091 for (unsigned int i=0; i<number_of_a(); ++i)
00092 {
00093
00094 vnl_double_3x4 Pi = param_to_cam_matrix(i,a,c);
00095
00096 vnl_crs_index::sparse_vector row = residual_indices_.sparse_row(i);
00097 for (sv_itr r_itr=row.begin(); r_itr!=row.end(); ++r_itr)
00098 {
00099 unsigned int j = r_itr->second;
00100 unsigned int k = r_itr->first;
00101
00102
00103 vnl_vector_fixed<double,4> Xj = param_to_pt_vector(j,b,c);
00104
00105
00106 vnl_vector_fixed<double,3> xij = Pi*Xj;
00107
00108 double* eij = e.data_block()+index_e(k);
00109 eij[0] = xij[0]/xij[2] - image_points_[k].x();
00110 eij[1] = xij[1]/xij[2] - image_points_[k].y();
00111 if (use_covars_){
00112
00113 const vnl_matrix<double>& Sij = factored_inv_covars_[k];
00114 eij[0] *= Sij(0,0);
00115 eij[0] += eij[1]*Sij(0,1);
00116 eij[1] *= Sij(1,1);
00117 }
00118 }
00119 }
00120 }
00121
00122
00123
00124
00125
00126 void
00127 vpgl_bundle_adjust_lsqr::fij(int i, int j,
00128 vnl_vector<double> const& ai,
00129 vnl_vector<double> const& bj,
00130 vnl_vector<double> const& c,
00131 vnl_vector<double>& fij)
00132 {
00133
00134 vnl_double_3x4 Pi = param_to_cam_matrix(i,ai.data_block(),c);
00135
00136
00137 vnl_vector_fixed<double,4> Xj = param_to_pt_vector(j,bj.data_block(),c);
00138
00139
00140 vnl_vector_fixed<double,3> xij = Pi*Xj;
00141
00142 int k = residual_indices_(i,j);
00143 fij[0] = xij[0]/xij[2] - image_points_[k].x();
00144 fij[1] = xij[1]/xij[2] - image_points_[k].y();
00145 if (use_covars_){
00146
00147 const vnl_matrix<double>& Sij = factored_inv_covars_[k];
00148 fij[0] *= Sij(0,0);
00149 fij[0] += fij[1]*Sij(0,1);
00150 fij[1] *= Sij(1,1);
00151 }
00152 }
00153
00154
00155
00156 void
00157 vpgl_bundle_adjust_lsqr::jac_blocks(vnl_vector<double> const& a,
00158 vnl_vector<double> const& b,
00159 vnl_vector<double> const& c,
00160 vcl_vector<vnl_matrix<double> >& A,
00161 vcl_vector<vnl_matrix<double> >& B,
00162 vcl_vector<vnl_matrix<double> >& C)
00163 {
00164 typedef vnl_crs_index::sparse_vector::iterator sv_itr;
00165 for (unsigned int i=0; i<number_of_a(); ++i)
00166 {
00167
00168 vnl_double_3x4 Pi = param_to_cam_matrix(i,a,c);
00169
00170
00171 const vnl_vector_ref<double> ai(number_of_params_a(i),
00172 const_cast<double*>(a.data_block())+index_a(i));
00173
00174 vnl_crs_index::sparse_vector row = residual_indices_.sparse_row(i);
00175 for (sv_itr r_itr=row.begin(); r_itr!=row.end(); ++r_itr)
00176 {
00177 unsigned int j = r_itr->second;
00178 unsigned int k = r_itr->first;
00179
00180 const vnl_vector_ref<double> bj(number_of_params_b(j),
00181 const_cast<double*>(b.data_block())+index_b(j));
00182
00183 jac_Aij(i,j,Pi,ai,bj,c,A[k]);
00184 jac_Bij(i,j,Pi,ai,bj,c,B[k]);
00185 jac_Cij(i,j,Pi,ai,bj,c,C[k]);
00186 if (use_covars_){
00187 const vnl_matrix<double>& Sij = factored_inv_covars_[k];
00188 A[k] = Sij*A[k];
00189 B[k] = Sij*B[k];
00190 C[k] = Sij*C[k];
00191 }
00192 }
00193 }
00194 }
00195
00196
00197 void
00198 vpgl_bundle_adjust_lsqr::compute_weight_ij(int , int ,
00199 vnl_vector<double> const& ,
00200 vnl_vector<double> const& ,
00201 vnl_vector<double> const& ,
00202 vnl_vector<double> const& fij,
00203 double& weight)
00204 {
00205 double u2 = fij.squared_magnitude()/scale2_;
00206
00207
00208 weight = (u2 > 1.0) ? 0.0 : 1 - u2;
00209
00210
00211
00212 }
00213
00214
00215
00216 void vpgl_bundle_adjust_lsqr::
00217 jac_inhomg_3d_point(vnl_double_3x4 const& P,
00218 vnl_vector<double> const& pt,
00219 vnl_matrix<double>& J)
00220 {
00221 double denom = P(2,0)*pt[0] + P(2,1)*pt[1] + P(2,2)*pt[2] + P(2,3);
00222 denom *= denom;
00223
00224 double txy = P(0,0)*P(2,1) - P(0,1)*P(2,0);
00225 double txz = P(0,0)*P(2,2) - P(0,2)*P(2,0);
00226 double tyz = P(0,1)*P(2,2) - P(0,2)*P(2,1);
00227 double tx = P(0,0)*P(2,3) - P(0,3)*P(2,0);
00228 double ty = P(0,1)*P(2,3) - P(0,3)*P(2,1);
00229 double tz = P(0,2)*P(2,3) - P(0,3)*P(2,2);
00230
00231 J(0,0) = ( txy*pt[1] + txz*pt[2] + tx) / denom;
00232 J(0,1) = (-txy*pt[0] + tyz*pt[2] + ty) / denom;
00233 J(0,2) = (-txz*pt[0] - tyz*pt[1] + tz) / denom;
00234
00235 txy = P(1,0)*P(2,1) - P(1,1)*P(2,0);
00236 txz = P(1,0)*P(2,2) - P(1,2)*P(2,0);
00237 tyz = P(1,1)*P(2,2) - P(1,2)*P(2,1);
00238 tx = P(1,0)*P(2,3) - P(1,3)*P(2,0);
00239 ty = P(1,1)*P(2,3) - P(1,3)*P(2,1);
00240 tz = P(1,2)*P(2,3) - P(1,3)*P(2,2);
00241
00242 J(1,0) = ( txy*pt[1] + txz*pt[2] + tx) / denom;
00243 J(1,1) = (-txy*pt[0] + tyz*pt[2] + ty) / denom;
00244 J(1,2) = (-txz*pt[0] - tyz*pt[1] + tz) / denom;
00245 }
00246
00247
00248
00249 void vpgl_bundle_adjust_lsqr::jac_camera_center(vnl_double_3x3 const& M,
00250 vnl_vector<double> const& C,
00251 vnl_vector<double> const& pt,
00252 vnl_matrix<double>& J)
00253 {
00254
00255
00256 vnl_double_3x4 P;
00257 P.update(M);
00258 P.set_column(3,-(M*pt));
00259 jac_inhomg_3d_point(P,C,J);
00260 }
00261
00262
00263
00264
00265 void vpgl_bundle_adjust_lsqr::jac_camera_rotation(vnl_double_3x3 const& K,
00266 vnl_vector<double> const& C,
00267 vnl_vector<double> const& r,
00268 vnl_vector<double> const& pt,
00269 vnl_matrix<double>& J)
00270 {
00271 vnl_double_3 t(pt[0]-C[0], pt[1]-C[1], pt[2]-C[2]);
00272
00273 const double& x = r[0];
00274 const double& y = r[1];
00275 const double& z = r[2];
00276 double x2 = x*x, y2 = y*y, z2 = z*z;
00277 double m2 = x2 + y2 + z2;
00278
00279
00280 if (m2 == 0.0)
00281 {
00282 double inv_tz2 = 1.0/(t[2]*t[2]);
00283 J(0,0) = -t[0]*t[1] * inv_tz2;
00284 J(1,0) = -1 - t[1]*t[1] * inv_tz2;
00285 J(0,1) = 1 + t[0]*t[0] * inv_tz2;
00286 J(1,1) = t[0]*t[1] * inv_tz2;
00287 J(0,2) = -t[1] / t[2];
00288 J(1,2) = t[0] / t[2];
00289 }
00290 else
00291 {
00292 double m = vcl_sqrt(m2);
00293 double c = vcl_cos(m);
00294 double s = vcl_sin(m);
00295
00296
00297 double ct = (1-c)/m2;
00298 double st = s/m;
00299
00300
00301
00302
00303 double dct = s/(m*m2);
00304 double dst = c/m2 - dct;
00305 dct -= 2*(1-c)/(m2*m2);
00306
00307 double utc = t[2]*x*z + t[1]*x*y - t[0]*(y2+z2);
00308 double uts = t[2]*y - t[1]*z;
00309 double vtc = t[0]*x*y + t[2]*y*z - t[1]*(x2+z2);
00310 double vts = t[0]*z - t[2]*x;
00311 double wtc = t[0]*x*z + t[1]*y*z - t[2]*(x2+y2);
00312 double wts = t[1]*x - t[0]*y;
00313
00314
00315
00316 double u = ct*utc + st*uts + t[0];
00317 double v = ct*vtc + st*vts + t[1];
00318 double w = ct*wtc + st*wts + t[2];
00319
00320 double w2 = w*w;
00321
00322 double dw = dct*x*wtc + ct*(t[0]*z - 2*t[2]*x)
00323 + dst*x*wts + st*t[1];
00324 J(0,0) = (w*(dct*x*utc + ct*(t[2]*z + t[1]*y)
00325 + dst*x*uts) - u*dw)/w2;
00326 J(1,0) = (w*(dct*x*vtc + ct*(t[0]*y - 2*t[1]*x)
00327 + dst*x*vts - st*t[2]) - v*dw)/w2;
00328
00329 dw = dct*y*wtc + ct*(t[1]*z - 2*t[2]*y)
00330 + dst*y*wts - st*t[0];
00331 J(0,1) = (w*(dct*y*utc + ct*(t[1]*x - 2*t[0]*y)
00332 + dst*y*uts + st*t[2]) - u*dw)/w2;
00333 J(1,1) = (w*(dct*y*vtc + ct*(t[0]*x + t[2]*z)
00334 + dst*y*vts) - v*dw)/w2;
00335
00336 dw = dct*z*wtc + ct*(t[0]*x + t[1]*y)
00337 + dst*z*wts;
00338 J(0,2) = (w*(dct*z*utc + ct*(t[2]*x - 2*t[0]*z)
00339 + dst*z*uts - st*t[1]) - u*dw)/w2;
00340 J(1,2) = (w*(dct*z*vtc + ct*(t[2]*y - 2*t[1]*z)
00341 + dst*z*vts + st*t[0]) - v*dw)/w2;
00342 }
00343
00344
00345 J(0,0) *= K(0,0);
00346 J(0,0) += J(1,0)*K(0,1);
00347 J(1,0) *= K(1,1);
00348 J(0,1) *= K(0,0);
00349 J(0,1) += J(1,1)*K(0,1);
00350 J(1,1) *= K(1,1);
00351 J(0,2) *= K(0,0);
00352 J(0,2) += J(1,2)*K(0,1);
00353 J(1,2) *= K(1,1);
00354 }
00355
00356
00357
00358 vnl_double_3x3
00359 vpgl_bundle_adjust_lsqr::rod_to_matrix(vnl_vector<double> const& r)
00360 {
00361 double x2 = r[0]*r[0], y2 = r[1]*r[1], z2 = r[2]*r[2];
00362 double m = x2 + y2 + z2;
00363 double theta = vcl_sqrt(m);
00364 double s = vcl_sin(theta) / theta;
00365 double c = (1 - vcl_cos(theta)) / m;
00366
00367 vnl_matrix_fixed<double,3,3> R(0.0);
00368 R(0,0) = R(1,1) = R(2,2) = 1.0;
00369 if (m == 0.0)
00370 return R;
00371
00372 R(0,0) -= (y2 + z2) * c;
00373 R(1,1) -= (x2 + z2) * c;
00374 R(2,2) -= (x2 + y2) * c;
00375 R(0,1) = R(1,0) = r[0]*r[1]*c;
00376 R(0,2) = R(2,0) = r[0]*r[2]*c;
00377 R(1,2) = R(2,1) = r[1]*r[2]*c;
00378
00379 double t = r[0]*s;
00380 R(1,2) -= t;
00381 R(2,1) += t;
00382 t = r[1]*s;
00383 R(0,2) += t;
00384 R(2,0) -= t;
00385 t = r[2]*s;
00386 R(0,1) -= t;
00387 R(1,0) += t;
00388
00389 return R;
00390 }
00391