Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
CamPoseCalib.cpp
1 #include "CamPoseCalib.hh"
2 
3 // BIAS
4 #include <MathAlgo/Lapack.hh>
5 #include <Geometry/SimilarityTransform.hh>
6 #include <Base/Common/CompareFloatingPoint.hh>
7 
8 using namespace BIAS;
9 using namespace std;
10 
11 CamPoseCalib::CamPoseCalib() : calcSecD_(false)
12 {
13  transChangeEpsilon_ = 1E-9;
14  rotChangeEpsilon_ = 1E-9;
15  minDepthModel_ = 1E-9;
16  paramToEst_=6;
17  estimateF_=0;
18  estimatePrincipal_=false;
19  estimateTransX_=true;
20  estimateTransY_=true;
21  estimateTransZ_=true;
22  doLM_=true;
23  lastError_=DBL_MAX;
24  errorIncreaseForLM_=0.01; // in percent
25  robustFunc_=-1;
27  initialGuess_=false;
28  sx_=-1;
29  sy_=-1;
30  initMu_=10000;
31  Reset();
32 }
33 
34 
36 {
37  mu_=initMu_;
38  initialized_=false;
39  initialGuess_=false;
41  resultTrans_.Set(0,0,0);
42  mps_.clear();
43  initialMps_.clear();
44  origMps_.clear();
45  tps_.clear();
46  lastError_=DBL_MAX;
47 
48  mpsLine_.clear();
49  origMpsLine_.clear();
50  initialMpsLine_.clear();
51  tpsLinePoint_.clear();
52  tpsLineNormal_.clear();
53 }
54 
55 
56 void CamPoseCalib::outputPose_(int iteration)
57 {
58  ofstream up("poseUpVector.log", ios_base::app);
59  ofstream axis("poseOptAxis.log", ios_base::app);
60  ofstream transX("poseTransX.log", ios_base::app);
61  ofstream transY("poseTransY.log", ios_base::app);
62  ofstream transZ("poseTransZ.log", ios_base::app);
63  ofstream transAbs("poseTransAbs.log", ios_base::app);
64 
65  BIAS::Vector3<double> upVec(0,-1,0), axisVec(0,0,1);
66  double angle;
67  angle=acos( (camR_ * GetRotation()*upVec)*truthUpVec_);
68  up<<iteration<<" "<<angle/M_PI*180.0<<endl;
69 
70  angle=acos( (camR_ * GetRotation()*axisVec) * truthOptAxis_);
71  axis<<iteration<<" "<<angle/M_PI*180.0<<endl;
72 
73  transX<<iteration<<" "<<truthCenter_[0]-GetTranslation()[0]<<endl;
74  transY<<iteration<<" "<<truthCenter_[1]-GetTranslation()[1]<<endl;
75  transZ<<iteration<<" "<<truthCenter_[2]-GetTranslation()[2]<<endl;
76  transAbs<<iteration<<" "<<(truthCenter_-GetTranslation()).Length()<<endl;
77 
78  ofstream svdOut("poseSingularValues.log",ios_base::app);
79  svdOut<<iteration<<" ";
82  BIAS::SVD svdJ2(J2);
83  for (unsigned int i=0;i<J2.GetRows(); i++) {
84  svdOut<<svdJ2.GetSingularValue(i)<<" ";
85  }
86  svdOut<<endl;
87 }
88 
89 
90 int CamPoseCalib::Estimate(unsigned int iterations)
91 {
92  if (initialGuess_) {
93  int res =GuessInitialCam_();
94  if (res==-2) return -5;
95  }
96  if (!initialized_) {
97  // check if there are points at all
98  if (origMps_.empty() && origMpsLine_.empty()) {
99  BIASERR("No points !");
100  return -10;
101  }
102  BIAS::Vector3<double> point,avgPos(0,0,0);
103  for (unsigned int i=0; i<origMps_.size(); i++) {
104  point=(camRT_ * origMps_[i]) - (camRT_ * camC_);
105  avgPos+=point;
106  initialMps_.push_back( point );
107  }
108  for (unsigned int i=0; i<origMpsLine_.size(); i++) {
109  point=(camRT_ * origMpsLine_[i]) - (camRT_ * camC_);
110  avgPos+=point;
111  initialMpsLine_.push_back( point );
112  }
113  // now scale all model points for numerical stability
114  avgPos/=( (double)initialMps_.size() + (double)initialMpsLine_.size() );
115  scaleNumStabiltity_= 1.0/avgPos.Length();
116  for (unsigned int j=0; j<initialMps_.size(); j++) {
118  }
119  for (unsigned int j=0; j<initialMpsLine_.size(); j++) {
121  }
124  initialized_=true;
125  }
126 
129  unsigned int rows=mps_.size()*2 + mpsLine_.size();
131  solveVector_.newsize(rows);
132 
133  BIASDOUT(D_BIAS_CAMPOSE_ESTIMATE_STEPS,"solveMatrix.size:"<<
135 
136 #ifdef BIAS_DEBUG
137  if ( (mps_.size() != tps_.size() ) ) {
138  BIASERR("different number of model points and target points");
139  BIASABORT;
140  }
141 #endif
142 
143  unsigned int i=0;
144  int resCode =-1;
145  double transChange=1, rotChange=1,w;
146  Vector3<double> lastTrans(0,0,0);
147 
150  Vector3<double> axis;
151  double angle;
152  while ( (i<iterations) && ((transChange>transChangeEpsilon_) ||
153  (rotChange>rotChangeEpsilon_)) ) {
158  if (calcSecD_) {
160  BIASDOUT(D_BIAS_CAMPOSE_SECD,"Second Derivative Matrix s:"<<secDMatrix_);
161 
162  }
163  if (int(2*variances_.size()) == solveVector_.size()) {
165  }
166  BIASDOUT(D_BIAS_CAMPOSE_EQSYS,"solveMatrix:"<<solveMatrix_<<endl<<
167  "solveVector:"<<solveVector_);
168  BIASDOUT(D_BIAS_CAMPOSE_ESTIMATE_STEPS,"iteration:"<<i<<"/"<<iterations);
169 
170  //outputPose_(i);
171 
172  if (robustFunc_>=0)
174  if (weights_.size()>0) {
175  int row=0;
176  if ((int)(2*weights_.size()+weightsLine_.size())==solveVector_.size()){
177  for (unsigned int i=0; i<weights_.size()*2; i++) {
178  w=sqrt(weights_[i/2]);//sqrt is neccessary to have w as the influence
179  solveVector_[i]*=w;
180  for (int col=0;col<solveMatrix_.num_cols();col++)
181  solveMatrix_[i][col]*=w;
182  row++;
183  }
184  for (int i=row; i<solveVector_.size(); i++) {
185  w=sqrt(weightsLine_[i]);
186  solveVector_[i]*=w;
187  for (int col=0;col<solveMatrix_.num_cols();col++)
188  solveMatrix_[i][col]*=w;
189  row++;
190  }
191  } else
192  BIASERR("number of weights is not equal to nr of correspondences");
193  }
194  // result=Lapack_WLLS_solve(solveMatrix_,solveVector_,
195  // weightMatrix_, resCode);
196 
197  resCode = -1;
198  if (doLM_)
199  resCode=SolveLM_(solveMatrix_,solveVector_, result,iterations);
200  else {
201  resCode=svd_.Solve(solveMatrix_,solveVector_, result);
202  ApplySolution_(result);
203  }
204 
205  if (resCode!=0) {
206  // BIASERR("error solving the equation system. probably singular "
207  // "matrix J^T J");
208  return -2;
209  }
210 
211  BIASDOUT(D_BIAS_CAMPOSE_ESTIMATE_EQSYS,"result:"<<result);
212 
213 
214  // calc the change of the transform
215  transChange = resultTrans_.Dist(lastTrans);
217  lastRot_.GetRotationAxisAngle(axis, angle);
218  rotChange = angle;
219  lastRot_ = resultR_;
220  lastTrans = resultTrans_;
221  BIASDOUT(D_BIAS_CAMPOSE_ESTIMATE_ITER,"iteration:"<<i<<"/"<<iterations
222  <<" transChange:"<<transChange<<" rotChange:"<<rotChange
223  <<" err:"<<GetAvgError());
224  i++;
225  } //while()
226 
227  if (i>=iterations) {
228 #ifdef BIAS_DEBUG
229  BIASDOUT(D_BIAS_CAMPOSE_ESTIMATE_ITER,"too many iterations in CamPoseCalib::Estimate: "<<i
230  <<" last changes were t="<<transChange<<" r="<<rotChange);
231 #endif
232  return 1;
233  }
234 
235  return 0;
236 }
237 
238 
240 {
241  double mp2mp2;
242  unsigned int col,row2;
243 
244  const bool estX=estimateTransX_,estY=estimateTransY_,estZ=estimateTransZ_;
245 
246  // for every 3D-point-2D-point corr create 2 rows
247  for (unsigned int row=0;row<mps_.size();row++) {
248  const BIAS::Vector3<double> &mp = mps_[row];
249  mp2mp2=mp[2]*mp[2];
250  if (mp2mp2>minDepthModel_) {
251  const BIAS::Vector2<double> &target=tps_[row];
252  row2=row*2;
253  solveVector_[row2] = target[0] - (mp[0]/mp[2] * sx_ + cx_);
254  solveVector_[row2+1]= target[1] - (mp[1]/mp[2] * sy_ + cy_);
255 
256  BIASDOUT(D_BIAS_CAMPOSE_ESTIMATE_STEPS,"mp:"<<mp<<" tp:"<<target);
257  double *matrixRow = solveMatrix_[row2];
258  col=0;
259  if (estX==1) {
260  matrixRow[col]= sx_ / mp[2];
261  col++;
262  }
263  if (estY==1) {
264  matrixRow[col]= 0;
265  col++;
266  }
267  if (estZ==1) {
268  matrixRow[col]= sx_* -mp[0]/(mp2mp2);
269  col++;
270  }
271  matrixRow[col]= sx_* -mp[0] * mp[1] / (mp2mp2);
272  col++;
273  matrixRow[col]= sx_* (mp2mp2 + mp[0]*mp[0])/(mp2mp2);
274  col++;
275  matrixRow[col]= sx_* -mp[1]/mp[2];
276 
277  double *matrixRowP1 = solveMatrix_[row2+1];
278  col=0;
279  if (estX==1) {
280  matrixRowP1[col]= 0;
281  col++;
282  }
283  if (estY==1) {
284  matrixRowP1[col]= sy_ / mp[2];
285  col++;
286  }
287  if (estZ==1) {
288  matrixRowP1[col]= sy_* -mp[1]/(mp2mp2);
289  col++;
290  }
291  matrixRowP1[col]= sy_* (-mp2mp2 - mp[1]*mp[1])/(mp2mp2);
292  col++;
293  matrixRowP1[col]= sy_* ( mp[1]*mp[0])/(mp2mp2);
294  col++;
295  matrixRowP1[col]= sy_* mp[0]/mp[2];
296 
297  if (estimateF_>0) {
298  if (estimateF_==1) { // fx=fy
299  col++;
300  matrixRow[col] = mp[0]/mp[2];
301  matrixRowP1[col]= mp[1]/mp[2];
302  } else { // both sx_ and sy_ are to estimate
303  col++;
304  matrixRow[col] = mp[0]/mp[2];
305  col++;
306  matrixRowP1[col] = mp[1]/mp[2];
307  }
308  }
309  if (estimatePrincipal_) {
310  col++;
311  matrixRow[col] = 1;
312  col++;
313  matrixRowP1[col] = 1;
314  }
315  } else {
316  BIASDOUT(D_BIAS_CAMPOSE_EQSYS,"mp:"<<mp<<" tp:"<<tps_[row]<<
317  " point distance to cam center too small:"<<mp[2]);
318  }
319  }
320  return 0;
321 }
322 
323 
325 {
326  double mp2mp2;
327  unsigned int col,row2;
328 
329  const bool estX=estimateTransX_,estY=estimateTransY_,estZ=estimateTransZ_;
332  rowEntryX(solveMatrix_.GetCols()),
333  rowEntryY(solveMatrix_.GetCols());
334 
335  // for every 3D-point-2D-point corr add 1 row
336  row2=mps_.size()*2;
337  for (unsigned int row=0;row<mpsLine_.size();row++) {
338  const BIAS::Vector3<double> &mp = mpsLine_[row];
339  mp2mp2=mp[2]*mp[2];
340  if (mp2mp2>minDepthModel_) {
341  const BIAS::Vector2<double> &target=tpsLinePoint_[row];
342  const BIAS::Vector2<double> &targetNormal=tpsLineNormal_[row];
343  diff[0]= target[0] - (mp[0]/mp[2] * sx_ + cx_);
344  diff[1]= target[1] - (mp[1]/mp[2] * sy_ + cy_);
345  diff.ScalarProduct(targetNormal, solveVector_[row2]);
346 
347  BIASDOUT(D_BIAS_CAMPOSE_ESTIMATE_STEPS,"mp:"<<mp<<" tp:"<<target);
348  double *matrixRow = rowEntryX.GetData();
349  col=0;
350  if (estX==1) {
351  matrixRow[col]= sx_ / mp[2];
352  col++;
353  }
354  if (estY==1) {
355  matrixRow[col]= 0;
356  col++;
357  }
358  if (estZ==1) {
359  matrixRow[col]= sx_* -mp[0]/(mp2mp2);
360  col++;
361  }
362  matrixRow[col]= sx_* -mp[0] * mp[1] / (mp2mp2);
363  col++;
364  matrixRow[col]= sx_* (mp2mp2 + mp[0]*mp[0])/(mp2mp2);
365  col++;
366  matrixRow[col]= sx_* -mp[1]/mp[2];
367 
368  double *matrixRowP1 = rowEntryY.GetData();
369  col=0;
370  if (estX==1) {
371  matrixRowP1[col]= 0;
372  col++;
373  }
374  if (estY==1) {
375  matrixRowP1[col]= sy_ / mp[2];
376  col++;
377  }
378  if (estZ==1) {
379  matrixRowP1[col]= sy_* -mp[1]/(mp2mp2);
380  col++;
381  }
382  matrixRowP1[col]= sy_* (-mp2mp2 - mp[1]*mp[1])/(mp2mp2);
383  col++;
384  matrixRowP1[col]= sy_* ( mp[1]*mp[0])/(mp2mp2);
385  col++;
386  matrixRowP1[col]= sy_* mp[0]/mp[2];
387 
388  if (estimateF_>0) {
389  if (estimateF_==1) { // fx=fy
390  col++;
391  matrixRow[col] = mp[0]/mp[2];
392  matrixRowP1[col]= mp[1]/mp[2];
393  } else { // both sx_ and sy_ are to estimate
394  col++;
395  matrixRow[col] = mp[0]/mp[2];
396  col++;
397  matrixRowP1[col] = mp[1]/mp[2];
398  }
399  }
400  if (estimatePrincipal_) {
401  col++;
402  matrixRow[col] = 1;
403  col++;
404  matrixRowP1[col] = 1;
405  }
406 
407  //now multiply the 2 rows with normal
408  for (unsigned int j=0; j<solveMatrix_.GetCols(); j++) {
409  solveMatrix_[row2][j]=
410  rowEntryX[j]*targetNormal[0] +
411  rowEntryY[j]*targetNormal[1];
412  }
413  row2++;
414  } else {
415  BIASDOUT(D_BIAS_CAMPOSE_EQSYS,"mp:"<<mp<<" tp:"<<tps_[row]<<
416  " point distance to cam center too small:"<<mp[2]);
417  }
418  }
419  return 0;
420 }
421 
423  BIAS::Vector<double> &result)
424 {
425  return svd_.Solve(J,eps,result);
426 
427 // BIAS::Matrix<double> J2(J.num_cols(),J.num_cols());
428 // BIAS::Vector<double> Jeps(J.Transpose()*eps);
429 // J2=J.Transpose()*J; // this could be done faster
430 
431 // result=Lapack_LU_linear_solve(J2,Jeps);
432 // if (result.size()<J.num_cols())
433 // return -1;
434 // else
435 // return 0;
436 }
437 
438 
439 
441 {
442  // transform the model points by the result transform
443  // add the result to the previous transforms
444  BIASDOUT(D_BIAS_CAMPOSE_APPLY_SOL,"resulting paramter change:"<<result);
446 
447  double alpha=result[row];
448  double beta =result[row+1];
449  double gamma=result[row+2];;
450  row+=2;
451  if (estimateF_>0) {
452  if (estimateF_==1) { // fx=fy
453  row++;
454  sx_+=result[row];
455  sy_+=result[row];
456  } else { // both sx_ and sy_ are to estimate
457  row++;
458  sx_+=result[row];
459  row++;
460  sy_+=result[row];
461  }
462  }
463  if (estimatePrincipal_) {
464  row++;
465  cx_+=result[row];
466  row++;
467  cy_+=result[row];
468  }
469 
470  BIAS::RMatrix R;
471 
472  R.SetXYZ(alpha,beta,gamma);
473 
474  resultR_= R*resultR_;
476  row=0;
477  if (estimateTransX_) {
478  resultTrans_[0]+= result[row];
479  row++;
480  }
481  if (estimateTransY_) {
482  resultTrans_[1]+= result[row];
483  row++;
484  }
485  if (estimateTransZ_) {
486  resultTrans_[2]+= result[row];
487  row++;
488  }
489 
490  BIASDOUT(D_BIAS_CAMPOSE_APPLY_SOL,"result trans:"<<resultTrans_<<endl
491  <<" result R:"<<R);
492 
493  for (unsigned int mpIdx=0;mpIdx<mps_.size();mpIdx++) {
494  mps_[mpIdx]=resultR_* initialMps_[mpIdx] + resultTrans_;
495  }
496  for (unsigned int mpIdx=0;mpIdx<mpsLine_.size();mpIdx++) {
497  mpsLine_[mpIdx]=resultR_* initialMpsLine_[mpIdx] + resultTrans_;
498  }
499  return 0;
500 }
501 
502 
503 int CamPoseCalib::SetInitialCamera(double fx, double fy, double cx, double cy,
504  const RMatrix &R, const Vector3<double> &C)
505 {
506  sx_=fx; sy_=fy;
507  cx_=cx; cy_=cy;
508  camR_=R;
509  camRT_=R.Transpose();
510  camC_=C;
511 
512  return 0;
513 }
514 
515 
517 {
518  camP_=P;
519  KMatrix K;
520  camP_.GetK(K);
521  sx_=K[0][0]; sy_=K[1][1];
522  cx_=K[0][2]; cy_=K[1][2];
523  camR_=camP_.GetR();
525  camC_=camP_.GetC();
526  return 0;
527 }
528 
530 {
531  initialGuess_=true;
532  sx_=K[0][0]; sy_=K[1][1];
533  cx_=K[0][2]; cy_=K[1][2];
534  return 0;
535 }
536 
538 {
539  origMps_.push_back(x);
540  tps_.push_back(y);
541  return 0;
542 }
543 
545 {
546  KMatrix K;
547  K.SetIdentity();
548  K[0][0]= sx_; K[0][2]= cx_;
549  K[1][1]= sy_; K[1][2]= cy_;
550 
551  P.Compose(K,
552  camR_ * GetRotation(),
553  camC_ + GetTranslation());
554 }
555 
557 {
558  Vector<double> res(6);
559  Vector3<double> C;
560  Vector3<double> ang;
561  RMatrix R;
562  C = camC_ + GetTranslation();
563  R = camR_ * GetRotation();
564  R.GetRotationAnglesXYZ(ang);
565  for (int i=0; i<3; i++){
566  res[i] = C[i];
567  res[i+3] = ang[i];
568  }
569  return res;
570 }
571 
572 
574  BIAS::Vector<double> &result, unsigned int iterations)
575 {
576  // return svd_.Solve(J,eps,result);
577  unsigned int i=0,iteration=0;
578  BIAS::Matrix<double> J2temp;
579  BIAS::Vector<double> Jeps(J.Transpose()*eps);
580  bool errorIncreased=true;
581  // vars for orig values
582  double fxOrig,fyOrig,cxOrig,cyOrig;
583  BIAS::Vector3<double> resultTransOrig;
584  BIAS::RMatrix resultROrig;
585  std::vector<BIAS::Vector3<double> > mpsOrig,mpsOrigLine;
586 
588  // J2=J.Transpose()*J; // this could be done faster
589  // the faster variant here is GetSystemMatrix, which does the same
591  if (calcSecD_) { // calc the necessary dampening value mu_
592  BIASDOUT(D_BIAS_CAMPOSE_SECD,"Hessian of Gauss-Newton:"<<coVarMat_);
594  BIASDOUT(D_BIAS_CAMPOSE_SECD,"Hessian of Newton:"<<coVarMat_);
595  BIAS::SVD eigValComp(coVarMat_);
596  BIAS::Vector<double> eigValues(eigValComp.GetEigenValues());
597  BIASDOUT(D_BIAS_CAMPOSE_SECD,"EigValues of Hessian:"<<eigValues);
598  if (eigValues[0]<0)
599  mu_=-5*(eigValues[0]);
600  else mu_=0.001;
601  }
602  double angle;
604  while ((errorIncreased) && (iteration<iterations) && (mu_<1E50)) {
605  //mu_=10000;
606  BIASDOUT( D_BIAS_CAMPOSE_LM, "solving for mu:"<<mu_);
607  J2temp=coVarMat_;
608  for (i=0;i<(unsigned int)J2temp.num_rows();i++)
609  J2temp[i][i]+=mu_;
610 
611  result=Lapack_LU_linear_solve(J2temp,Jeps);
612  if (result.size()<J.num_cols())
613  return -1;
614 // svd_.Solve(J2temp,Jeps,result);
615 
616 
617  //// apply the solution temporary
618  //save original values
619  fxOrig=sx_;
620  fyOrig=sy_;
621  cxOrig=cx_;
622  cyOrig=cy_;
623 
624  resultROrig=resultR_;
625  resultTransOrig=resultTrans_;
626 
627  mpsOrig=mps_;
628  mpsOrigLine=mpsLine_;
629  BIASDOUT( D_BIAS_CAMPOSE_LM, "result:"<<result);
630  ApplySolution_(result);
631  BIASDOUT( D_BIAS_CAMPOSE_LM, "last SquaredError:"<<lastError_<<
632  " new squared error:"<<GetAvgSquaredWeightedError_());
633 
634 
635  // check if rotation is more than 90 degrees
636  RMatrix rotChange = lastRot_.Transpose()*resultR_;
637  BIASDOUT( D_BIAS_CAMPOSE_LM, "rotChange Matrix:"<<rotChange);
638  rotChange.GetRotationAxisAngle(axis, angle);
639  BIASDOUT( D_BIAS_CAMPOSE_LM, "rotChange="<<angle);
640  if ( (angle<1.56) &&
641  //// check if the solution decreases the error
644  ) {
645  errorIncreased=false;
646  mu_ /= 10;
647  if (mu_<0.001) mu_=initMu_;
648  } else {
649  mu_ *= 10;
650  }
651 
652  if (errorIncreased) {
653  // reset the original values
654  sx_=fxOrig;
655  sy_=fyOrig;
656  cx_=cxOrig;
657  cy_=cyOrig;
658 
659  resultR_=resultROrig;
660  resultTrans_=resultTransOrig;
661 
662  mps_=mpsOrig;
663  mpsLine_=mpsOrigLine;
664  }
665  iteration++;
666  }//end while
667 
668  return 0;
669 }
670 
671 
673 {
674  double err=0,dx,dy;
675  unsigned int i=0;
676  int weightAmount=int(2*weights_.size()+weightsLine_.size());
677  if (weightAmount!= solveVector_.size()) {
678  // weights_.resize(mps_.size());
679  weights_.assign(mps_.size(), 1.0);
680  weightsLine_.assign(mpsLine_.size(), 1.0);
681  }
682  for (i=0;i<mps_.size();i++) {
683  const BIAS::Vector3<double> &mp=mps_[i];
684  if (fabs(mp[2])>minDepthModel_) {
685  dx= tps_[i][0] - (mp[0]/mp[2] * sx_ + cx_);
686  dy= tps_[i][1] - (mp[1]/mp[2] * sy_ + cy_);
687  err= sqrt(dx*dx + dy*dy);
688 
689  switch (robustFunc_) {
690  case 0: // Fair
691  weights_[i]*= 1.0 / (1.0 + (err/outlierError_));
692  break;
693  case 1: // Huber
694  if (err>outlierError_)
695  weights_[i]*= outlierError_/err;
696  else
697  weights_[i]*= 1.0;
698  break;
699  case 2: // Tukey
700  if (err<=outlierError_) {
701  weights_[i]*=(err/outlierError_)*(err/outlierError_);
702  weights_[i]*= (1.0 - weights_[i]) * (1.0 - weights_[i]);
703  } else
704  weights_[i]=0;
705  break;
706  }
707  } else
708  weights_[i]=0;
709  }
710 
711  for (i=0;i<mpsLine_.size();i++) {
712  const BIAS::Vector3<double> &mp=mpsLine_[i];
713  if (fabs(mp[2])>minDepthModel_) {
714  const BIAS::Vector2<double> &tp = tpsLinePoint_[i];
715  const BIAS::Vector2<double> &normal = tpsLineNormal_[i];
716  dx = tp[0] - (mp[0]/mp[2] * sx_ + cx_);
717  dy = tp[1] - (mp[1]/mp[2] * sy_ + cy_);
718  err= fabs(dx*normal[0]+dy*normal[1]);
719  switch (robustFunc_) {
720  case 0: // Fair
721  weightsLine_[i]*= 1.0 / (1.0 + (err/outlierError_));
722  break;
723  case 1: // Huber
724  if (err>outlierError_)
725  weightsLine_[i]*= outlierError_/err;
726  else
727  weightsLine_[i]*= 1.0;
728  break;
729  case 2: // Tukey
730  if (err<=outlierError_) {
731  weightsLine_[i]*=(err/outlierError_)*(err/outlierError_);
732  weightsLine_[i]*= (1.0 - weightsLine_[i]) * (1.0 - weightsLine_[i]);
733  } else
734  weightsLine_[i]=0;
735  break;
736  }
737  } else
738  weightsLine_[i]=0;
739  }
740  return 0;
741 }
742 
743 
745  double err=0,dx,dy;
746  unsigned int i=0,count=0;
747  const bool bVars=(variances_.size()==mps_.size());
748  Vector2<double> diff;
749  for (i=0;i<mps_.size();i++) {
750  const BIAS::Vector3<double> &mp = mps_[i];
751  if (fabs(mp[2])>minDepthModel_) {
752  const BIAS::Vector2<double> &tp = tps_[i];
753  dx = tp[0] - (mp[0]/mp[2] * sx_ + cx_);
754  dy = tp[1] - (mp[1]/mp[2] * sy_ + cy_);
755  if (bVars) { // use mahalanobis distance
756  const Matrix2x2<double> &var=variances_[i];
757  diff[0]=dx; diff[1]=dy;
758  err+= diff*(var*diff);
759  } else {
760  err+= sqrt(dx*dx + dy*dy);
761  }
762  count++;
763  }
764  }
765 
766  for (i=0;i<mpsLine_.size();i++) {
767  const BIAS::Vector3<double> &mp = mpsLine_[i];
768  if (fabs(mp[2])>minDepthModel_) {
769  const BIAS::Vector2<double> &tp = tpsLinePoint_[i];
770  const BIAS::Vector2<double> &normal = tpsLineNormal_[i];
771  dx = tp[0] - (mp[0]/mp[2] * sx_ + cx_);
772  dy = tp[1] - (mp[1]/mp[2] * sy_ + cy_);
773  err+= fabs(dx*normal[0]+dy*normal[1]);
774  count++;
775  }
776  }
777 
778  err/= double(count);
779  return err;
780 }
781 
783  double err=0,dx,dy;
784  unsigned int i=0,count=0;
785  const unsigned int size=mps_.size();
786  if (weights_.size()==mps_.size()) {
787  for (i=0; i<size; i++) {
788  const BIAS::Vector3<double> &mp = mps_[i];
789  if (fabs(mp[2])>minDepthModel_) {
790  const BIAS::Vector2<double> &tp = tps_[i];
791  dx = tp[0] - (mp[0]/mp[2] * sx_ + cx_);
792  dy = tp[1] - (mp[1]/mp[2] * sy_ + cy_);
793 
794  err+= weights_[i]*(dx*dx + dy*dy);
795  count++;
796  }
797  }
798  } else {
799  for (i=0; i<size; i++) {
800  const BIAS::Vector3<double> &mp = mps_[i];
801  if (fabs(mp[2])>minDepthModel_) {
802  const BIAS::Vector2<double> &tp = tps_[i];
803  dx = tp[0] - (mp[0]/mp[2] * sx_ + cx_);
804  dy = tp[1] - (mp[1]/mp[2] * sy_ + cy_);
805 
806  err+= dx*dx + dy*dy;
807  count++;
808  }
809  }
810  }
811 
812  double errNormal;
813  for (i=0;i<mpsLine_.size();i++) {
814  const BIAS::Vector3<double> &mp = mpsLine_[i];
815  if (fabs(mp[2])>minDepthModel_) {
816  const BIAS::Vector2<double> &tp = tpsLinePoint_[i];
817  const BIAS::Vector2<double> &normal = tpsLineNormal_[i];
818  dx = tp[0] - (mp[0]/mp[2] * sx_ + cx_);
819  dy = tp[1] - (mp[1]/mp[2] * sy_ + cy_);
820  errNormal= fabs(dx*normal[0]+dy*normal[1]);
821  err+= errNormal*errNormal;
822  count++;
823  }
824  }
825 
826  err/= double(count);
827  return err;
828 }
829 
830 
832 {
835  double mp2mp2;
836  // each entry is summed up over all corrs
837  for (unsigned int mpI=0; mpI < mps_.size(); mpI++) {
838  const BIAS::Vector3<double> &mp = mps_[mpI];
839  const double errX= -solveVector_[mpI*2];
840  const double errY= -solveVector_[mpI*2+1];
841  mp2mp2=mp[2]*mp[2];
842  if (mp2mp2>minDepthModel_) {
843  ////////////// 0. row is trans_x
844  ////// m'_x:
845  //// partials for translation_x
846  // t_x=0
847  // t_y=0
848  // t_z
849  secDMatrix_[0][2]+= errX *
850  (-sx_/mp2mp2) ;
851  // rot_x
852  secDMatrix_[0][3]+= errX *
853  (-sx_/mp2mp2 * mp[1]);
854  // rot_y
855  secDMatrix_[0][4]+= errX *
856  (sx_/mp2mp2 * mp[0]);
857  // rot_z =0
858  ////// m'_y:
859  //// partials for translation_x are all zero
860 
861  ///////////// 1. row is trans_y
862  ////// m'_x:
863  //// partials for translation_y are all zero
864  ////// m'_y:
865  //// partials for translation_y
866  // t_x=0
867  // t_y=0
868  // t_z
869  secDMatrix_[1][2]+= errY *
870  (-sy_/mp2mp2);
871  // rot_x
872  secDMatrix_[1][3]+= errY *
873  (-sy_/mp2mp2 * mp[1]);
874  // rot_y
875  secDMatrix_[1][4]+= errY *
876  (sy_/mp2mp2 * mp[0]);
877  // rot_z =0
878 
879  ///////////// 2. row is trans_z
880  ////// m'_x:
881  //// partials for translation_z
882  // t_x
883  secDMatrix_[2][0]+= errX *
884  (-sx_ / mp2mp2);
885  // t_y=0
886  // t_z
887  secDMatrix_[2][2]+= errX *
888  (sx_ * mp[0]*2 / (mp2mp2*mp[2]));
889  // rot_x
890  secDMatrix_[2][3]+= errX *
891  (sx_ * mp[0]* mp[1]*2 / (mp2mp2*mp[2]));
892  // rot_y
893  secDMatrix_[2][4]+= errX *
894  (-sx_ / mp[2] - 2*sx_*mp[0]*mp[0] / (mp2mp2*mp[2]));
895  // rot_z
896  secDMatrix_[2][5]+= errX *
897  (sx_ *mp[1] / mp2mp2);
898 
899  ////// m'_y:
900  //// partials for translation_z
901  // t_x =0
902  // t_y
903  secDMatrix_[2][1]+= errY *
904  (-sy_ / mp2mp2);
905  // t_z
906  secDMatrix_[2][2]+= errY *
907  (sy_ * mp[1]*2 / (mp2mp2*mp[2]));
908  // rot_x
909  secDMatrix_[2][3]+= errY *
910  (sy_ / mp[2] + sy_*2*mp[1]*mp[1] / (mp2mp2*mp[2]));
911  //rot_y
912  secDMatrix_[2][4]+= errY *
913  (-sy_ * mp[0]* mp[1]*2 / (mp2mp2*mp[2]));
914  // rot_z
915  secDMatrix_[2][5]+= errY *
916  (-sy_ * mp[0] / mp2mp2);
917 
918  ///////////// 3. row is rot_x
919  ////// m'_x:
920  //// partials for rot_x
921  // t_x
922  secDMatrix_[3][0]+= errX *
923  (-sx_ / mp2mp2 * mp[1]);
924  // t_y =0
925  // t_z
926  secDMatrix_[3][2]+= errX *
927  (sx_ * mp[0]* mp[1]*2 / (mp2mp2*mp[2]));
928  // rot_x
929  secDMatrix_[3][3]+= errX *
930  (sx_*mp[0] / mp[2] + 2*sx_*mp[0]*mp[1]*mp[1] / (mp2mp2*mp[2]));
931  // rot_y
932  secDMatrix_[3][4]+= errX *
933  (-sx_ * mp[1]/mp[2]- sx_*2*mp[0]*mp[0] *mp[1] / (mp2mp2*mp[2]));
934  // rot_z
935  secDMatrix_[3][5]+= errX *
936  (sx_/mp2mp2 * (-mp[0]*mp[0] + mp[1]*mp[1]));
937  ////// m'_y:
938  //// partials for rot_x
939  // t_x = 0
940  // t_y
941  secDMatrix_[3][1]+= errY *
942  (-sy_ * mp[1] / mp2mp2);
943  // t_z
944  secDMatrix_[3][2]+= errY *
945  (sy_ /mp[2] + 2*sy_*mp[1]*mp[1] / (mp2mp2*mp[2]));
946  // rot_x
947  secDMatrix_[3][3]+= errY *
948  (2*sy_*( mp[1] / mp[2] + mp[1]*mp[1]*mp[1] / (mp2mp2*mp[2]) ));
949  // rot_y
950  secDMatrix_[3][4]+= errY *
951  (-2*sy_*mp[1]*mp[1]*mp[0]/ (mp2mp2*mp[2]));
952  // rot_z
953  secDMatrix_[3][5]+= errY *
954  (-2*sy_ * mp[0] *mp[1] / mp2mp2);
955 
956  ///////////// 4. row is rot_y
957  ////// m'_x:
958  //// partials for rot_y
959  // t_x
960  secDMatrix_[4][0]+= errX *
961  (sx_*mp[0] / mp2mp2);
962  // t_y = 0
963  // t_z
964  secDMatrix_[4][2]+= errX *
965  (-sx_ / mp[2] - 2*sx_*mp[0]*mp[0] / (mp2mp2*mp[2]));
966  // rot_x
967  secDMatrix_[4][3]+= errX *
968  (-sx_*mp[1]/mp[2] - 2*sx_*mp[0]*mp[0]*mp[1] / (mp[2]*mp2mp2));
969  // rot_y
970  secDMatrix_[4][4]+= errX *
971  (2*sx_/mp[2] * (mp[0] + mp[0]*mp[0]*mp[0] / mp2mp2));
972  // rot_z
973  secDMatrix_[4][5]+= errX *
974  (-2*sx_*mp[1]*mp[0] / mp2mp2);
975 
976  ////// m'_y:
977  //// partials for rot_y
978  // t_x =0
979  // t_y
980  secDMatrix_[4][1]+= errY *
981  (sy_*mp[0]/mp2mp2);
982  // t_z
983  secDMatrix_[4][2]+= errY *
984  (-2*sy_*mp[0]*mp[1]/(mp2mp2*mp[2]));
985  //rot_x
986  secDMatrix_[4][3]+= errY *
987  (-2*sy_*mp[0]*mp[1]*mp[1] / (mp2mp2*mp[2]));
988  // rot_y
989  secDMatrix_[4][4]+= errY *
990  (sy_/mp2mp2*(mp[2]*mp[1] + 2*mp[0]*mp[0]*mp[1]/mp[2]));
991  // rot_z
992  secDMatrix_[4][5]+= errY *
993  (sy_/mp2mp2*(-mp[1]*mp[1] + mp[0]*mp[0]));
994 
995 
996  ///////////// 5. row is rot_z
997  ////// m'_x:
998  //// partials for rot_z
999  // t_x =0
1000  // t_y =0
1001  // t_z
1002  secDMatrix_[5][2]+= errX *
1003  sx_*mp[1] / mp2mp2;
1004  // rot_x
1005  secDMatrix_[5][3]+= errX *
1006  (sx_/mp2mp2*(-mp[0]*mp[0] + mp[1]*mp[1]));
1007  // rot_y
1008  secDMatrix_[5][4]+= errX *
1009  (-2*sx_*mp[0]*mp[1] / mp2mp2);
1010  // rot_z
1011  secDMatrix_[5][5]+= errX *
1012  (-sx_*mp[0]/mp[2]);
1013 
1014  ////// m'_y:
1015  //// partials for rot_z
1016  // t_x =0
1017  // t_y =0
1018  // t_z
1019  secDMatrix_[5][2]+= errY *
1020  -sy_*mp[0] / mp2mp2;
1021  // rot_x
1022  secDMatrix_[5][3]+= errY *
1023  (-2*sy_ * mp[0] *mp[1] / mp2mp2);
1024  // rot_y
1025  secDMatrix_[5][4]+= errY *
1026  (sy_/mp2mp2* (mp[0]*mp[0] - mp[1]*mp[1]));
1027  // rot_z
1028  secDMatrix_[5][5]+= errY *
1029  -sy_*mp[1] / mp[2];
1030  }
1031  }
1032  return 0;
1033 }
1034 
1036 {
1037  if (!doLM_) {
1038  BIASERR("covariance only for LM estimation yet.");
1039  return -1;
1040  }
1041  BIAS::SVD svd(coVarMat_);
1042 
1043  double sigma2 =
1044  GetAvgSquaredWeightedError_() * mps_.size(); // undo averaging
1045  BIASASSERT((2 * mps_.size() - paramToEst_)!=0);
1046  sigma2 /= (double)(2 * mps_.size() -paramToEst_);
1047  coVar = sigma2 * svd.Invert();
1048  coVar.MakeSymmetric();
1049 
1050 #ifdef BIAS_DEBUG
1051  for (int i=0; i<coVar.num_rows(); i++) {
1052  for (int j=i; j<coVar.num_cols(); j++) {
1053  if (BIAS_ISINF(coVar[i][j]) || BIAS_ISNAN(coVar[i][j])){
1054  cout << coVarMat_ << endl << svd.Invert() << endl
1055  << GetAvgSquaredWeightedError_() << " "
1056  << sigma2 << " "<< mps_.size() <<" " << paramToEst_
1057  << endl << coVar << endl;
1058  }
1059  INFNANCHECK(coVar[i][j]);
1060  }
1061  }
1062 #endif
1063  return 0;
1064 }
1065 
1066 
1068 {
1069  if (dst.Size() != src.Size()){
1070  dst.newsize(src.Size());
1071  }
1072 #ifdef BIAS_DEBUG
1073  for (unsigned int i=0; i<src.Size(); i++) {
1074  INFNANCHECK(src[i]);
1075  }
1076 #endif
1077 
1078 
1079  Vector3<double> C;
1082  R = camR_ * resultR_.Transpose() * ( (-1.0/scaleNumStabiltity_) * I);
1083  C = GetTranslation() + camC_;
1084 
1085 
1087  for (int r=0; r<3; r++){
1088  T[r][3] = C[r];
1089  for (int c=0; c<3; c++){
1090  T[r][c] = R[r][c];
1091  }
1092  }
1093 
1094  Vector4<double> sC;
1095  for (int i=0; i<3; i++) sC[i] = src[i];
1096  sC[3] = 1.0;
1097  Vector4<double> dC = T * sC;
1098  if (Equal(dC[3], 0.0)){
1099  BIASASSERT("H5N1" && false);
1100  }
1101  dC /= dC[3];
1102  for (int i=0; i<3; i++) {
1103  dst[i] = dC[i];
1104 #ifdef BIAS_DEBUG
1105  INFNANCHECK(dst[i]);
1106 #endif
1107  }
1108 
1109  RMatrixBase sR, dR;
1110  sR.SetXYZ(src[3], src[4], src[5]);
1111  dR = camR_ * sR;
1112  return (dR.GetRotationAnglesXYZ(dst[3], dst[4], dst[5]));
1113 }
1114 
1115 #include <MathAlgo/UnscentedTransform.hh>
1116 
1117 // helper class for covariance matrix transfromation
1118 class GuessCoo2WoorlCoo : public BIAS::UnscentedTransform
1119 {
1120 public:
1121  GuessCoo2WoorlCoo(CamPoseCalib *p) : ccc(p) {};
1122 protected:
1123  CamPoseCalib *ccc;
1124  virtual int Transform_(const Vector<double>& src,
1125  Vector<double>& dst) const
1126  { return ccc->TransformVec(src, dst); }
1127 };
1128 
1129 void CamPoseCalib::
1131 {
1132  GuessCoo2WoorlCoo g2w(this);
1133  Vector<double> g, w;
1134  Matrix<double> gc, wc;
1135  if (GetCoVarMatrix(gc)!=0){
1136  BIASASSERT("H5N1" && false);
1137  }
1138 
1139  for (int i=0; i<gc.num_rows(); i++) {
1140  for (int j=i; j<gc.num_cols(); j++) {
1141  gc[j][i] = gc[i][j] = 0.5*(gc[i][j] + gc[j][i]);
1142 #ifdef BIAS_DEBUG
1143  if (BIAS_ISINF(gc[i][j]) || BIAS_ISNAN(gc[i][j])){
1144  cout << gc << endl;
1145  }
1146  INFNANCHECK(gc[i][j]);
1147 #endif
1148  }
1149  }
1150 
1151 
1152  g = GetResult();
1153 #ifdef BIAS_DEBUG
1154  for (unsigned int i=0; i<g.Size(); i++) {
1155  INFNANCHECK(g[i]);
1156  }
1157 #endif
1158  g2w.Transform(g, gc, w, wc);
1159  cov = wc;
1160  //cout << "cpc: before unscented tranform: "<<gc
1161  // <<"\tafter unscented tranform: "<<wc<<endl;
1162 
1163  /*Matrix<double> est_cov;
1164  int res = 0;
1165  if ((res = GetCoVarMatrix(est_cov))!=0){
1166  return res;
1167  }
1168 
1169  Vector3<double> C;
1170  Matrix3x3<double> I(MatrixIdentity);
1171  Matrix3x3<double> R;
1172  R = camR_* resultR_.Transpose() * ( (-1.0/scaleNumStabiltity_) * I);
1173  C = GetTranslation() + camC_;
1174 
1175  // J is the jacobian
1176  Matrix<double> J(6, 6, MatrixZero);
1177  for (int r=0; r<3; r++){
1178  //J[r][3] = C[r];
1179  for (int c=0; c<3; c++){
1180  J[r][c] = R[r][c];
1181  }
1182  }
1183 
1184  // now the second part
1185 
1186  cov = T.Transpose() * est_cov * T;
1187  cout << "est_cov: "<<est_cov<<"\ncov: "<<cov<<endl;
1188  return res;*/
1189 }
1190 
1191 
1192 int CamPoseCalib::SetInitialCamera(double fx, double fy, double cx, double cy)
1193 {
1194  initialGuess_=true;
1195  sx_=fx; sy_=fy;
1196  cx_=cx; cy_=cy;
1197  return 0;
1198 }
1199 
1201 {
1202  camR_.SetIdentity();
1203  camRT_.SetIdentity();
1204  camC_.Set(0,0,0);
1205  //// find 3 image points far away from each other
1206  BIAS::Vector2<double> i0(0,0),i1(0,0),i2(0,0),c(cx_,cy_);
1207  BIAS::Vector3<double> obj0,obj1,obj2; // corresponding model points
1208 
1209  double dist=0,newDist;
1210  int index=0;
1211  unsigned int i;
1212 
1213  // first point far away from image center
1214  for (i=0; i<tps_.size(); i++) {
1215  newDist=(tps_[i]-c).Length();
1216  if (newDist>dist) {
1217  i0=tps_[i]; dist=newDist;
1218  index=i;
1219  }
1220  }
1221  obj0=origMps_[index];
1222 
1223  // second point far away from first point
1224  dist=0; index=-1;
1225  for (i=0; i<tps_.size(); i++) {
1226  newDist = (tps_[i]-i0).Length();
1227  if ( newDist > dist) {
1228  i1=tps_[i]; dist=newDist;
1229  index=i;
1230  }
1231  }
1232  obj1=origMps_[index];
1233 
1234  //third point far away from connection between i0 and i1
1235  dist=0; index=-1;
1236  BIAS::Vector2<double> diff0,diff1;
1237  for (i=0; i<tps_.size(); i++) {
1238  diff0= tps_[i]-i0;
1239  diff1= tps_[i]-i1;
1240  newDist = fabs(diff0*diff1);
1241  if ( newDist > dist) {
1242  i2=tps_[i]; dist=newDist;
1243  index=i;
1244  }
1245  }
1246  if (index<0) return -2; // bad image point configuration
1247 
1248  obj2=origMps_[index];
1249 
1250  BIASDOUT(D_BIAS_CAMPOSE_INITGUESS,"found image points:"<<
1251  i0<<" "<<i1<<" "<<i2);
1252  BIASDOUT(D_BIAS_CAMPOSE_INITGUESS,"corresponding obj points:"<<
1253  obj0<<" "<<obj1<<" "<<obj2);
1254 
1255  //// construct orthonormal basis for i0,i1,i2 and obj0,obj1,obj2
1256  double sxy= (sx_+sy_) *0.5;
1257  if (sx_<=0) sxy=600;
1258  BIAS::Vector3<double> iw0(i0[0]-cx_,i0[1]-cy_,sxy), // iw = image world (3D)
1259  iw1(i1[0]-cx_,i1[1]-cy_,sxy),
1260  iw2(i2[0]-cx_,i2[1]-cy_,sxy), delta_iw0,delta_iw1,delta_iw2;
1261  BIAS::Vector3<double> delta_obj0,delta_obj1,delta_obj2;
1262  delta_iw0= iw1-iw0;
1263  if (delta_iw0.NormL2()<1e-10) return -1;
1264  delta_iw2= delta_iw0.CrossProduct(iw2-iw0);
1265  if (delta_iw2.NormL2()<1e-10) return -1;
1266  delta_iw1= delta_iw2.CrossProduct(delta_iw0);
1267  if (delta_iw1.NormL2()<1e-10) return -1;
1268 
1269  delta_obj0 = obj1 - obj0;
1270  if (delta_obj0.NormL2()<1e-10) return -1;
1271  delta_obj2 = delta_obj0.CrossProduct(obj2-obj0);
1272  if (delta_obj2.NormL2()<1e-10) return -1;
1273  delta_obj1 = delta_obj2.CrossProduct(delta_obj0);
1274  if (delta_obj1.NormL2()<1e-10) return -1;
1275 
1276  BIASDOUT(D_BIAS_CAMPOSE_INITGUESS,"delta Vecs image:"<<
1277  delta_iw0<<" "<< delta_iw1<<" "<< delta_iw2<<
1278  endl<<" and objects:"<<endl<<
1279  delta_obj0<<" "<< delta_obj1<<" "<< delta_obj2);
1280 
1281  //// use bases as rotation matrix and construct transform between both
1282  //// basis
1283  BIAS::RMatrix R_ci, R_co;
1284  delta_iw0.Normalize(); delta_iw1.Normalize(); delta_iw2.Normalize();
1285  R_ci.SetFromColumnVectors(delta_iw0,delta_iw1,delta_iw2);
1286  delta_obj0.Normalize(); delta_obj1.Normalize(); delta_obj2.Normalize();
1287  R_co.SetFromColumnVectors(delta_obj0,delta_obj1,delta_obj2);
1288  BIASDOUT(D_BIAS_CAMPOSE_INITGUESS,"normalized delta Vecs image:"<<
1289  delta_iw0<<" "<< delta_iw1<<" "<< delta_iw2<<
1290  endl<<" and objects:"<<endl<<
1291  delta_obj0<<" "<< delta_obj1<<" "<< delta_obj2);
1292  BIAS::SimilarityTransform T_ci, T_co;
1293  T_ci.SetR(R_ci); T_ci.SetC(iw0);
1294  T_co.SetR(R_co); T_co.SetC(obj0);
1295 
1296  BIASDOUT(D_BIAS_CAMPOSE_INITGUESS,"T_ci*(0,0,0) gives:"<<T_ci*
1297  BIAS::Vector3<double>(0,0,0));
1298 
1299  BIAS::SimilarityTransform finalT, moveT;
1300  T_co.InvertIP();
1301  BIASDOUT(D_BIAS_CAMPOSE_INITGUESS,"T_co^-1* obj0 gives:"<<T_co*obj0);
1302  finalT = T_ci * T_co;
1303 
1304  BIASDOUT(D_BIAS_CAMPOSE_INITGUESS,"finalT * obj0 gives:"<<finalT*obj0);
1305 
1306  //// now move the cam away from the object
1307  double mu = delta_obj0.Length() / (delta_iw0.Length() * iw0.Length());
1308  moveT.SetC(mu * iw0);
1309  finalT = moveT * finalT;
1310 
1311  //// set the final pose as initial cam pose
1312  finalT.InvertIP();
1313  camR_=finalT.GetR();
1315  camC_=finalT.GetC();
1316 
1317  // /// debug test
1318 // PMatrix PTest;
1319 // KMatrix KTest;
1320 // KTest.SetIdentity();
1321 // KTest[0][0]=sx_; KTest[1][1]=sy_;
1322 // KTest[0][2]=cx_; KTest[1][2]=cy_;
1323 // PTest.Compose(KTest,camR_,camC_);
1324 // cout<<" Projection of obj0:"<<obj0<<" should be:"<<i0<<" but is:";
1325 // HomgPoint2D(PTest*HomgPoint3D(obj0)).GetEuclidian(i0);
1326 // cout<<i0<<endl;
1327 // cout<<" Projection of obj1:"<<obj1<<" should be:"<<i1<<" but is:";
1328 // HomgPoint2D(PTest*HomgPoint3D(obj1)).GetEuclidian(i1);
1329 // cout<<i1<<endl;
1330  return 0;
1331 }
1332 
1333 
1335 {
1336  // multiply each two rows with the covar matrices
1337  int row=0, i=0;
1338  double dummyVal;
1339  while (row<solveVector_.size()) {
1340  const double &s00=variances_[i][0][0];
1341  const double &s01=variances_[i][0][1];
1342  const double &s10=variances_[i][1][0];
1343  const double &s11=variances_[i][1][1];
1344 
1345  // first the solveVector
1346  dummyVal= s00*solveVector_[row] + s01*solveVector_[row+1];
1347  solveVector_[row+1]= s10*solveVector_[row] + s11*solveVector_[row+1];
1348  solveVector_[row]=dummyVal;
1349 
1350  // now the matrix(Jacobian)
1351  for (int col=0;col<solveMatrix_.num_cols();col++) {
1352  dummyVal= s00* solveMatrix_[row][col] + s01* solveMatrix_[row+1][col];
1353  solveMatrix_[row+1][col]=
1354  s10*solveMatrix_[row][col] + s11* solveMatrix_[row+1][col];
1355  solveMatrix_[row][col]=dummyVal;
1356  }
1357  row+=2;
1358  i++;
1359  }
1360  return 0;
1361 }
1362 
1363 
1365  const BIAS::Vector2<double> &pointOnLine,
1366  const BIAS::Vector2<double> &normalOfLine)
1367 {
1368  origMpsLine_.push_back(x);
1369  tpsLinePoint_.push_back(pointOnLine);
1370  tpsLineNormal_.push_back(normalOfLine);
1371  return 0;
1372 }
std::vector< double > weightsLine_
std::vector< BIAS::Vector2< double > > tpsLineNormal_
std::vector< BIAS::Vector3< double > > initialMpsLine_
std::vector< BIAS::Vector3< double > > origMps_
void Set(const T *pv)
copy the array of vectorsize beginning at *T to this-&gt;data_
Definition: Vector3.hh:532
void SetXYZ(ROTATION_MATRIX_TYPE PhiX, ROTATION_MATRIX_TYPE PhiY, ROTATION_MATRIX_TYPE PhiZ)
Set Euler angles (in rad) in order XYZ.
computes and holds the singular value decomposition of a rectangular (not necessarily quadratic) Matr...
Definition: SVD.hh:92
Subscript num_cols() const
Definition: cmat.h:320
Vector< double > Solve(const Vector< double > &y) const
Definition: SVD.cpp:135
double Length() const
returns the Euclidean Length of the Vector
Definition: Vector3.hh:193
int GetCoVarMatrix(BIAS::Matrix< double > &coVar)
returns the covariance of the last estimate, which is (H=Hessian): H^{-1} * eps^T*eps * 1/(2n-p) The ...
void SetR(const BIAS::RMatrixBase &R)
Set rotational part from rotation matrix R.
void ScalarProduct(const Vector2< T > &argvec, T &result) const
scalar product of two vectors, storing the result in result
Definition: Vector2.hh:356
Matrix< T > Transpose() const
transpose function, storing data destination matrix
Definition: Matrix.hh:823
BIAS::Vector< double > GetResult() const
returns the result vector, corresponding to the covariance matrix
int ApplySolution_(BIAS::Vector< double > &result)
helper function for Estimate
Implements a 3D similarity transformation (rotation, translation, and isometric scaling).
BIAS::Matrix< double > coVarMat_
int Solve_(BIAS::Matrix< double > &J, BIAS::Vector< double > &eps, BIAS::Vector< double > &result)
Matrix< T > & newsize(Subscript M, Subscript N)
Definition: cmat.h:269
BIAS::Vector3< double > GetTranslation() const
this returns the translation from the initial camera center to the new camera center ...
BIAS::Vector< double > solveVector_
BIAS::Vector< double > GetEigenValues()
Call this after Compute(), returns the eigenvalues of the matrix in ascending order (smallest first)...
Definition: SVD.cpp:573
unsigned int Size() const
length of the vector
Definition: Vector.hh:143
std::vector< BIAS::Vector3< double > > mpsLine_
int GetR(Matrix3x3< double > &R)
Definition: PMatrix.cpp:204
void InvertIP()
Invert the similarity transform (in place)
this classs allows estimation of the internal (except skew) and external camera parameters by an iter...
Definition: CamPoseCalib.hh:86
void SetZero()
equivalent to matrix call
Definition: Vector.hh:156
bool doLM_
for LM algorithm extension
double GetAvgError()
returns the avg error of the estimation, which is the average difference of the projected points to t...
BIAS::Vector< double > Lapack_LU_linear_solve(const BIAS::Matrix< double > &A, const BIAS::Vector< double > &b)
solve linear equations using LU factorization
Definition: Lapack.cpp:269
BIAS::RMatrix camR_
void Reset()
clears the correspondences, such that u can do a new estimate,
void GetP(BIAS::PMatrix &P)
returns the estimated new projection matrix
double GetAvgSquaredWeightedError_()
returns the avg error of the estimation, which is the weighted average squared difference of the proj...
3D rotation matrix
Definition: RMatrix.hh:49
void outputPose_(int iteration)
double Dist(const Vector3< T > &vec) const
Return the euclidean distance of 2 vectors.
Definition: Vector3.hh:639
class Vector4 contains a Vector of dim.
Definition: Vector4.hh:65
Vector< T > & newsize(Subscript N)
Definition: vec.h:220
BIAS::Vector3< double > truthUpVec_
void SetZero()
Sets all values to zero.
Definition: Matrix.hh:856
void CrossProduct(const Vector3< T > &argvec, Vector3< T > &destvec) const
cross product of two vectors destvec = this x argvec
Definition: Vector3.hh:594
std::vector< BIAS::Vector2< double > > tps_
unsigned int GetRows() const
Definition: Matrix.hh:202
const double GetSingularValue(int index) const
return one singular value (which may be zero).
Definition: SVD.hh:386
void SetC(const Vector3< double > &C)
Set translational part from vector C.
int TransformVec(const BIAS::Vector< double > &src, BIAS::Vector< double > &dst)
int SetInitialCamera(const BIAS::KMatrix &K)
activates an automatic initial guess for the projection matrix, according to Christian Perwass&#39; habil...
BIAS::RMatrix camRT_
BIAS::Vector3< double > camC_
const bool calcSecD_
BIAS::RMatrix resultR_
BIAS::Matrix< double > solveMatrix_
BIAS::RMatrix GetRotation() const
this return the relative rotation from the initial camera orientation to the new estimated camera rot...
int SolveLM_(BIAS::Matrix< double > &J, BIAS::Vector< double > &eps, BIAS::Vector< double > &result, unsigned int iterations)
int CreateEquationSys_()
helper function for Estimate, creates the Jacobi matrix
BIAS::Vector3< double > resultTrans_
std::vector< BIAS::Vector3< double > > mps_
bool Equal(const T left, const T right, const T eps)
comparison function for floating point values See http://www.boost.org/libs/test/doc/components/test_...
unsigned int GetCols() const
Definition: Matrix.hh:204
int GetC(Vector3< double > &C)
computes translation vector origin world coo -&gt; origin camera coo (center), uses decomposition, which is cached
Definition: PMatrix.cpp:165
Matrix3x3< T > Transpose() const
returns transposed matrix tested 12.06.2002
Definition: Matrix3x3.cpp:167
std::vector< BIAS::Vector3< double > > origMpsLine_
int GetRotationAnglesXYZ(double &PhiX, double &PhiY, double &PhiZ) const
Get Euler angles for this rotation matrix in order XYZ.
Matrix< double > Invert()
returns pseudoinverse of A = U * S * V^T A^+ = V * S^+ * U^T
Definition: SVD.cpp:214
std::vector< BIAS::Vector3< double > > initialMps_
uses the unscented transformation to map a normal distribututed random variable using a nonlinear tra...
K describes the mapping from world coordinates (wcs) to pixel coordinates (pcs).
Definition: KMatrix.hh:48
Implements a 3D rotation matrix.
Definition: RMatrixBase.hh:44
std::vector< BIAS::Vector2< double > > tpsLinePoint_
Subscript num_rows() const
Definition: cmat.h:319
int GetRotationAxisAngle(Vector3< ROTATION_MATRIX_TYPE > &axis, ROTATION_MATRIX_TYPE &angle) const
Calculates angle and rotation axis representation for this rotation matrix.
BIAS::Matrix< double > secDMatrix_
describes a projective 3D -&gt; 2D mapping in homogenous coordinates
Definition: PMatrix.hh:88
void SetFromColumnVectors(const BIAS::Vector3< T > &v0, const BIAS::Vector3< T > &v1, const BIAS::Vector3< T > &v2)
set this matrix from 3 vectors each representating a column
Definition: Matrix3x3.cpp:208
int SetWeightsByError_()
for robust estimation
void MakeSymmetric()
componentwise: this = 0.5(this + this^T) yields symmetric matrix only allowed for square shaped matri...
Definition: Matrix.hh:522
BIAS::Vector3< double > truthOptAxis_
std::vector< double > weights_
void GetSystemMatrix(Matrix< T > &dest) const
compute square system matrix dest = A^T * A
Definition: Matrix.hh:1075
std::vector< BIAS::Matrix2x2< double > > variances_
int AddConstraints2DLine_()
adds rows for 3D-point-2D-point corrs
int AddCorr(const BIAS::Vector3< double > &x, const BIAS::Vector2< double > &y)
add a corresponding point pair
Vector3< T > & Normalize()
normalize this vector to length 1
Definition: Vector3.hh:663
BIAS::Vector3< double > truthCenter_
Subscript size() const
Definition: vec.h:262
double NormL2() const
the L2 norm sqrt(a^2 + b^2 + c^2)
Definition: Vector3.hh:633
void GetCov(BIAS::Matrix< double > &cov)
returns the covarinace of the last estimate in the world coo system
BIAS::RMatrix lastRot_
void Compose(const Matrix3x3< double > &K, const Matrix3x3< double > &R, const Vector3< double > &C)
composes this from K, R and C using P = [ K R&#39; | -K R&#39; C ] with R&#39; = transpose(R) ...
Definition: PMatrix.cpp:581
BIAS::PMatrix camP_
void SetIdentity()
set the elements of this matrix to the identity matrix (possibly overriding the inherited method) ...
Definition: Matrix3x3.hh:429
int Estimate(unsigned int iterations=20)
Does the calculation with a certain number of iterations.
int GetK(KMatrix &K)
calibration matrix
Definition: PMatrix.cpp:220