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
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
00025
00026 bool status = Get2ndPose_Exact(iprts, model_3D, Rlu, tlu, sol);
00027
00028 if(!status) {
00029 return false;
00030 }
00031
00032
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
00056
00057
00058
00059
00060
00061
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();
00070
00071 int n = P.cols;
00072 it = 0;
00073
00074 Mat pbar = Sum(P,2) / n;
00075
00076
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
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
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
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
00155 AbsKernel(P, Qp, F, tFactor, Ri, ti, Qi, old_err);
00156 it = 1;
00157
00158
00159
00160 }
00161
00162
00163 double new_err;
00164
00165 AbsKernel(P, Qi, F, tFactor, Ri, ti, Qi, new_err);
00166
00167 it = it + 1;
00168
00169
00170
00171 while(fabs((old_err-new_err)/old_err) > TOL && (new_err > EPSILON)) {
00172 old_err = new_err;
00173
00174 AbsKernel(P, Qi, F, tFactor, Ri, ti, Qi, new_err);
00175
00176
00177 it = it + 1;
00178 }
00179
00180 R = Ri;
00181 t = ti;
00182 obj_err = sqrt(new_err/n);
00183
00184
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
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
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
00259
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
00285
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
00292 R = -v*decomp.u.t();
00293 t = EstimateT(R,G,F,P);
00294 }
00295 }
00296 else {
00297
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
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
00370
00371
00372
00373 double n = Norm(Vec2Mat(q_vector));
00374
00375
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
00390
00391
00392
00393
00394
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
00428
00429 double winkel = acos(v2.dot(v1));
00430
00431
00432
00433 Quaternion QU = Quaternion_byAngleAndVector(winkel,v2.cross(v1));
00434
00435
00436
00437
00438 Mat R = quat2mat(QU);
00439
00440
00441
00442
00443 Mat a = Sum(Sq(NormRv(v1) - R*NormRv(v2)));
00444
00445
00446
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
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
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
00634
00635
00636
00637
00638
00639
00640
00641 Mat a = R-RpyMat(angs);
00642
00643
00644
00645
00646
00647
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
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
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
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
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
00739 for(unsigned int i=0; i < sol.size(); i++) {
00740
00741
00742
00743 sol[i].R = Rim.t()*sol[i].R;
00744
00745
00746
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
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
00763
00764
00765
00766
00767
00768 Mat R_ = R*Rz;
00769
00770
00771
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
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
00850
00851
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
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
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
00917
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
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
00953
00954
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
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
00982
00983
00984
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
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
01073
01074
01075
01076
01077
01078 Mat sum1 = Sum(Sq(e2));
01079
01080
01081
01082 Mat sum2 = Sum(2*Mul(e1,e2));
01083
01084
01085
01086
01087 Mat sum3 = Sum(2*Mul(e0,e2) + Sq(e1));
01088
01089
01090
01091
01092 Mat sum4 = Sum(2*Mul(e0,e1));
01093 Mat sum5 = Sum(Sq(e0));
01094
01095
01096
01097
01098
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
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
01122
01123
01124
01125
01126
01127
01128
01129
01130 coeffs[0] = a4;
01131 coeffs[1] = a3;
01132 coeffs[2] = a2;
01133 coeffs[3] = a1;
01134 coeffs[4] = a0;
01135
01136
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, °rees, zero_real, zero_imag);
01145
01146
01147
01148
01149
01150
01151
01152
01153 at.clear();
01154
01155
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
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
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 }