RPP.cpp
Go to the documentation of this file.
1 #include "RPP.h"
2 #include <cstdio>
3 
4 using namespace std;
5 using namespace cv;
6 
7 static double TOL = 1E-5;
8 static double EPSILON = 1E-8;
9 
10 namespace RPP
11 {
12 
13 bool Rpp(const Mat &model_3D, const Mat &iprts,
14  Mat &Rlu, Mat &tlu, int &it1, double &obj_err1, double &img_err1, vector<Solution> &sol)
15 {
16  // get a first guess of the pose.
17  if(Rlu.data) {
18  ObjPose(model_3D, iprts, Rlu, Rlu, tlu, it1, obj_err1, img_err1);
19  }
20  else {
21  ObjPose(model_3D, iprts, cv::Mat(), Rlu, tlu, it1, obj_err1, img_err1);
22  }
23 
24  // get 2nd Pose
25  // vector <Solution> sol;
26  bool status = Get2ndPose_Exact(iprts, model_3D, Rlu, tlu, sol);
27 
28  if(!status) {
29  return false;
30  }
31 
32  //refine with lu
33  int bestIdx=-1;
34  double lowestErr = 1e6;
35 
36  for(unsigned int i=0; i < sol.size(); i++) {
37  ObjPose(model_3D, iprts, sol[i].R, Rlu, sol[i].t, it1, obj_err1, img_err1);
38 
39  sol[i].R = Rlu;
40  sol[i].obj_err = obj_err1;
41  sol[i].img_err = img_err1;
42 
43  if(img_err1 < lowestErr) {
44  lowestErr = img_err1;
45  bestIdx = i;
46  }
47  }
48 
49  Rlu = sol[bestIdx].R;
50  tlu = sol[bestIdx].t;
51  obj_err1 = sol[bestIdx].obj_err;
52  img_err1 = sol[bestIdx].img_err;
53 
54 
55 // printf("Best solution: %d\n", bestIdx);
56 
57  // printf("Final R\n");
58  //Print(Rlu);
59 
60  //printf("Final t\n");
61  //Print(tlu);
62 
63  return true;
64 }
65 
66 void ObjPose(const Mat _P, Mat Qp, Mat initR,
67  Mat &R, Mat &t, int &it, double &obj_err, double &img_err)
68 {
69  Mat P = _P.clone(); // make a copy, else _P will get modified, nasty GOTCHA!
70 
71  int n = P.cols;
72  it = 0;
73 
74  Mat pbar = Sum(P,2) / n;
75 
76  // move the origin to the center of P
77  for(int i=0; i < n; i++) {
78  P.at<double>(0,i) -= pbar.at<double>(0,0);
79  P.at<double>(1,i) -= pbar.at<double>(1,0);
80  P.at<double>(2,i) -= pbar.at<double>(2,0);
81  }
82 
83  // compute projection matrices
84  vector <Mat> F(n);
85  Mat V(3,1,CV_64F);
86  Mat ret(1,1,CV_64F);
87 
88  for(int i=0; i < n; i++) {
89  F[i].create(3,3,CV_64F);
90 
91  V.at<double>(0,0) = Qp.at<double>(0,i);
92  V.at<double>(1,0) = Qp.at<double>(1,i);
93  V.at<double>(2,0) = Qp.at<double>(2,i);
94 
95  ret = V.t()*V;
96 
97  F[i] = (V*V.t()) / ret.at<double>(0,0);
98  }
99 
100  // compute the matrix factor required to compute t
101  Mat sumF = Mat::zeros(3,3,CV_64F);
102 
103  for(int i=0; i < n; i++) {
104  sumF += F[i];
105  }
106 
107  Mat tFactor = (Mat::eye(3,3,CV_64F)-sumF/n).inv()/n;
108 
109  double old_err;
110  Mat Qi;
111  Mat Ri, ti;
112 
113  if(initR.data) {
114  Ri = initR;
115 
116  Mat sum_ = Mat::zeros(3,1,CV_64F);
117 
118  Mat _eye = Mat::eye(3,3,CV_64F);
119  Mat PP(3,1,CV_64F);
120 
121  for(int i=0; i < n; i++) {
122  PP.at<double>(0,0) = P.at<double>(0,i);
123  PP.at<double>(1,0) = P.at<double>(1,i);
124  PP.at<double>(2,0) = P.at<double>(2,i);
125 
126  sum_ = sum_ + (F[i] - _eye)*Ri*PP;
127  }
128 
129  ti = tFactor*sum_;
130 
131  // calculate error
132  Qi = Xform(P, Ri, ti);
133 
134  old_err = 0;
135 
136  Mat vec(3,1,CV_64F);
137  Mat QiCol(3,1,CV_64F);
138 
139  for(int i=0; i < n; i++) {
140  QiCol.at<double>(0,0) = Qi.at<double>(0,i);
141  QiCol.at<double>(1,0) = Qi.at<double>(1,i);
142  QiCol.at<double>(2,0) = Qi.at<double>(2,i);
143 
144  vec = (_eye - F[i])*QiCol;
145 
146  double x = vec.at<double>(0,0);
147  double y = vec.at<double>(1,0);
148  double z = vec.at<double>(2,0);
149 
150  old_err += (x*x + y*y + z*z);
151  }
152  }
153  else {
154  // no initial guess; use weak-perspective approximation
155  AbsKernel(P, Qp, F, tFactor, Ri, ti, Qi, old_err);
156  it = 1;
157 
158  //printf("SVD\n");
159  //Print(Ri);
160  }
161 
162  // compute next pose estimate
163  double new_err;
164 
165  AbsKernel(P, Qi, F, tFactor, Ri, ti, Qi, new_err);
166 
167  it = it + 1;
168 
169  //printf("before while\n");
170 
171  while(fabs((old_err-new_err)/old_err) > TOL && (new_err > EPSILON)) {
172  old_err = new_err;
173  // compute the optimal estimate of R
174  AbsKernel(P, Qi, F, tFactor, Ri, ti, Qi, new_err);
175 
176  //printf("it %d\n", it);
177  it = it + 1;
178  }
179 
180  R = Ri;
181  t = ti;
182  obj_err = sqrt(new_err/n);
183 
184  // calculate image-space error
185  Mat Pcol(3,1,CV_64F);
186  Mat Qproj;
187 
188  img_err = 0;
189 
190  for(int i=0; i < n; i++) {
191  Pcol.at<double>(0,0) = P.at<double>(0,i);
192  Pcol.at<double>(1,0) = P.at<double>(1,i);
193  Pcol.at<double>(2,0) = P.at<double>(2,i);
194 
195  Qproj = Ri*Pcol + ti;
196 
197  double xx = (Qproj.at<double>(0,0)/Qproj.at<double>(2,0)) - Qp.at<double>(0,0);
198  double yy = (Qproj.at<double>(1,0)/Qproj.at<double>(2,0)) - Qp.at<double>(1,0);
199 
200  img_err += (xx*xx + yy*yy);
201  }
202 
203  img_err = sqrt(img_err/n);
204 
205  // get back to original refernce frame
206 
207  t = t - Ri*pbar;
208 }
209 
210 Mat EstimateT(const Mat &R, const Mat &G, const vector <Mat> &F, const Mat &P)
211 {
212  Mat sum = Mat::zeros(3,1,CV_64F);
213 
214  Mat PP(3,1,CV_64F);
215 
216  for(int i=0; i < P.cols; i++) {
217  PP.at<double>(0,0) = P.at<double>(0,i);
218  PP.at<double>(1,0) = P.at<double>(1,i);
219  PP.at<double>(2,0) = P.at<double>(2,i);
220 
221  sum += F[i]*R*PP;
222  }
223 
224  Mat ret = G*sum;
225 
226  return ret;
227 }
228 
229 void AbsKernel(Mat P, Mat Q, const vector <Mat> &F, const Mat &G,
230  Mat &R, Mat &t, Mat &Qout, double &err2)
231 {
232  int n = P.cols;
233 
234  Mat QQ(3,1,CV_64F);
235 
236  for(int i=0; i < n; i++) {
237  QQ.at<double>(0,0) = Q.at<double>(0,i);
238  QQ.at<double>(1,0) = Q.at<double>(1,i);
239  QQ.at<double>(2,0) = Q.at<double>(2,i);
240 
241  QQ= F[i]*QQ;
242 
243  Q.at<double>(0,i) = QQ.at<double>(0,0);
244  Q.at<double>(1,i) = QQ.at<double>(1,0);
245  Q.at<double>(2,i) = QQ.at<double>(2,0);
246  }
247 
248  Mat pbar = Sum(P,2)/n;
249  Mat qbar = Sum(Q,2)/n;
250 
251  // compute P' and Q'
252  for(int i=0; i < n; i++) {
253  P.at<double>(0,i) -= pbar.at<double>(0,0);
254  P.at<double>(1,i) -= pbar.at<double>(1,0);
255  P.at<double>(2,i) -= pbar.at<double>(2,0);
256  }
257 
258  // use SVD solution
259  // compute M matrix
260  Mat M = Mat::zeros(3,3,CV_64F);
261  Mat PP(3,1,CV_64F);
262 
263  for(int i=0; i < n; i++) {
264  PP.at<double>(0,0) = P.at<double>(0,i);
265  PP.at<double>(1,0) = P.at<double>(1,i);
266  PP.at<double>(2,0) = P.at<double>(2,i);
267 
268  QQ.at<double>(0,0) = Q.at<double>(0,i);
269  QQ.at<double>(1,0) = Q.at<double>(1,i);
270  QQ.at<double>(2,0) = Q.at<double>(2,i);
271 
272  M += PP*QQ.t();
273  }
274 
275  SVD decomp(M);
276 
277  R = decomp.vt.t()*(decomp.u.t());
278  Mat v = decomp.vt.t();
279 
280  if(sign(determinant(R)) == 1) {
281  t = EstimateT(R,G,F,P);
282 
283  if(t.at<double>(2,0) < 0) {
284  // we need to invert the t
285  // negate the 3rd column
286 
287  v.at<double>(0,2) = -v.at<double>(0,2);
288  v.at<double>(1,2) = -v.at<double>(1,2);
289  v.at<double>(2,2) = -v.at<double>(2,2);
290 
291  // we need to invert the t
292  R = -v*decomp.u.t();
293  t = EstimateT(R,G,F,P);
294  }
295  }
296  else {
297  // negate the 3rd column
298  v.at<double>(0,2) = -v.at<double>(0,2);
299  v.at<double>(1,2) = -v.at<double>(1,2);
300  v.at<double>(2,2) = -v.at<double>(2,2);
301 
302  R = v*decomp.u.t();
303  t = EstimateT(R,G,F,P);
304 
305  if(t.at<double>(2,0) < 0) {
306  R = -v*(decomp.u.t());
307  t = EstimateT(R,G,F,P);
308  }
309  }
310 
311 
312  // calculate error
313  Mat _eye = Mat::eye(3,3,CV_64F);
314  Mat vec(3,1,CV_64F);
315 
316  err2 = 0;
317  Qout = Xform(P, R, t);
318 
319  for(int i=0; i < n; i++) {
320  QQ.at<double>(0,0) = Qout.at<double>(0,i);
321  QQ.at<double>(1,0) = Qout.at<double>(1,i);
322  QQ.at<double>(2,0) = Qout.at<double>(2,i);
323 
324  vec = (_eye - F[i])*QQ;
325 
326  double x = vec.at<double>(0,0);
327  double y = vec.at<double>(1,0);
328  double z = vec.at<double>(2,0);
329 
330  err2 += (x*x + y*y + z*z);
331  }
332 }
333 
334 Mat NormRv(const Mat &R)
335 {
336  Mat ret(R.rows, R.cols, CV_64F);
337 
338  for(int i=0; i < R.cols; i++) {
339 
340  double mag = R.at<double>(0,i)*R.at<double>(0,i) +
341  R.at<double>(1,i)*R.at<double>(1,i) +
342  R.at<double>(2,i)*R.at<double>(2,i);
343 
344  double m = 1.f/sqrt(mag);
345 
346  ret.at<double>(0,i) = R.at<double>(0,i)*m;
347  ret.at<double>(1,i) = R.at<double>(1,i)*m;
348  ret.at<double>(2,i) = R.at<double>(2,i)*m;
349  }
350 
351  return ret;
352 }
353 
354 Mat NormRv(const Vec3d &V)
355 {
356  Mat ret(3,1,CV_64F);
357 
358  double mag = sqrt(V[0]*V[0] + V[1]*V[1] + V[2]*V[2]);
359 
360  ret.at<double>(0,0) = V[0] / mag;
361  ret.at<double>(1,0) = V[1] / mag;
362  ret.at<double>(2,0) = V[2] / mag;
363 
364  return ret;
365 }
366 
367 Quaternion Quaternion_byAngleAndVector(double q_angle, const Vec3d &q_vector)
368 {
369  //printf("Quaternion_byAngleAndVector\n");
370 
371  // rotation_axis=q_vector/norm(q_vector);
372  // matlab norm with default argument of 2 is largest singular value
373  double n = Norm(Vec2Mat(q_vector));
374 
375  //printf("n = %f\n", n);
376 
377  Vec3d rotation_axis = q_vector;
378 
379  rotation_axis[0] /= n;
380  rotation_axis[1] /= n;
381  rotation_axis[2] /= n;
382 
383  rotation_axis[0] *= sin(q_angle*0.5);
384  rotation_axis[1] *= sin(q_angle*0.5);
385  rotation_axis[2] *= sin(q_angle*0.5);
386 
387  Quaternion Q_ = Quaternion_byVectorAndScalar(rotation_axis, cos(q_angle*0.5));
388 
389  //printf("Q_\n");
390  //Print(Q_);
391 
392 // double a = 1/Quaternion_Norm(Q_);
393 
394  //printf("a = %f\n", a);
395 
397 
398  return Q;
399 }
400 
401 Mat quat2mat(const Quaternion &Q)
402 {
403  double a = Q.scalar;
404  double b = Q.vector[0];
405  double c = Q.vector[1];
406  double d = Q.vector[2];
407 
408  Mat R(3,3,CV_64F);
409 
410  R.at<double>(0,0) = a*a + b*b - c*c -d*d;
411  R.at<double>(0,1) = 2*(b*c - a*d);
412  R.at<double>(0,2) = 2*(b*d + a*c);
413 
414  R.at<double>(1,0) = 2*(b*c + a*d);
415  R.at<double>(1,1) = a*a + c*c - b*b - d*d;
416  R.at<double>(1,2) = 2*(c*d - a*b);
417 
418  R.at<double>(2,0) = 2*(b*d - a*c);
419  R.at<double>(2,1) = 2*(c*d + a*b);
420  R.at<double>(2,2) = a*a + d*d - b*b -c*c;
421 
422  return R;
423 }
424 
425 Mat GetRotationbyVector(const Vec3d &v1, const Vec3d &v2)
426 {
427  //printf("GetRotationbyVector\n");
428 
429  double winkel = acos(v2.dot(v1));
430 
431  //printf("winkel = %f\n", winkel);
432 
433  Quaternion QU = Quaternion_byAngleAndVector(winkel,v2.cross(v1));
434 
435  //printf("QU\n");
436  //Print(QU);
437 
438  Mat R = quat2mat(QU);
439 
440  //printf("R\n");
441  //Print(R);
442 
443  Mat a = Sum(Sq(NormRv(v1) - R*NormRv(v2)));
444 
445  //printf("a\n");
446  //Print(a);
447 
448  double mag = a.at<double>(0,0)*a.at<double>(0,0);
449 
450  if(mag > 1e-3) {
451  fprintf(stderr, "Error in GetRotationbyVector()\n");
452  exit(1);
453  }
454 
455  return R;
456 }
457 
458 Mat Sum(const Mat &m, int dim)
459 {
460  // columns
461  if(dim == 1) {
462  Mat ret(1, m.cols, CV_64F);
463 
464  for(int j=0; j < m.cols; j++) {
465  double sum = 0;
466 
467  for(int i=0; i < m.rows; i++) {
468  sum += m.at<double>(i,j);
469  }
470 
471  ret.at<double>(0,j) = sum;
472  }
473 
474  return ret;
475  }
476  else {
477  Mat ret(m.rows, 1, CV_64F);
478 
479  for(int i=0; i < m.rows; i++) {
480  double sum = 0;
481 
482  for(int j=0; j < m.cols; j++) {
483  sum += m.at<double>(i,j);
484  }
485 
486  ret.at<double>(i,0) = sum;
487  }
488 
489  return ret;
490  }
491 }
492 
493 Mat Mul(const Mat &a, const Mat &b)
494 {
495  assert(a.rows == b.rows && a.cols == b.cols);
496 
497  Mat ret(a.rows, a.cols, CV_64F);
498 
499  for(int i=0; i < a.rows; i++) {
500  for(int j=0; j < a.cols; j++) {
501  ret.at<double>(i,j) = a.at<double>(i,j)*b.at<double>(i,j);
502  }
503  }
504 
505  return ret;
506 }
507 
508 Mat Mean(const Mat &m)
509 {
510  Mat ret(1, m.cols, CV_64F);
511 
512  for(int j=0; j < m.cols; j++) {
513  double sum = 0;
514 
515  for(int i=0; i < m.rows; i++) {
516  sum += m.at<double>(i,j);
517  }
518 
519  ret.at<double>(0,j) = sum / m.cols;
520  }
521 
522  return ret;
523 }
524 
525 Mat Point2Mat(const vector <Point3d> &pts)
526 {
527  Mat ret(3, pts.size(), CV_64F);
528 
529  for(unsigned int i=0; i < pts.size(); i++) {
530  ret.at<double>(0,i) = pts[i].x;
531  ret.at<double>(1,i) = pts[i].y;
532  ret.at<double>(2,i) = pts[i].z;
533  }
534 
535  return ret;
536 }
537 
538 Mat Point2Mat(const vector <Point2d> &pts)
539 {
540  Mat ret(3, pts.size(), CV_64F);
541 
542  for(unsigned int i=0; i < pts.size(); i++) {
543  ret.at<double>(0,i) = pts[i].x;
544  ret.at<double>(1,i) = pts[i].y;
545  ret.at<double>(2,i) = 1.f;
546  }
547 
548  return ret;
549 }
550 
551 Mat Vec2Mat(const Vec3d &v)
552 {
553  Mat ret(3,1,CV_64F);
554 
555  ret.at<double>(0,0) = v[0];
556  ret.at<double>(1,0) = v[1];
557  ret.at<double>(2,0) = v[2];
558 
559  return ret;
560 }
561 
562 
563 Mat RpyMat(const Vec3d &angs)
564 {
565  double cosA = cos(angs[2]);
566  double sinA = sin(angs[2]);
567  double cosB = cos(angs[1]);
568  double sinB = sin(angs[1]);
569  double cosC = cos(angs[0]);
570  double sinC = sin(angs[0]);
571 
572  double cosAsinB = cosA*sinB;
573  double sinAsinB = sinA*sinB;
574 
575  Mat R(3,3,CV_64F);
576 
577  R.at<double>(0,0) = cosA*cosB;
578  R.at<double>(0,1) = cosAsinB*sinC-sinA*cosC;
579  R.at<double>(0,2) = cosAsinB*cosC+sinA*sinC;
580 
581  R.at<double>(1,0) = sinA*cosB;
582  R.at<double>(1,1) = sinAsinB*sinC+cosA*cosC;
583  R.at<double>(1,2) = sinAsinB*cosC-cosA*sinC;
584 
585  R.at<double>(2,0) = -sinB;
586  R.at<double>(2,1) = cosB*sinC;
587  R.at<double>(2,2) = cosB*cosC;
588 
589  return R;
590 }
591 
592 bool RpyAng(const Mat &R, Vec3d &ret)
593 {
594  //printf("\nRpyAng\n");
595 
596  Vec3d angs;
597 
598  double R11 = R.at<double>(0,0);
599  double R12 = R.at<double>(0,1);
600  double R13 = R.at<double>(0,2);
601 
602  double R21 = R.at<double>(1,0);
603  double R22 = R.at<double>(1,1);
604  double R23 = R.at<double>(1,2);
605 
606  double R31 = R.at<double>(2,0);
607  double R32 = R.at<double>(2,1);
608  double R33 = R.at<double>(2,2);
609 
610  double sinB = -R31;
611  double cosB = sqrt(R11*R11 + R21*R21);
612 
613  if(fabs (cosB) > 1e-15) {
614  double sinA = R21 / cosB;
615  double cosA = R11 / cosB;
616  double sinC = R32 / cosB;
617  double cosC = R33 / cosB;
618  angs[0] = atan2(sinC,cosC);
619  angs[1] = atan2(sinB,cosB);
620  angs[2] = atan2(sinA,cosA);
621  }
622  else {
623  double sinC = (R12 - R23) / 2;
624  double cosC = (R22 + R13) / 2;
625  angs[0] = atan2(sinC,cosC);
626  angs[1] = M_PI_2;
627  angs[2] = 0;
628 
629  if(sinB < 0)
630  angs = -angs;
631  }
632 
633  //printf("R\n");
634  //Print(R);
635 
636  //printf("angs\n");
637  //Print(Vec2Mat(angs));
638 
639  //printf("angs: %f %f %f\n", angs[0], angs[1], angs[2]);
640 
641  Mat a = R-RpyMat(angs);
642 
643  //printf("a\n");
644  //Print(a);
645 
646  //double a = Norm(R-RpyMat(angs));
647  //printf("a = %f\n", a);
648 
649  if(Norm(R-RpyMat(angs)) > 1e-6) {
650  fprintf(stderr, "rpyMat: Error not correct Solution\n");
651  return false;
652  }
653 
654  ret = angs;
655 
656  return true;
657 }
658 
659 bool RpyAng_X(const Mat &R, Vec3d &ret)
660 {
661  Vec3d ang_zyx;
662  bool status = RpyAng(R, ang_zyx);
663 
664  if(!status) {
665  return false;
666  }
667 
668  if(fabs(ang_zyx[0]) > M_PI_2) {
669  // test the same R
670  while ( fabs(ang_zyx[0]) > M_PI_2 ) {
671  if(ang_zyx[0] > 0) {
672  ang_zyx[0] = ang_zyx[0]+M_PI;
673  ang_zyx[1] = 3*M_PI-ang_zyx[1];
674  ang_zyx[2] = ang_zyx[2]+M_PI;
675 
676  ang_zyx[0] -= 2*M_PI;
677  ang_zyx[1] -= 2*M_PI;
678  ang_zyx[2] -= 2*M_PI;
679  }
680  else {
681  ang_zyx[0] = ang_zyx[0]+M_PI;
682  ang_zyx[1] = 3*M_PI-ang_zyx[1];
683  ang_zyx[2] = ang_zyx[2]+M_PI;
684  }
685  }
686  }
687 
688  ret = ang_zyx;
689 
690  return true;
691 }
692 
693 bool Get2ndPose_Exact(const Mat &v, const Mat &P, const Mat &R, const Mat &t, vector<Solution> &ret)
694 {
695  //printf("Get2ndPose_Exact\n");
696 
697  Mat cent = NormRv(Mean(NormRv(v).t()).t());
698  Vec3d _cent;
699 
700  _cent[0] = cent.at<double>(0,0);
701  _cent[1] = cent.at<double>(1,0);
702  _cent[2] = cent.at<double>(2,0);
703 
704  Mat Rim = GetRotationbyVector(Vec3d(0,0,1), _cent);
705 
706  Mat v_ = Rim*v;
707  cent = NormRv(Mean(NormRv(v_).t()).t());
708 
709  Mat R_ = Rim*R;
710  Mat t_ = Rim*t;
711 /*
712  printf("cent\n");
713  Print(cent);
714 
715  printf("Rim\n");
716  Print(Rim);
717 
718  printf("R\n");
719  Print(R);
720 
721  printf("t\n");
722  Print(t);
723 
724  printf("R_\n");
725  Print(R_);
726 
727  printf("t_\n");
728  Print(t_);
729 */
730  vector<Solution> sol;
731 
732  bool status = GetRfor2ndPose_V_Exact(v_,P,R_,t_, sol);
733 
734  if(!status) {
735  return false;
736  }
737 
738  // de Normalise the Pose
739  for(unsigned int i=0; i < sol.size(); i++) {
740  //printf("BEFORE\n");
741  //Print(sol[i].R);
742 
743  sol[i].R = Rim.t()*sol[i].R;
744 
745  //printf("AFTER\n");
746  //Print(sol[i].R);
747  sol[i].t = Rim.t()*sol[i].t;
748  }
749 
750  ret = sol;
751 
752  return true;
753 }
754 
755 bool DecomposeR(const Mat &R, Mat &Rz2, Mat &ret)
756 {
757  //printf("\nDecomposeR\n");
758 
759  double cl = atan2(R.at<double>(2,1), R.at<double>(2,0));
760  Mat Rz = RpyMat(Vec3d(0,0,cl));
761 /*
762  printf("cl = %f\n", cl);
763  printf("Rz\n");
764  Print(Rz);
765  printf("R\n");
766  Print(R);
767 */
768  Mat R_ = R*Rz;
769 
770  //printf("R_\n");
771  //Print(R_);
772 
773  if(R_.at<double>(2,1) > 1e-3) {
774  fprintf(stderr, "error in DecomposeR 1\n");
775  return false;
776  }
777 
778  Vec3d ang_zyx;
779  bool status = RpyAng_X(R_, ang_zyx);
780 
781  if(!status) {
782  return false;
783  }
784 
785  if(fabs(ang_zyx[0]) > 1e-3) {
786  fprintf(stderr, "error in DecomposeR 2\n");
787  return false;
788  }
789 
790  Rz2 = Rz*RpyMat(Vec3d(0,0,M_PI));
791  R_ = R*Rz2;
792 
793  if(R_.at<double>(2,1) > 1e-3) {
794  fprintf(stderr, "error in DecomposeR 3\n");
795  return false;
796  }
797 
798  // why do we do this?
799  status = RpyAng_X(R_, ang_zyx);
800 
801  if(!status) {
802  return false;
803  }
804 
805  ret = Rz;
806 
807  return true;
808 }
809 
810 Mat Sq(const Mat &m)
811 {
812  Mat ret(m.rows, m.cols, CV_64F);
813 
814  for(int i=0; i < m.rows; i++) {
815  for(int j=0; j < m.cols; j++) {
816  ret.at<double>(i,j) = m.at<double>(i,j)*m.at<double>(i,j);
817  }
818  }
819 
820  return ret;
821 }
822 
823 Mat Xform(const Mat &P, const Mat &R, const Mat &t)
824 {
825  Mat ret(3,P.cols,CV_64F);
826 
827  for(int i=0; i < P.cols; i++) {
828  double x = P.at<double>(0,i);
829  double y = P.at<double>(1,i);
830  double z = P.at<double>(2,i);
831 
832  ret.at<double>(0,i) = R.at<double>(0,0)*x + R.at<double>(0,1)*y + R.at<double>(0,2)*z + t.at<double>(0,0);
833  ret.at<double>(1,i) = R.at<double>(1,0)*x + R.at<double>(1,1)*y + R.at<double>(1,2)*z + t.at<double>(1,0);
834  ret.at<double>(2,i) = R.at<double>(2,0)*x + R.at<double>(2,1)*y + R.at<double>(2,2)*z + t.at<double>(2,0);
835  }
836 
837  return ret;
838 }
839 
840 double Norm(const Mat &m)
841 {
842  SVD decomp(m);
843 
844  return decomp.w.at<double>(0,0);
845 }
846 
847 bool GetRfor2ndPose_V_Exact(const Mat &v, const Mat &P, const Mat &R, const Mat &t, vector<Solution> &ret)
848 {
849  //printf("\nGetRfor2ndPose_V_Exact\n");
850  //printf("R\n");
851  //Print(R);
852 
853  Mat Rz2;
854  Mat RzN;
855 
856  bool status = DecomposeR(R, Rz2, RzN);
857 
858  if(!status) {
859  return false;
860  }
861 
862  Mat R_ = R*RzN;
863 
864  Mat P_ = RzN.t()*P;
865 
866  Vec3d ang_zyx;
867 
868  status = RpyAng_X(R_, ang_zyx);
869 
870  if(!status) {
871  return false;
872  }
873 
874  Mat Ry = RpyMat(Vec3d(0,ang_zyx[1],0));
875  Mat Rz = RpyMat(Vec3d(0,0,ang_zyx[2]));
876 
877  vector <double> bl;
878  Mat Tnew;
879  vector <double> at;
880 
881  GetRotationY_wrtT(v ,P_,t,Rz, bl, Tnew, at);
882 
883  // Suggestion by csantos
884  if(bl.empty()) {
885  return false;
886  }
887 
888  for(unsigned int i=0; i < bl.size(); i++) {
889  bl[i] = bl[i]/180*M_PI;
890  }
891 
892  // we got 2 solutions. YEAH
893  vector <Mat> V(v.cols);
894 
895  Mat tmp(3,1,CV_64F);
896 
897  for(int i=0; i < v.cols; i++) {
898  tmp.at<double>(0,0) = v.at<double>(0,i);
899  tmp.at<double>(1,0) = v.at<double>(1,i);
900  tmp.at<double>(2,0) = v.at<double>(2,i);
901 
902  Mat a = tmp.t()*tmp;
903 
904  V[i] = tmp*tmp.t() / a.at<double>(0,0);
905  }
906 
907  vector <Solution> sol(bl.size());
908 
909  for(unsigned int j=0; j < bl.size(); j++) {
910  sol[j].bl = bl[j];
911  sol[j].at = at[j];
912 
913  Ry = RpyMat(Vec3d(0,bl[j],0));
914  sol[j].R = Rz*Ry*RzN.t();
915 
916  //printf("sol[j].R\n");
917  //Print(sol[j].R);
918 
919 
920  sol[j].t.at<double>(0,0) = Tnew.at<double>(0,j);
921  sol[j].t.at<double>(1,0) = Tnew.at<double>(1,j);
922  sol[j].t.at<double>(2,0) = Tnew.at<double>(2,j);
923 
924  // test the Error
925  double E=0;
926  Mat _eye = Mat::eye(3,3,CV_64F);
927  Mat Pcol(3,1,CV_64F);
928 
929  for(int i=0; i < v.cols; i++) {
930  Pcol.at<double>(0,0) = P.at<double>(0,i);
931  Pcol.at<double>(1,0) = P.at<double>(1,i);
932  Pcol.at<double>(2,0) = P.at<double>(2,i);
933 
934  Mat a = Sum(Sq((_eye - V[i])*(sol[j].R*Pcol + sol[j].t)));
935 
936  E = E + a.at<double>(0,0);
937  }
938 
939  sol[j].E = E;
940  }
941 
942  ret = sol;
943 
944  return true;
945 }
946 
947 void GetRotationY_wrtT(const Mat &v, const Mat &p, const Mat &t, const Mat &Rz,
948  vector <double> &al, Mat &tnew, vector <double> &at)
949 {
950 
951 /*
952 if nargin == 4,
953  Rz = eye(3);
954 end
955 */
956 
957  vector <Mat> V(v.cols);
958  Mat vv(3,1,CV_64F);
959 
960  for(int i=0; i < v.cols; i++) {
961  vv.at<double>(0,0) = v.at<double>(0,i);
962  vv.at<double>(1,0) = v.at<double>(1,i);
963  vv.at<double>(2,0) = v.at<double>(2,i);
964 
965  Mat tmp = vv.t()*vv;
966  double a = tmp.at<double>(0,0);
967  V[i] = (vv*vv.t()) / a;
968  }
969 
970  //generate G
971  Mat G = Mat::zeros(3,3,CV_64F);
972 
973  for(int i=0; i < v.cols; i++) {
974  G += V[i];
975  }
976 
977  Mat _eye = Mat::eye(3,3,CV_64F);
978 
979  G = (_eye - G/v.cols).inv()/v.cols;
980 
981  //printf("G\n");
982  //Print(G);
983 
984  // generate opt_t*[bt^2 bt 1]
985 
986  Mat opt_t = Mat::zeros(3,3,CV_64F);
987 
988  for(int i=0; i < v.cols; i++) {
989  double v11 = V[i].at<double>(0,0);
990  double v12 = V[i].at<double>(0,1);
991  double v13 = V[i].at<double>(0,2);
992  double v21 = V[i].at<double>(1,0);
993  double v22 = V[i].at<double>(1,1);
994  double v23 = V[i].at<double>(1,2);
995  double v31 = V[i].at<double>(2,0);
996  double v32 = V[i].at<double>(2,1);
997  double v33 = V[i].at<double>(2,2);
998 
999  double px = p.at<double>(0,i);
1000  double py = p.at<double>(1,i);
1001  double pz = p.at<double>(2,i);
1002 
1003  double r1 = Rz.at<double>(0,0);
1004  double r2 = Rz.at<double>(0,1);
1005  double r3 = Rz.at<double>(0,2);
1006 
1007  double r4 = Rz.at<double>(1,0);
1008  double r5 = Rz.at<double>(1,1);
1009  double r6 = Rz.at<double>(1,2);
1010 
1011  double r7 = Rz.at<double>(2,0);
1012  double r8 = Rz.at<double>(2,1);
1013  double r9 = Rz.at<double>(2,2);
1014 
1015  opt_t.at<double>(0,0) += (((v11-1)*r2+v12*r5+v13*r8)*py+(-(v11-1)*r1-v12*r4-v13*r7)*px+(-(v11-1)*r3-v12*r6-v13*r9)*pz);
1016  opt_t.at<double>(0,1) += ((2*(v11-1)*r1+2*v12*r4+2*v13*r7)*pz+(-2*(v11-1)*r3-2*v12*r6-2*v13*r9)*px);
1017  opt_t.at<double>(0,2) += ((v11-1)*r1+v12*r4+v13*r7)*px+((v11-1)*r3+v12*r6+v13*r9)*pz+((v11-1)*r2+v12*r5+v13*r8)*py;
1018 
1019  opt_t.at<double>(1,0) += ((v21*r2+(v22-1)*r5+v23*r8)*py+(-v21*r1-(v22-1)*r4-v23*r7)*px+(-v21*r3-(v22-1)*r6-v23*r9)*pz);
1020  opt_t.at<double>(1,1) += ((2*v21*r1+2*(v22-1)*r4+2*v23*r7)*pz+(-2*v21*r3-2*(v22-1)*r6-2*v23*r9)*px);
1021  opt_t.at<double>(1,2) += (v21*r1+(v22-1)*r4+v23*r7)*px+(v21*r3+(v22-1)*r6+v23*r9)*pz+(v21*r2+(v22-1)*r5+v23*r8)*py;
1022 
1023  opt_t.at<double>(2,0) += ((v31*r2+v32*r5+(v33-1)*r8)*py+(-v31*r1-v32*r4-(v33-1)*r7)*px+(-v31*r3-v32*r6-(v33-1)*r9)*pz);
1024  opt_t.at<double>(2,1) += ((2*v31*r1+2*v32*r4+2*(v33-1)*r7)*pz+(-2*v31*r3-2*v32*r6-2*(v33-1)*r9)*px);
1025  opt_t.at<double>(2,2) += (v31*r1+v32*r4+(v33-1)*r7)*px+(v31*r3+v32*r6+(v33-1)*r9)*pz+(v31*r2+v32*r5+(v33-1)*r8)*py;
1026  }
1027 
1028  opt_t = G*opt_t;
1029 
1030  Mat E_2 = Mat::zeros(1,5,CV_64F);
1031 
1032 
1033  // estimate Error function E
1034  for(int i=0; i < v.cols; i++) {
1035  double px = p.at<double>(0,i);
1036  double py = p.at<double>(1,i);
1037  double pz = p.at<double>(2,i);
1038 
1039  Mat Rpi(3,3,CV_64F);
1040 
1041  Rpi.at<double>(0,0) = -px;
1042  Rpi.at<double>(0,1) = 2*pz;
1043  Rpi.at<double>(0,2) = px;
1044 
1045  Rpi.at<double>(1,0) = py;
1046  Rpi.at<double>(1,1) = 0;
1047  Rpi.at<double>(1,2) = py;
1048 
1049  Rpi.at<double>(2,0) = -pz;
1050  Rpi.at<double>(2,1) = -2*px;
1051  Rpi.at<double>(2,2) = pz;
1052 
1053  Mat E = (_eye - V[i])*(Rz*Rpi + opt_t);
1054 
1055  Mat e0(3,1,CV_64F);
1056  Mat e1(3,1,CV_64F);
1057  Mat e2(3,1,CV_64F);
1058 
1059  e0.at<double>(0,0) = E.at<double>(0,2);
1060  e0.at<double>(1,0) = E.at<double>(1,2);
1061  e0.at<double>(2,0) = E.at<double>(2,2);
1062 
1063  e1.at<double>(0,0) = E.at<double>(0,1);
1064  e1.at<double>(1,0) = E.at<double>(1,1);
1065  e1.at<double>(2,0) = E.at<double>(2,1);
1066 
1067  e2.at<double>(0,0) = E.at<double>(0,0);
1068  e2.at<double>(1,0) = E.at<double>(1,0);
1069  e2.at<double>(2,0) = E.at<double>(2,0);
1070 
1071 /*
1072  printf("E\n");
1073  Print(E);
1074 
1075  printf("e2\n");
1076  Print(e2);
1077 */
1078  Mat sum1 = Sum(Sq(e2));
1079  //printf("e2\n");
1080  //Print(e2);
1081 
1082  Mat sum2 = Sum(2*Mul(e1,e2));
1083 
1084  //printf("e2\n");
1085  //Print(e2);
1086 
1087  Mat sum3 = Sum(2*Mul(e0,e2) + Sq(e1));
1088 
1089  //printf("e2\n");
1090  //Print(e2);
1091 
1092  Mat sum4 = Sum(2*Mul(e0,e1));
1093  Mat sum5 = Sum(Sq(e0));
1094 
1095 
1096 
1097 
1098  // E_2 =E_2+ sum([e2.^2 2.*e1.*e2 (2.*e0.*e2+e1.^2) 2.*e0.*e1 e0.^2]);
1099  E_2.at<double>(0,0) += sum1.at<double>(0,0);
1100  E_2.at<double>(0,1) += sum2.at<double>(0,0);
1101  E_2.at<double>(0,2) += sum3.at<double>(0,0);
1102  E_2.at<double>(0,3) += sum4.at<double>(0,0);
1103  E_2.at<double>(0,4) += sum5.at<double>(0,0);
1104  }
1105 
1106  double e4=E_2.at<double>(0,0);
1107  double e3=E_2.at<double>(0,1);
1108  double e2=E_2.at<double>(0,2);
1109  double e1=E_2.at<double>(0,3);
1110  double e0=E_2.at<double>(0,4);
1111 
1112  //printf("e0 to e4 = %f %f %f %f %f\n", e0, e1, e2, e3, e4);
1113 
1114  double a4=-e3;
1115  double a3=(4*e4-2*e2);
1116  double a2=(-3*e1+3*e3);
1117  double a1=(-4*e0+2*e2);
1118  double a0=e1;
1119 
1120  double coeffs[5];
1121 // double z[10];
1122 /*
1123  // backwards in GSL
1124  coeffs[0] = a0;
1125  coeffs[1] = a1;
1126  coeffs[2] = a2;
1127  coeffs[3] = a3;
1128  coeffs[4] = a4;
1129 */
1130  coeffs[0] = a4;
1131  coeffs[1] = a3;
1132  coeffs[2] = a2;
1133  coeffs[3] = a1;
1134  coeffs[4] = a0;
1135 
1136  //printf("coeffs = %f %f %f %f\n", coeffs[0], coeffs[1], coeffs[2], coeffs[3]);
1137  int degrees = 4;
1138  double zero_real[5];
1139  double zero_imag[5];
1140 
1141  memset(zero_real, 0, sizeof(double)*5);
1142  memset(zero_imag, 0, sizeof(double)*5);
1143 
1144  rpoly_ak1(coeffs, &degrees, zero_real, zero_imag);
1145 
1146 /*
1147  gsl_poly_complex_workspace *w = gsl_poly_complex_workspace_alloc(5);
1148  gsl_poly_complex_solve (coeffs, 5, w, z);
1149  gsl_poly_complex_workspace_free (w);
1150 */
1151  // get all valid solutions -> which are real zero
1152 
1153  at.clear();
1154 
1155  // Nghia - modified a bit here, if it fails use the original
1156  for(int i=0; i < 5; i++) {
1157  double _at = zero_real[i];
1158 
1159  double p1 = pow(1.0 + _at*_at, 3.0);
1160 
1161  if(fabs(p1) > 0.1 && zero_imag[i] == 0) {
1162  at.push_back(_at);
1163  }
1164  }
1165 
1166 /*
1167  // check for valid solutions
1168  for(int i=0; i < 8; i+=2) {
1169  double _at = z[i];
1170 
1171  double p1 = pow(1.0 + _at*_at, 3.0);
1172 
1173  if(fabs(p1) > 0.1 && z[i+1] == 0)
1174  at.push_back(_at);
1175  }
1176 */
1177  //printf("at size: %d\n", at.size());
1178 
1179  al.resize(at.size());
1180 
1181  vector <double> al2, at2;
1182 
1183  for(unsigned int i=0; i < at.size(); i++) {
1184  double sa = (2.f*at[i]) / (1.f +at[i]*at[i]);
1185  double ca = (1.f - at[i]*at[i]) / (1.f + at[i]*at[i]);
1186 
1187  al[i] = atan2(sa,ca) * 180/M_PI;
1188 
1189  double tMaxMin = (4*a4*at[i]*at[i]*at[i] + 3*a3*at[i]*at[i] + 2*a2*at[i] + a1);
1190 
1191  if(tMaxMin > 0) {
1192  al2.push_back(al[i]);
1193  at2.push_back(at[i]);
1194  }
1195  }
1196 
1197  al = al2;
1198  at = at2;
1199 
1200  tnew = Mat(3,al.size(),CV_64F);
1201 
1202  for(unsigned int a=0; a < al.size(); a++) {
1203  Mat R = Rz*RpyMat(Vec3d(0, (al[a]*M_PI/180), 0));
1204  Mat t_opt = Mat::zeros(3,1,CV_64F);
1205 
1206  Mat pcol(3,1,CV_64F);
1207 
1208  for(int i=0; i < v.cols; i++) {
1209  pcol.at<double>(0,0) = p.at<double>(0,i);
1210  pcol.at<double>(1,0) = p.at<double>(1,i);
1211  pcol.at<double>(2,0) = p.at<double>(2,i);
1212 
1213  t_opt = t_opt + (V[i] - _eye)*R*pcol;
1214  }
1215 
1216  t_opt = G*t_opt;
1217 
1218  tnew.at<double>(0,a) = t_opt.at<double>(0,0);
1219  tnew.at<double>(1,a) = t_opt.at<double>(1,0);
1220  tnew.at<double>(2,a) = t_opt.at<double>(2,0);
1221  }
1222 }
1223 
1224 void Print(const Mat &m)
1225 {
1226  for(int i=0; i < m.rows; i++) {
1227  for(int j=0; j < m.cols; j++) {
1228  printf("%4.6f ", m.at<double>(i,j));
1229  }
1230  printf("\n");
1231  }
1232 
1233  printf("\n");
1234 }
1235 
1236 void Print(const Quaternion &q)
1237 {
1238  printf("vector = %f %f %f\n", q.vector[0], q.vector[1], q.vector[2]);
1239  printf("scalar = %f\n", q.scalar);
1240  printf("\n");
1241 }
1242 
1243 }
d
bool Rpp(const Mat &model_3D, const Mat &iprts, Mat &Rlu, Mat &tlu, int &it1, double &obj_err1, double &img_err1, vector< Solution > &sol)
Definition: RPP.cpp:13
void ObjPose(const Mat _P, Mat Qp, Mat initR, Mat &R, Mat &t, int &it, double &obj_err, double &img_err)
Definition: RPP.cpp:66
f
Mat GetRotationbyVector(const Vec3d &v1, const Vec3d &v2)
Definition: RPP.cpp:425
bool RpyAng(const Mat &R, Vec3d &ret)
Definition: RPP.cpp:592
Definition: RPP.h:46
double Quaternion_Norm(const Quaternion &Q)
Definition: RPP.h:157
Mat Point2Mat(const vector< Point2d > &pts)
Definition: RPP.cpp:538
TFSIMD_FORCE_INLINE const tfScalar & y() const
void AbsKernel(Mat P, Mat Q, const vector< Mat > &F, const Mat &G, Mat &R, Mat &t, Mat &Qout, double &err2)
Definition: RPP.cpp:229
bool Get2ndPose_Exact(const Mat &v, const Mat &P, const Mat &R, const Mat &t, vector< Solution > &ret)
Definition: RPP.cpp:693
Mat Mean(const Mat &m)
Definition: RPP.cpp:508
void GetRotationY_wrtT(const Mat &v, const Mat &p, const Mat &t, const Mat &Rz, vector< double > &al, Mat &tnew, vector< double > &at)
Definition: RPP.cpp:947
Quaternion Quaternion_byAngleAndVector(double q_angle, const Vec3d &q_vector)
Definition: RPP.cpp:367
bool GetRfor2ndPose_V_Exact(const Mat &v, const Mat &P, const Mat &R, const Mat &t, vector< Solution > &ret)
Definition: RPP.cpp:847
int sign(double x)
Definition: RPP.h:162
Mat NormRv(const Vec3d &V)
Definition: RPP.cpp:354
Mat Vec2Mat(const Vec3d &v)
Definition: RPP.cpp:551
void rpoly_ak1(double op[MDP1], int *Degree, double zeror[MAXDEGREE], double zeroi[MAXDEGREE])
Definition: Rpoly.cpp:11
static double EPSILON
Definition: RPP.cpp:8
bool DecomposeR(const Mat &R, Mat &Rz2, Mat &ret)
Definition: RPP.cpp:755
bool RpyAng_X(const Mat &R, Vec3d &ret)
Definition: RPP.cpp:659
TFSIMD_FORCE_INLINE const tfScalar & x() const
static double TOL
Definition: RPP.cpp:7
TFSIMD_FORCE_INLINE const tfScalar & z() const
Mat Mul(const Mat &a, const Mat &b)
Definition: RPP.cpp:493
Mat RpyMat(const Vec3d &angs)
Definition: RPP.cpp:563
cv::Mat quat2mat(const Quaternion &Q)
Definition: RPP.cpp:401
Mat Sq(const Mat &m)
Definition: RPP.cpp:810
double Norm(const Mat &m)
Definition: RPP.cpp:840
cv::Vec3d vector
Definition: RPP.h:53
Mat Xform(const Mat &P, const Mat &R, const Mat &t)
Definition: RPP.cpp:823
Mat EstimateT(const Mat &R, const Mat &G, const vector< Mat > &F, const Mat &P)
Definition: RPP.cpp:210
Mat Sum(const Mat &m, int dim)
Definition: RPP.cpp:458
void Print(const Mat &m)
Definition: RPP.cpp:1224
double scalar
Definition: RPP.h:54
Quaternion Quaternion_byVectorAndScalar(const cv::Vec3d &vector, double scalar)
Definition: RPP.h:139
Quaternion Quaternion_multiplyByScalar(const Quaternion &q, double scalar)
Definition: RPP.h:144


fiducial_pose
Author(s): Jim Vaughan
autogenerated on Thu Dec 28 2017 04:06:58