RPP.cpp
Go to the documentation of this file.
00001 #include "RPP.h"
00002 #include <cstdio>
00003 
00004 using namespace std;
00005 using namespace cv;
00006 
00007 static double TOL = 1E-5;
00008 static double EPSILON = 1E-8;
00009 
00010 namespace RPP
00011 {
00012 
00013 bool Rpp(const Mat &model_3D, const Mat &iprts,
00014          Mat &Rlu, Mat &tlu, int &it1, double &obj_err1, double &img_err1, vector<Solution> &sol)
00015 {
00016     // get a first guess of the pose.
00017     if(Rlu.data) {
00018         ObjPose(model_3D, iprts, Rlu, Rlu, tlu, it1, obj_err1, img_err1);
00019     }
00020     else {
00021         ObjPose(model_3D, iprts, cv::Mat(), Rlu, tlu, it1, obj_err1, img_err1);
00022     }
00023 
00024     // get 2nd Pose
00025     // vector <Solution> sol;
00026     bool status = Get2ndPose_Exact(iprts, model_3D, Rlu, tlu, sol);
00027 
00028     if(!status) {
00029         return false;
00030     }
00031 
00032     //refine with lu
00033     int bestIdx=-1;
00034     double lowestErr = 1e6;
00035 
00036     for(unsigned int i=0; i < sol.size(); i++) {
00037         ObjPose(model_3D, iprts, sol[i].R, Rlu, sol[i].t, it1, obj_err1, img_err1);
00038 
00039         sol[i].R = Rlu;
00040         sol[i].obj_err = obj_err1;
00041         sol[i].img_err = img_err1;
00042 
00043         if(img_err1 < lowestErr) {
00044             lowestErr = img_err1;
00045             bestIdx = i;
00046         }
00047     }
00048 
00049     Rlu = sol[bestIdx].R;
00050     tlu = sol[bestIdx].t;
00051     obj_err1 = sol[bestIdx].obj_err;
00052     img_err1 = sol[bestIdx].img_err;
00053 
00054 
00055 //    printf("Best solution: %d\n", bestIdx);
00056 
00057  //   printf("Final R\n");
00058     //Print(Rlu);
00059 
00060     //printf("Final t\n");
00061     //Print(tlu);
00062 
00063     return true;
00064 }
00065 
00066 void ObjPose(const Mat _P, Mat Qp, Mat initR,
00067              Mat &R, Mat &t, int &it, double &obj_err, double &img_err)
00068 {
00069     Mat P = _P.clone(); // make a copy, else _P will get modified, nasty GOTCHA!
00070 
00071     int n = P.cols;
00072     it = 0;
00073 
00074     Mat pbar = Sum(P,2) / n;
00075 
00076     // move the origin to the center of P
00077     for(int i=0; i < n; i++) {
00078         P.at<double>(0,i) -= pbar.at<double>(0,0);
00079         P.at<double>(1,i) -= pbar.at<double>(1,0);
00080         P.at<double>(2,i) -= pbar.at<double>(2,0);
00081     }
00082 
00083     // compute projection matrices
00084     vector <Mat> F(n);
00085     Mat V(3,1,CV_64F);
00086     Mat ret(1,1,CV_64F);
00087 
00088     for(int i=0; i < n; i++) {
00089         F[i].create(3,3,CV_64F);
00090 
00091         V.at<double>(0,0) = Qp.at<double>(0,i);
00092         V.at<double>(1,0) = Qp.at<double>(1,i);
00093         V.at<double>(2,0) = Qp.at<double>(2,i);
00094 
00095         ret = V.t()*V;
00096 
00097         F[i] = (V*V.t()) / ret.at<double>(0,0);
00098     }
00099 
00100     // compute the matrix factor required to compute t
00101     Mat sumF = Mat::zeros(3,3,CV_64F);
00102 
00103     for(int i=0; i < n; i++) {
00104         sumF += F[i];
00105     }
00106 
00107     Mat tFactor = (Mat::eye(3,3,CV_64F)-sumF/n).inv()/n;
00108 
00109     double old_err;
00110     Mat Qi;
00111     Mat Ri, ti;
00112 
00113     if(initR.data) {
00114         Ri = initR;
00115 
00116         Mat sum_ = Mat::zeros(3,1,CV_64F);
00117 
00118         Mat _eye = Mat::eye(3,3,CV_64F);
00119         Mat PP(3,1,CV_64F);
00120 
00121         for(int i=0; i < n; i++) {
00122             PP.at<double>(0,0) = P.at<double>(0,i);
00123             PP.at<double>(1,0) = P.at<double>(1,i);
00124             PP.at<double>(2,0) = P.at<double>(2,i);
00125 
00126             sum_ = sum_ + (F[i] - _eye)*Ri*PP;
00127         }
00128 
00129         ti = tFactor*sum_;
00130 
00131         // calculate error
00132         Qi = Xform(P, Ri, ti);
00133 
00134         old_err = 0;
00135 
00136         Mat vec(3,1,CV_64F);
00137         Mat QiCol(3,1,CV_64F);
00138 
00139         for(int i=0; i < n; i++) {
00140             QiCol.at<double>(0,0) = Qi.at<double>(0,i);
00141             QiCol.at<double>(1,0) = Qi.at<double>(1,i);
00142             QiCol.at<double>(2,0) = Qi.at<double>(2,i);
00143 
00144             vec = (_eye - F[i])*QiCol;
00145 
00146             double x = vec.at<double>(0,0);
00147             double y = vec.at<double>(1,0);
00148             double z = vec.at<double>(2,0);
00149 
00150             old_err += (x*x + y*y + z*z);
00151         }
00152     }
00153     else {
00154         // no initial guess; use weak-perspective approximation
00155         AbsKernel(P, Qp, F, tFactor, Ri, ti, Qi, old_err);
00156         it = 1;
00157 
00158         //printf("SVD\n");
00159         //Print(Ri);
00160     }
00161 
00162     // compute next pose estimate
00163     double new_err;
00164 
00165     AbsKernel(P, Qi, F, tFactor, Ri, ti, Qi, new_err);
00166 
00167     it = it + 1;
00168 
00169     //printf("before while\n");
00170 
00171     while(fabs((old_err-new_err)/old_err) > TOL && (new_err > EPSILON)) {
00172         old_err = new_err;
00173         // compute the optimal estimate of R
00174         AbsKernel(P, Qi, F, tFactor, Ri, ti, Qi, new_err);
00175 
00176         //printf("it %d\n", it);
00177         it = it + 1;
00178     }
00179 
00180     R = Ri;
00181     t = ti;
00182     obj_err = sqrt(new_err/n);
00183 
00184     // calculate image-space error
00185     Mat Pcol(3,1,CV_64F);
00186     Mat Qproj;
00187 
00188     img_err = 0;
00189 
00190     for(int i=0; i < n; i++) {
00191         Pcol.at<double>(0,0) = P.at<double>(0,i);
00192         Pcol.at<double>(1,0) = P.at<double>(1,i);
00193         Pcol.at<double>(2,0) = P.at<double>(2,i);
00194 
00195         Qproj = Ri*Pcol + ti;
00196 
00197         double xx = (Qproj.at<double>(0,0)/Qproj.at<double>(2,0)) - Qp.at<double>(0,0);
00198         double yy = (Qproj.at<double>(1,0)/Qproj.at<double>(2,0)) - Qp.at<double>(1,0);
00199 
00200         img_err += (xx*xx + yy*yy);
00201     }
00202 
00203     img_err = sqrt(img_err/n);
00204 
00205     // get back to original refernce frame
00206 
00207     t = t - Ri*pbar;
00208 }
00209 
00210 Mat EstimateT(const Mat &R, const Mat &G, const vector <Mat> &F, const Mat &P)
00211 {
00212     Mat sum = Mat::zeros(3,1,CV_64F);
00213 
00214     Mat PP(3,1,CV_64F);
00215 
00216     for(int i=0; i < P.cols; i++) {
00217         PP.at<double>(0,0) = P.at<double>(0,i);
00218         PP.at<double>(1,0) = P.at<double>(1,i);
00219         PP.at<double>(2,0) = P.at<double>(2,i);
00220 
00221         sum += F[i]*R*PP;
00222     }
00223 
00224     Mat ret = G*sum;
00225 
00226     return ret;
00227 }
00228 
00229 void AbsKernel(Mat P, Mat Q, const vector <Mat> &F, const Mat &G,
00230                Mat &R, Mat &t, Mat &Qout, double &err2)
00231 {
00232     int n = P.cols;
00233 
00234     Mat QQ(3,1,CV_64F);
00235 
00236     for(int i=0; i < n; i++) {
00237         QQ.at<double>(0,0) = Q.at<double>(0,i);
00238         QQ.at<double>(1,0) = Q.at<double>(1,i);
00239         QQ.at<double>(2,0) = Q.at<double>(2,i);
00240 
00241         QQ= F[i]*QQ;
00242 
00243         Q.at<double>(0,i) = QQ.at<double>(0,0);
00244         Q.at<double>(1,i) = QQ.at<double>(1,0);
00245         Q.at<double>(2,i) = QQ.at<double>(2,0);
00246     }
00247 
00248     Mat pbar = Sum(P,2)/n;
00249     Mat qbar = Sum(Q,2)/n;
00250 
00251     // compute P' and Q'
00252     for(int i=0; i < n; i++) {
00253         P.at<double>(0,i) -= pbar.at<double>(0,0);
00254         P.at<double>(1,i) -= pbar.at<double>(1,0);
00255         P.at<double>(2,i) -= pbar.at<double>(2,0);
00256     }
00257 
00258     // use SVD solution
00259     // compute M matrix
00260     Mat M = Mat::zeros(3,3,CV_64F);
00261     Mat PP(3,1,CV_64F);
00262 
00263     for(int i=0; i < n; i++) {
00264         PP.at<double>(0,0) = P.at<double>(0,i);
00265         PP.at<double>(1,0) = P.at<double>(1,i);
00266         PP.at<double>(2,0) = P.at<double>(2,i);
00267 
00268         QQ.at<double>(0,0) = Q.at<double>(0,i);
00269         QQ.at<double>(1,0) = Q.at<double>(1,i);
00270         QQ.at<double>(2,0) = Q.at<double>(2,i);
00271 
00272         M += PP*QQ.t();
00273     }
00274 
00275     SVD decomp(M);
00276 
00277     R = decomp.vt.t()*(decomp.u.t());
00278     Mat v = decomp.vt.t();
00279 
00280     if(sign(determinant(R)) == 1) {
00281         t = EstimateT(R,G,F,P);
00282 
00283         if(t.at<double>(2,0) < 0) {
00284             // we need to invert the t
00285             // negate the 3rd column
00286 
00287             v.at<double>(0,2) = -v.at<double>(0,2);
00288             v.at<double>(1,2) = -v.at<double>(1,2);
00289             v.at<double>(2,2) = -v.at<double>(2,2);
00290 
00291             // we need to invert the t
00292             R = -v*decomp.u.t();
00293             t = EstimateT(R,G,F,P);
00294         }
00295     }
00296     else {
00297         // negate the 3rd column
00298         v.at<double>(0,2) = -v.at<double>(0,2);
00299         v.at<double>(1,2) = -v.at<double>(1,2);
00300         v.at<double>(2,2) = -v.at<double>(2,2);
00301 
00302         R = v*decomp.u.t();
00303         t = EstimateT(R,G,F,P);
00304 
00305         if(t.at<double>(2,0) < 0) {
00306             R = -v*(decomp.u.t());
00307             t = EstimateT(R,G,F,P);
00308         }
00309     }
00310 
00311 
00312     // calculate error
00313     Mat _eye = Mat::eye(3,3,CV_64F);
00314     Mat vec(3,1,CV_64F);
00315 
00316     err2 = 0;
00317     Qout = Xform(P, R, t);
00318 
00319     for(int i=0; i < n; i++) {
00320         QQ.at<double>(0,0) = Qout.at<double>(0,i);
00321         QQ.at<double>(1,0) = Qout.at<double>(1,i);
00322         QQ.at<double>(2,0) = Qout.at<double>(2,i);
00323 
00324         vec = (_eye - F[i])*QQ;
00325 
00326         double x = vec.at<double>(0,0);
00327         double y = vec.at<double>(1,0);
00328         double z = vec.at<double>(2,0);
00329 
00330         err2 += (x*x + y*y + z*z);
00331     }
00332 }
00333 
00334 Mat NormRv(const Mat &R)
00335 {
00336     Mat ret(R.rows, R.cols, CV_64F);
00337 
00338     for(int i=0; i < R.cols; i++) {
00339 
00340         double mag = R.at<double>(0,i)*R.at<double>(0,i) +
00341                     R.at<double>(1,i)*R.at<double>(1,i) +
00342                     R.at<double>(2,i)*R.at<double>(2,i);
00343 
00344         double m = 1.f/sqrt(mag);
00345 
00346         ret.at<double>(0,i) = R.at<double>(0,i)*m;
00347         ret.at<double>(1,i) = R.at<double>(1,i)*m;
00348         ret.at<double>(2,i) = R.at<double>(2,i)*m;
00349     }
00350 
00351     return ret;
00352 }
00353 
00354 Mat NormRv(const Vec3d &V)
00355 {
00356     Mat ret(3,1,CV_64F);
00357 
00358     double mag = sqrt(V[0]*V[0] + V[1]*V[1] + V[2]*V[2]);
00359 
00360     ret.at<double>(0,0) = V[0] / mag;
00361     ret.at<double>(1,0) = V[1] / mag;
00362     ret.at<double>(2,0) = V[2] / mag;
00363 
00364     return ret;
00365 }
00366 
00367 Quaternion Quaternion_byAngleAndVector(double q_angle, const Vec3d &q_vector)
00368 {
00369     //printf("Quaternion_byAngleAndVector\n");
00370 
00371     // rotation_axis=q_vector/norm(q_vector);
00372     // matlab norm with default argument of 2 is largest singular value
00373     double n = Norm(Vec2Mat(q_vector));
00374 
00375     //printf("n = %f\n", n);
00376 
00377     Vec3d rotation_axis = q_vector;
00378 
00379     rotation_axis[0] /= n;
00380     rotation_axis[1] /= n;
00381     rotation_axis[2] /= n;
00382 
00383     rotation_axis[0] *= sin(q_angle*0.5);
00384     rotation_axis[1] *= sin(q_angle*0.5);
00385     rotation_axis[2] *= sin(q_angle*0.5);
00386 
00387     Quaternion Q_ = Quaternion_byVectorAndScalar(rotation_axis, cos(q_angle*0.5));
00388 
00389     //printf("Q_\n");
00390     //Print(Q_);
00391 
00392 //    double a = 1/Quaternion_Norm(Q_);
00393 
00394     //printf("a = %f\n", a);
00395 
00396     Quaternion Q = Quaternion_multiplyByScalar(Q_, 1/Quaternion_Norm(Q_));
00397 
00398     return Q;
00399 }
00400 
00401 Mat quat2mat(const Quaternion &Q)
00402 {
00403     double a = Q.scalar;
00404     double b = Q.vector[0];
00405     double c = Q.vector[1];
00406     double d = Q.vector[2];
00407 
00408     Mat R(3,3,CV_64F);
00409 
00410     R.at<double>(0,0) = a*a + b*b - c*c -d*d;
00411     R.at<double>(0,1) = 2*(b*c - a*d);
00412     R.at<double>(0,2) = 2*(b*d + a*c);
00413 
00414     R.at<double>(1,0) = 2*(b*c + a*d);
00415     R.at<double>(1,1) = a*a + c*c - b*b - d*d;
00416     R.at<double>(1,2) = 2*(c*d - a*b);
00417 
00418     R.at<double>(2,0) = 2*(b*d - a*c);
00419     R.at<double>(2,1) = 2*(c*d + a*b);
00420     R.at<double>(2,2) = a*a + d*d - b*b -c*c;
00421 
00422     return R;
00423 }
00424 
00425 Mat GetRotationbyVector(const Vec3d &v1, const Vec3d &v2)
00426 {
00427     //printf("GetRotationbyVector\n");
00428 
00429     double winkel = acos(v2.dot(v1));
00430 
00431     //printf("winkel = %f\n", winkel);
00432 
00433     Quaternion QU = Quaternion_byAngleAndVector(winkel,v2.cross(v1));
00434 
00435     //printf("QU\n");
00436     //Print(QU);
00437 
00438     Mat R = quat2mat(QU);
00439 
00440     //printf("R\n");
00441     //Print(R);
00442 
00443     Mat a = Sum(Sq(NormRv(v1) - R*NormRv(v2)));
00444 
00445     //printf("a\n");
00446     //Print(a);
00447 
00448     double mag = a.at<double>(0,0)*a.at<double>(0,0);
00449 
00450     if(mag > 1e-3) {
00451         fprintf(stderr, "Error in GetRotationbyVector()\n");
00452         exit(1);
00453     }
00454 
00455     return R;
00456 }
00457 
00458 Mat Sum(const Mat &m, int dim)
00459 {
00460     // columns
00461     if(dim == 1) {
00462         Mat ret(1, m.cols, CV_64F);
00463 
00464         for(int j=0; j < m.cols; j++) {
00465             double sum = 0;
00466 
00467             for(int i=0; i < m.rows; i++) {
00468                 sum += m.at<double>(i,j);
00469             }
00470 
00471             ret.at<double>(0,j) = sum;
00472         }
00473 
00474         return ret;
00475     }
00476     else {
00477         Mat ret(m.rows, 1, CV_64F);
00478 
00479         for(int i=0; i < m.rows; i++) {
00480             double sum = 0;
00481 
00482             for(int j=0; j < m.cols; j++) {
00483                 sum += m.at<double>(i,j);
00484             }
00485 
00486             ret.at<double>(i,0) = sum;
00487         }
00488 
00489         return ret;
00490     }
00491 }
00492 
00493 Mat Mul(const Mat &a, const Mat &b)
00494 {
00495     assert(a.rows == b.rows && a.cols == b.cols);
00496 
00497     Mat ret(a.rows, a.cols, CV_64F);
00498 
00499     for(int i=0; i < a.rows; i++) {
00500         for(int j=0; j < a.cols; j++) {
00501             ret.at<double>(i,j) = a.at<double>(i,j)*b.at<double>(i,j);
00502         }
00503     }
00504 
00505     return ret;
00506 }
00507 
00508 Mat Mean(const Mat &m)
00509 {
00510     Mat ret(1, m.cols, CV_64F);
00511 
00512     for(int j=0; j < m.cols; j++) {
00513         double sum = 0;
00514 
00515         for(int i=0; i < m.rows; i++) {
00516             sum += m.at<double>(i,j);
00517         }
00518 
00519         ret.at<double>(0,j) = sum / m.cols;
00520     }
00521 
00522     return ret;
00523 }
00524 
00525 Mat Point2Mat(const vector <Point3d> &pts)
00526 {
00527     Mat ret(3, pts.size(), CV_64F);
00528 
00529     for(unsigned int i=0; i < pts.size(); i++) {
00530         ret.at<double>(0,i) = pts[i].x;
00531         ret.at<double>(1,i) = pts[i].y;
00532         ret.at<double>(2,i) = pts[i].z;
00533     }
00534 
00535     return ret;
00536 }
00537 
00538 Mat Point2Mat(const vector <Point2d> &pts)
00539 {
00540     Mat ret(3, pts.size(), CV_64F);
00541 
00542     for(unsigned int i=0; i < pts.size(); i++) {
00543         ret.at<double>(0,i) = pts[i].x;
00544         ret.at<double>(1,i) = pts[i].y;
00545         ret.at<double>(2,i) = 1.f;
00546     }
00547 
00548     return ret;
00549 }
00550 
00551 Mat Vec2Mat(const Vec3d &v)
00552 {
00553     Mat ret(3,1,CV_64F);
00554 
00555     ret.at<double>(0,0) = v[0];
00556     ret.at<double>(1,0) = v[1];
00557     ret.at<double>(2,0) = v[2];
00558 
00559     return ret;
00560 }
00561 
00562 
00563 Mat RpyMat(const Vec3d &angs)
00564 {
00565     double cosA = cos(angs[2]);
00566     double sinA = sin(angs[2]);
00567     double cosB = cos(angs[1]);
00568     double sinB = sin(angs[1]);
00569     double cosC = cos(angs[0]);
00570     double sinC = sin(angs[0]);
00571 
00572     double cosAsinB = cosA*sinB;
00573     double sinAsinB = sinA*sinB;
00574 
00575     Mat R(3,3,CV_64F);
00576 
00577     R.at<double>(0,0) = cosA*cosB;
00578     R.at<double>(0,1) = cosAsinB*sinC-sinA*cosC;
00579     R.at<double>(0,2) = cosAsinB*cosC+sinA*sinC;
00580 
00581     R.at<double>(1,0) = sinA*cosB;
00582     R.at<double>(1,1) = sinAsinB*sinC+cosA*cosC;
00583     R.at<double>(1,2) = sinAsinB*cosC-cosA*sinC;
00584 
00585     R.at<double>(2,0) = -sinB;
00586     R.at<double>(2,1) = cosB*sinC;
00587     R.at<double>(2,2) = cosB*cosC;
00588 
00589     return R;
00590 }
00591 
00592 bool RpyAng(const Mat &R, Vec3d &ret)
00593 {
00594     //printf("\nRpyAng\n");
00595 
00596     Vec3d angs;
00597 
00598     double R11 = R.at<double>(0,0);
00599     double R12 = R.at<double>(0,1);
00600     double R13 = R.at<double>(0,2);
00601 
00602     double R21 = R.at<double>(1,0);
00603     double R22 = R.at<double>(1,1);
00604     double R23 = R.at<double>(1,2);
00605 
00606     double R31 = R.at<double>(2,0);
00607     double R32 = R.at<double>(2,1);
00608     double R33 = R.at<double>(2,2);
00609 
00610     double sinB = -R31;
00611     double cosB = sqrt(R11*R11 + R21*R21);
00612 
00613     if(fabs (cosB) > 1e-15) {
00614         double sinA = R21 / cosB;
00615         double cosA = R11 / cosB;
00616         double sinC = R32 / cosB;
00617         double cosC = R33 / cosB;
00618         angs[0] = atan2(sinC,cosC);
00619         angs[1] = atan2(sinB,cosB);
00620         angs[2] = atan2(sinA,cosA);
00621     }
00622     else {
00623         double sinC = (R12 - R23) / 2;
00624         double cosC = (R22 + R13) / 2;
00625         angs[0] = atan2(sinC,cosC);
00626         angs[1] = M_PI_2;
00627         angs[2] = 0;
00628 
00629         if(sinB < 0)
00630             angs = -angs;
00631     }
00632 
00633     //printf("R\n");
00634     //Print(R);
00635 
00636     //printf("angs\n");
00637     //Print(Vec2Mat(angs));
00638 
00639     //printf("angs: %f %f %f\n", angs[0], angs[1], angs[2]);
00640 
00641     Mat a = R-RpyMat(angs);
00642 
00643     //printf("a\n");
00644     //Print(a);
00645 
00646     //double a = Norm(R-RpyMat(angs));
00647     //printf("a = %f\n", a);
00648 
00649     if(Norm(R-RpyMat(angs)) > 1e-6) {
00650         fprintf(stderr, "rpyMat: Error not correct Solution\n");
00651         return false;
00652     }
00653 
00654     ret = angs;
00655 
00656     return true;
00657 }
00658 
00659 bool RpyAng_X(const Mat &R, Vec3d &ret)
00660 {
00661     Vec3d ang_zyx;
00662     bool status = RpyAng(R, ang_zyx);
00663 
00664     if(!status) {
00665         return false;
00666     }
00667 
00668     if(fabs(ang_zyx[0]) > M_PI_2) {
00669          // test the same R
00670         while ( fabs(ang_zyx[0]) > M_PI_2 ) {
00671             if(ang_zyx[0] > 0) {
00672                 ang_zyx[0] = ang_zyx[0]+M_PI;
00673                 ang_zyx[1] = 3*M_PI-ang_zyx[1];
00674                 ang_zyx[2] = ang_zyx[2]+M_PI;
00675 
00676                 ang_zyx[0] -= 2*M_PI;
00677                 ang_zyx[1] -= 2*M_PI;
00678                 ang_zyx[2] -= 2*M_PI;
00679             }
00680             else {
00681               ang_zyx[0] = ang_zyx[0]+M_PI;
00682               ang_zyx[1] = 3*M_PI-ang_zyx[1];
00683               ang_zyx[2] = ang_zyx[2]+M_PI;
00684             }
00685         }
00686     }
00687 
00688     ret = ang_zyx;
00689 
00690     return true;
00691 }
00692 
00693 bool Get2ndPose_Exact(const Mat &v, const Mat &P, const Mat &R, const Mat &t, vector<Solution> &ret)
00694 {
00695     //printf("Get2ndPose_Exact\n");
00696 
00697     Mat cent = NormRv(Mean(NormRv(v).t()).t());
00698     Vec3d _cent;
00699 
00700     _cent[0] = cent.at<double>(0,0);
00701     _cent[1] = cent.at<double>(1,0);
00702     _cent[2] = cent.at<double>(2,0);
00703 
00704     Mat Rim = GetRotationbyVector(Vec3d(0,0,1), _cent);
00705 
00706     Mat v_ = Rim*v;
00707     cent = NormRv(Mean(NormRv(v_).t()).t());
00708 
00709     Mat R_ = Rim*R;
00710     Mat t_ = Rim*t;
00711 /*
00712     printf("cent\n");
00713     Print(cent);
00714 
00715     printf("Rim\n");
00716     Print(Rim);
00717 
00718     printf("R\n");
00719     Print(R);
00720 
00721     printf("t\n");
00722     Print(t);
00723 
00724     printf("R_\n");
00725     Print(R_);
00726 
00727     printf("t_\n");
00728     Print(t_);
00729 */
00730     vector<Solution> sol;
00731 
00732     bool status = GetRfor2ndPose_V_Exact(v_,P,R_,t_, sol);
00733 
00734     if(!status) {
00735         return false;
00736     }
00737 
00738     // de Normalise the Pose
00739     for(unsigned int i=0; i < sol.size(); i++) {
00740         //printf("BEFORE\n");
00741         //Print(sol[i].R);
00742 
00743         sol[i].R = Rim.t()*sol[i].R;
00744 
00745         //printf("AFTER\n");
00746         //Print(sol[i].R);
00747         sol[i].t = Rim.t()*sol[i].t;
00748     }
00749 
00750     ret = sol;
00751 
00752     return true;
00753 }
00754 
00755 bool DecomposeR(const Mat &R, Mat &Rz2, Mat &ret)
00756 {
00757     //printf("\nDecomposeR\n");
00758 
00759     double cl = atan2(R.at<double>(2,1), R.at<double>(2,0));
00760     Mat Rz = RpyMat(Vec3d(0,0,cl));
00761 /*
00762     printf("cl = %f\n", cl);
00763     printf("Rz\n");
00764     Print(Rz);
00765     printf("R\n");
00766     Print(R);
00767 */
00768     Mat R_ = R*Rz;
00769 
00770     //printf("R_\n");
00771     //Print(R_);
00772 
00773     if(R_.at<double>(2,1) > 1e-3) {
00774         fprintf(stderr, "error in DecomposeR 1\n");
00775         return false;
00776     }
00777 
00778     Vec3d ang_zyx;
00779     bool status = RpyAng_X(R_, ang_zyx);
00780 
00781     if(!status) {
00782         return false;
00783     }
00784 
00785     if(fabs(ang_zyx[0]) > 1e-3) {
00786         fprintf(stderr, "error in DecomposeR 2\n");
00787         return false;
00788     }
00789 
00790     Rz2 = Rz*RpyMat(Vec3d(0,0,M_PI));
00791     R_ = R*Rz2;
00792 
00793     if(R_.at<double>(2,1) > 1e-3) {
00794         fprintf(stderr, "error in DecomposeR 3\n");
00795         return false;
00796     }
00797 
00798     // why do we do this?
00799     status = RpyAng_X(R_, ang_zyx);
00800 
00801     if(!status) {
00802         return false;
00803     }
00804 
00805     ret = Rz;
00806 
00807     return true;
00808 }
00809 
00810 Mat Sq(const Mat &m)
00811 {
00812     Mat ret(m.rows, m.cols, CV_64F);
00813 
00814     for(int i=0; i < m.rows; i++) {
00815         for(int j=0; j < m.cols; j++) {
00816             ret.at<double>(i,j) = m.at<double>(i,j)*m.at<double>(i,j);
00817         }
00818     }
00819 
00820     return ret;
00821 }
00822 
00823 Mat Xform(const Mat &P, const Mat &R, const Mat &t)
00824 {
00825     Mat ret(3,P.cols,CV_64F);
00826 
00827     for(int i=0; i < P.cols; i++) {
00828         double x = P.at<double>(0,i);
00829         double y = P.at<double>(1,i);
00830         double z = P.at<double>(2,i);
00831 
00832         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);
00833         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);
00834         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);
00835     }
00836 
00837     return ret;
00838 }
00839 
00840 double Norm(const Mat &m)
00841 {
00842     SVD decomp(m);
00843 
00844     return decomp.w.at<double>(0,0);
00845 }
00846 
00847 bool GetRfor2ndPose_V_Exact(const Mat &v, const Mat &P, const Mat &R, const Mat &t, vector<Solution> &ret)
00848 {
00849     //printf("\nGetRfor2ndPose_V_Exact\n");
00850     //printf("R\n");
00851     //Print(R);
00852 
00853     Mat Rz2;
00854     Mat RzN;
00855 
00856     bool status = DecomposeR(R, Rz2, RzN);
00857 
00858     if(!status) {
00859         return false;
00860     }
00861 
00862     Mat R_ = R*RzN;
00863 
00864     Mat P_ = RzN.t()*P;
00865 
00866     Vec3d ang_zyx;
00867 
00868     status = RpyAng_X(R_, ang_zyx);
00869 
00870     if(!status) {
00871         return false;
00872     }
00873 
00874     Mat Ry = RpyMat(Vec3d(0,ang_zyx[1],0));
00875     Mat Rz = RpyMat(Vec3d(0,0,ang_zyx[2]));
00876 
00877     vector <double> bl;
00878     Mat Tnew;
00879     vector <double> at;
00880 
00881     GetRotationY_wrtT(v ,P_,t,Rz, bl, Tnew, at);
00882 
00883     // Suggestion by csantos
00884     if(bl.empty()) {
00885         return false;
00886     }
00887 
00888     for(unsigned int i=0; i < bl.size(); i++) {
00889         bl[i] = bl[i]/180*M_PI;
00890     }
00891 
00892     // we got 2 solutions. YEAH
00893     vector <Mat> V(v.cols);
00894 
00895     Mat tmp(3,1,CV_64F);
00896 
00897     for(int i=0; i < v.cols; i++) {
00898         tmp.at<double>(0,0) = v.at<double>(0,i);
00899         tmp.at<double>(1,0) = v.at<double>(1,i);
00900         tmp.at<double>(2,0) = v.at<double>(2,i);
00901 
00902         Mat a = tmp.t()*tmp;
00903 
00904         V[i] = tmp*tmp.t() / a.at<double>(0,0);
00905     }
00906 
00907     vector <Solution> sol(bl.size());
00908 
00909     for(unsigned int j=0; j < bl.size(); j++) {
00910         sol[j].bl = bl[j];
00911         sol[j].at = at[j];
00912 
00913         Ry = RpyMat(Vec3d(0,bl[j],0));
00914         sol[j].R = Rz*Ry*RzN.t();
00915 
00916         //printf("sol[j].R\n");
00917         //Print(sol[j].R);
00918 
00919 
00920         sol[j].t.at<double>(0,0) = Tnew.at<double>(0,j);
00921         sol[j].t.at<double>(1,0) = Tnew.at<double>(1,j);
00922         sol[j].t.at<double>(2,0) = Tnew.at<double>(2,j);
00923 
00924         // test the Error
00925         double E=0;
00926         Mat _eye = Mat::eye(3,3,CV_64F);
00927         Mat Pcol(3,1,CV_64F);
00928 
00929         for(int i=0; i < v.cols; i++) {
00930             Pcol.at<double>(0,0) = P.at<double>(0,i);
00931             Pcol.at<double>(1,0) = P.at<double>(1,i);
00932             Pcol.at<double>(2,0) = P.at<double>(2,i);
00933 
00934             Mat a = Sum(Sq((_eye - V[i])*(sol[j].R*Pcol + sol[j].t)));
00935 
00936             E = E + a.at<double>(0,0);
00937         }
00938 
00939         sol[j].E = E;
00940     }
00941 
00942     ret = sol;
00943 
00944     return true;
00945 }
00946 
00947 void GetRotationY_wrtT(const Mat &v, const Mat &p, const Mat &t, const Mat &Rz,
00948                         vector <double> &al, Mat &tnew, vector <double> &at)
00949 {
00950 
00951 /*
00952 if nargin == 4,
00953  Rz = eye(3);
00954 end
00955 */
00956 
00957     vector <Mat> V(v.cols);
00958     Mat vv(3,1,CV_64F);
00959 
00960     for(int i=0; i < v.cols; i++) {
00961         vv.at<double>(0,0) = v.at<double>(0,i);
00962         vv.at<double>(1,0) = v.at<double>(1,i);
00963         vv.at<double>(2,0) = v.at<double>(2,i);
00964 
00965         Mat tmp = vv.t()*vv;
00966         double a = tmp.at<double>(0,0);
00967         V[i] = (vv*vv.t()) / a;
00968     }
00969 
00970     //generate G
00971     Mat G = Mat::zeros(3,3,CV_64F);
00972 
00973     for(int i=0; i < v.cols; i++) {
00974        G += V[i];
00975     }
00976 
00977     Mat _eye = Mat::eye(3,3,CV_64F);
00978 
00979     G = (_eye - G/v.cols).inv()/v.cols;
00980 
00981     //printf("G\n");
00982     //Print(G);
00983 
00984     // generate opt_t*[bt^2 bt 1]
00985 
00986     Mat opt_t = Mat::zeros(3,3,CV_64F);
00987 
00988     for(int i=0; i < v.cols; i++) {
00989         double v11 = V[i].at<double>(0,0);
00990         double v12 = V[i].at<double>(0,1);
00991         double v13 = V[i].at<double>(0,2);
00992         double v21 = V[i].at<double>(1,0);
00993         double v22 = V[i].at<double>(1,1);
00994         double v23 = V[i].at<double>(1,2);
00995         double v31 = V[i].at<double>(2,0);
00996         double v32 = V[i].at<double>(2,1);
00997         double v33 = V[i].at<double>(2,2);
00998 
00999         double px = p.at<double>(0,i);
01000         double py = p.at<double>(1,i);
01001         double pz = p.at<double>(2,i);
01002 
01003         double r1 = Rz.at<double>(0,0);
01004         double r2 = Rz.at<double>(0,1);
01005         double r3 = Rz.at<double>(0,2);
01006 
01007         double r4 = Rz.at<double>(1,0);
01008         double r5 = Rz.at<double>(1,1);
01009         double r6 = Rz.at<double>(1,2);
01010 
01011         double r7 = Rz.at<double>(2,0);
01012         double r8 = Rz.at<double>(2,1);
01013         double r9 = Rz.at<double>(2,2);
01014 
01015         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);
01016         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);
01017         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;
01018 
01019         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);
01020         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);
01021         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;
01022 
01023         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);
01024         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);
01025         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;
01026     }
01027 
01028     opt_t = G*opt_t;
01029 
01030     Mat E_2 = Mat::zeros(1,5,CV_64F);
01031 
01032 
01033     // estimate Error function E
01034     for(int i=0; i < v.cols; i++) {
01035         double px = p.at<double>(0,i);
01036         double py = p.at<double>(1,i);
01037         double pz = p.at<double>(2,i);
01038 
01039         Mat Rpi(3,3,CV_64F);
01040 
01041         Rpi.at<double>(0,0) = -px;
01042         Rpi.at<double>(0,1) = 2*pz;
01043         Rpi.at<double>(0,2) = px;
01044 
01045         Rpi.at<double>(1,0) = py;
01046         Rpi.at<double>(1,1) = 0;
01047         Rpi.at<double>(1,2) = py;
01048 
01049         Rpi.at<double>(2,0) = -pz;
01050         Rpi.at<double>(2,1) = -2*px;
01051         Rpi.at<double>(2,2) = pz;
01052 
01053         Mat E = (_eye - V[i])*(Rz*Rpi + opt_t);
01054 
01055         Mat e0(3,1,CV_64F);
01056         Mat e1(3,1,CV_64F);
01057         Mat e2(3,1,CV_64F);
01058 
01059         e0.at<double>(0,0) = E.at<double>(0,2);
01060         e0.at<double>(1,0) = E.at<double>(1,2);
01061         e0.at<double>(2,0) = E.at<double>(2,2);
01062 
01063         e1.at<double>(0,0) = E.at<double>(0,1);
01064         e1.at<double>(1,0) = E.at<double>(1,1);
01065         e1.at<double>(2,0) = E.at<double>(2,1);
01066 
01067         e2.at<double>(0,0) = E.at<double>(0,0);
01068         e2.at<double>(1,0) = E.at<double>(1,0);
01069         e2.at<double>(2,0) = E.at<double>(2,0);
01070 
01071 /*
01072         printf("E\n");
01073         Print(E);
01074 
01075         printf("e2\n");
01076         Print(e2);
01077 */
01078         Mat sum1 = Sum(Sq(e2));
01079              //printf("e2\n");
01080         //Print(e2);
01081 
01082         Mat sum2 = Sum(2*Mul(e1,e2));
01083 
01084         //printf("e2\n");
01085         //Print(e2);
01086 
01087         Mat sum3 = Sum(2*Mul(e0,e2) + Sq(e1));
01088 
01089         //printf("e2\n");
01090         //Print(e2);
01091 
01092         Mat sum4 = Sum(2*Mul(e0,e1));
01093         Mat sum5 = Sum(Sq(e0));
01094 
01095 
01096 
01097 
01098         // E_2 =E_2+ sum([e2.^2 2.*e1.*e2 (2.*e0.*e2+e1.^2) 2.*e0.*e1 e0.^2]);
01099         E_2.at<double>(0,0) += sum1.at<double>(0,0);
01100         E_2.at<double>(0,1) += sum2.at<double>(0,0);
01101         E_2.at<double>(0,2) += sum3.at<double>(0,0);
01102         E_2.at<double>(0,3) += sum4.at<double>(0,0);
01103         E_2.at<double>(0,4) += sum5.at<double>(0,0);
01104     }
01105 
01106     double e4=E_2.at<double>(0,0);
01107     double e3=E_2.at<double>(0,1);
01108     double e2=E_2.at<double>(0,2);
01109     double e1=E_2.at<double>(0,3);
01110     double e0=E_2.at<double>(0,4);
01111 
01112     //printf("e0 to e4 = %f %f %f %f %f\n", e0, e1, e2, e3, e4);
01113 
01114     double a4=-e3;
01115     double a3=(4*e4-2*e2);
01116     double a2=(-3*e1+3*e3);
01117     double a1=(-4*e0+2*e2);
01118     double a0=e1;
01119 
01120     double coeffs[5];
01121 //    double z[10];
01122 /*
01123     // backwards in GSL
01124     coeffs[0] = a0;
01125     coeffs[1] = a1;
01126     coeffs[2] = a2;
01127     coeffs[3] = a3;
01128     coeffs[4] = a4;
01129 */
01130     coeffs[0] = a4;
01131     coeffs[1] = a3;
01132     coeffs[2] = a2;
01133     coeffs[3] = a1;
01134     coeffs[4] = a0;
01135 
01136     //printf("coeffs = %f %f %f %f\n", coeffs[0], coeffs[1], coeffs[2], coeffs[3]);
01137     int degrees = 4;
01138     double zero_real[5];
01139     double zero_imag[5];
01140 
01141     memset(zero_real, 0, sizeof(double)*5);
01142     memset(zero_imag, 0, sizeof(double)*5);
01143 
01144     rpoly_ak1(coeffs, &degrees, zero_real, zero_imag);
01145 
01146 /*
01147     gsl_poly_complex_workspace *w = gsl_poly_complex_workspace_alloc(5);
01148     gsl_poly_complex_solve (coeffs, 5, w, z);
01149     gsl_poly_complex_workspace_free (w);
01150 */
01151     // get all valid solutions -> which are real zero
01152 
01153     at.clear();
01154 
01155     // Nghia - modified a bit here, if it fails use the original
01156     for(int i=0; i < 5; i++) {
01157         double _at = zero_real[i];
01158 
01159         double p1 = pow(1.0 + _at*_at, 3.0);
01160 
01161         if(fabs(p1) > 0.1 && zero_imag[i] == 0) {
01162             at.push_back(_at);
01163         }
01164     }
01165 
01166 /*
01167     // check for valid solutions
01168     for(int i=0; i < 8; i+=2) {
01169         double _at = z[i];
01170 
01171         double p1 = pow(1.0 + _at*_at, 3.0);
01172 
01173         if(fabs(p1) > 0.1 && z[i+1] == 0)
01174             at.push_back(_at);
01175     }
01176 */
01177     //printf("at size: %d\n", at.size());
01178 
01179     al.resize(at.size());
01180 
01181     vector <double> al2, at2;
01182 
01183     for(unsigned int i=0; i < at.size(); i++) {
01184         double sa = (2.f*at[i]) / (1.f +at[i]*at[i]);
01185         double ca = (1.f - at[i]*at[i]) / (1.f + at[i]*at[i]);
01186 
01187         al[i] = atan2(sa,ca) * 180/M_PI;
01188 
01189         double tMaxMin = (4*a4*at[i]*at[i]*at[i] + 3*a3*at[i]*at[i] + 2*a2*at[i] + a1);
01190 
01191         if(tMaxMin > 0) {
01192             al2.push_back(al[i]);
01193             at2.push_back(at[i]);
01194         }
01195     }
01196 
01197     al = al2;
01198     at = at2;
01199 
01200     tnew = Mat(3,al.size(),CV_64F);
01201 
01202     for(unsigned int a=0; a < al.size(); a++) {
01203         Mat R = Rz*RpyMat(Vec3d(0, (al[a]*M_PI/180), 0));
01204         Mat t_opt = Mat::zeros(3,1,CV_64F);
01205 
01206         Mat pcol(3,1,CV_64F);
01207 
01208         for(int i=0; i < v.cols; i++) {
01209             pcol.at<double>(0,0) = p.at<double>(0,i);
01210             pcol.at<double>(1,0) = p.at<double>(1,i);
01211             pcol.at<double>(2,0) = p.at<double>(2,i);
01212 
01213             t_opt = t_opt + (V[i] - _eye)*R*pcol;
01214         }
01215 
01216         t_opt = G*t_opt;
01217 
01218         tnew.at<double>(0,a) = t_opt.at<double>(0,0);
01219         tnew.at<double>(1,a) = t_opt.at<double>(1,0);
01220         tnew.at<double>(2,a) = t_opt.at<double>(2,0);
01221     }
01222 }
01223 
01224 void Print(const Mat &m)
01225 {
01226     for(int i=0; i < m.rows; i++) {
01227         for(int j=0; j < m.cols; j++) {
01228             printf("%4.6f ", m.at<double>(i,j));
01229         }
01230         printf("\n");
01231     }
01232 
01233     printf("\n");
01234 }
01235 
01236 void Print(const Quaternion &q)
01237 {
01238     printf("vector = %f %f %f\n", q.vector[0], q.vector[1], q.vector[2]);
01239     printf("scalar = %f\n", q.scalar);
01240     printf("\n");
01241 }
01242 
01243 }


fiducial_pose
Author(s): Jim Vaughan
autogenerated on Thu Jun 6 2019 18:08:11