00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "SIFT/SIFTegomotion.H"
00039 #include "SIFT/VisualObject.H"
00040 #include "Image/CutPaste.H"
00041 #include "Image/DrawOps.H"
00042 #include "Raster/Raster.H"
00043 #include "Image/LinearAlgebra.H"
00044 #include "Image/MatrixOps.H"
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 double getMag(Image<double> v)
00112 {
00113 double mag = 0.0;
00114 for(int i = 0; i < v.getHeight(); i++)
00115 mag += v.getVal(0,i)*v.getVal(0,i);
00116
00117 return sqrt(mag);
00118 }
00119
00120
00121 SIFTegomotion::SIFTegomotion(rutz::shared_ptr<VisualObjectMatch> match,
00122 rutz::shared_ptr<CameraIntrinsicParam> cip,
00123 rutz::shared_ptr<XWinManaged> matchWin) :
00124 itsVoMatch(match),
00125 itsCip(cip),
00126 itsMatchWin(matchWin)
00127 {
00128 setCuMatch();
00129 calc();
00130 }
00131
00132
00133 void SIFTegomotion::setCuMatch()
00134 {
00135 for(uint i = 0; i < itsVoMatch->size(); i++)
00136 {
00137 double u1vo = (*itsVoMatch)[i].refkp->getX();
00138 double v1vo = (*itsVoMatch)[i].refkp->getY();
00139 double u2vo = (*itsVoMatch)[i].tstkp->getX();
00140 double v2vo = (*itsVoMatch)[i].tstkp->getY();
00141
00142
00143
00144 bool isIdentical = 0;
00145 for(uint j = 0; j < itsCuMatch.size(); j++)
00146 {
00147 double u1cu = itsCuMatch[j].refkp->getX();
00148 double v1cu = itsCuMatch[j].refkp->getY();
00149 double u2cu = itsCuMatch[j].tstkp->getX();
00150 double v2cu = itsCuMatch[j].tstkp->getY();
00151
00152
00153 if(fabs(u1vo - u1cu) < .05 &&
00154 fabs(v1vo - v1cu) < .05 &&
00155 fabs(u2vo - u2cu) < .05 &&
00156 fabs(v2vo - v2cu) < .05 )
00157 {
00158
00159 isIdentical = 1;
00160
00161
00162 }
00163 }
00164
00165 if(!isIdentical)
00166 {
00167
00168 itsCuMatch.push_back((*itsVoMatch)[i]);
00169 }
00170 }
00171
00172 LINFO("there are %"ZU" unique coordinate (%"ZU" duplicates)",
00173 itsCuMatch.size(), itsVoMatch->size() - itsCuMatch.size());
00174
00175 }
00176
00177
00178 Image<double> SIFTegomotion::getU(int nPoint)
00179 {
00180 uint size;
00181 if (nPoint == -1) size = itsCuMatch.size();
00182 else size = nPoint;
00183
00184 Image<double> U(9,size,ZEROS);
00185
00186 int w = itsMatchWin->getDims().w()/2;
00187 int h = itsMatchWin->getDims().h()/2;
00188 Image< PixRGB<byte> > img(w,2*h,ZEROS);
00189
00190
00191 Image<double> A; Image<double> Ainv;
00192 if(itsCip.is_valid())
00193 {
00194 A = itsCip->getCameraMatrix();
00195 Ainv = matrixInv(A);
00196 print(A, "Camera Matrix");
00197 print(Ainv, "Inverse Camera Matrix");
00198 }
00199
00200 LINFO("there are %d points in the match", itsVoMatch->size());
00201
00202 Image< PixRGB<byte> > rImg = itsVoMatch->getVoRef()->getImage();
00203 Image< PixRGB<byte> > tImg = itsVoMatch->getVoTest()->getImage();
00204 for(uint i = 0; i < size; i++)
00205 {
00206
00207 double tU = itsCuMatch[i].refkp->getX();
00208 double tV = itsCuMatch[i].refkp->getY();
00209 double rU = itsCuMatch[i].tstkp->getX();
00210 double rV = itsCuMatch[i].tstkp->getY();
00211 double rUdot = tU - rU;
00212 double rVdot = tV - rV;
00213 LDEBUG("UNCALIB: (%10.5f,%10.5f) & (%10.5f,%10.5f) -> (%10.5f,%10.5f)",
00214 rU, rV, tU, tV, rUdot, rVdot);
00215
00216 Point2D<int> locR(int(rU + 0.5F), int(rV + 0.5F));
00217 drawDisk(rImg, locR, 2, PixRGB<byte>(255,0,0));
00218 Point2D<int> locT(int(tU + 0.5F), int(tV + 0.5F));
00219 drawDisk(tImg, locT, 2, PixRGB<byte>(255,0,0));
00220
00221 drawLine(rImg, locR, locT, PixRGB<byte>(255,255,0));
00222
00223
00224 if(itsCip.is_valid())
00225 {
00226 Image<double> mR(1,3,ZEROS);
00227 mR.setVal(0, 0, rU); mR.setVal(0, 1, rV); mR.setVal(0, 2, 1.0);
00228 Image<double> pR = matrixMult(Ainv, mR);
00229
00230 rU = pR.getVal(0,0);
00231 rV = pR.getVal(0,1);
00232
00233 Image<double> mT(1,3,ZEROS);
00234 mT.setVal(0, 0, tU); mT.setVal(0, 1, tV); mT.setVal(0, 2, 1.0);
00235 Image<double> pT = matrixMult(Ainv, mT);
00236 tU = pT.getVal(0,0);
00237 tV = pT.getVal(0,1);
00238
00239 rVdot = tU - rU;
00240 rUdot = tV - rV;
00241
00242 LDEBUG("CALIB: (%10.5f,%10.5f) & (%10.5f,%10.5f) -> (%10.5f,%10.5f)",
00243 rU, rV, tU, tV, rUdot, rVdot);
00244 }
00245
00246
00247 double m1 = rU;
00248 double m2 = rV;
00249 double m3 = 1.0f;
00250 double m1dot = rUdot;
00251 double m2dot = rVdot;
00252 double m3dot = 0.0f;
00253
00254 U.setVal(0, i, m1*m1);
00255 U.setVal(1, i, 2*m1*m2);
00256 U.setVal(2, i, 2*m1*m3);
00257 U.setVal(3, i, m2*m2);
00258 U.setVal(4, i, 2*m2*m3);
00259 U.setVal(5, i, m3*m3);
00260 U.setVal(6, i, m1*m2dot - m2*m1dot);
00261 U.setVal(7, i, m1*m3dot - m3*m1dot);
00262 U.setVal(8, i, m2*m3dot - m3*m2dot);
00263
00264 }
00265
00266 inplacePaste(img, rImg, Point2D<int>(0, 0));
00267 inplacePaste(img, tImg, Point2D<int>(0, h));
00268 itsMatchWin->drawImage(img,w,0);
00269
00270
00271 return U;
00272 }
00273
00274
00275 void SIFTegomotion::calc()
00276 {
00277 uint techNum = 0;
00278
00279 if(techNum == 0)
00280 leastSquaresAlgebraic();
00281 else
00282 sevenPointAlgorithm();
00283 }
00284
00285
00286 void SIFTegomotion::leastSquaresAlgebraic()
00287 {
00288
00289 Image<double> U = getU(); print(U, "U");
00290 Image<double> A = matrixMult(transpose(U), U); print(A, "A");
00291
00292
00293
00294
00295 Image<double> V1;
00296 Image<double> D;
00297 Image<double> V2;
00298 svd(A, V1, D, V2, SVD_LAPACK, SVD_FULL);
00299 print(V1,"V1"); print(D, "D"); print(V2, "V2");
00300
00301
00302
00303 Image<double> T = crop(V2, Point2D<int>(8,0), Dims(1, 9)); print(T, "T");
00304
00305 Image<double> ans = matrixMult(U,T); print(ans,"ans");
00306
00307
00308
00309 itsVel = getVel(T);
00310 itsOmega = getOmega(T);
00311 print(T, "T"); print(itsVel, "vel"); print(itsOmega, "omega");
00312
00313 }
00314
00315
00316
00317
00318 void SIFTegomotion::sevenPointAlgorithm()
00319 {
00320
00321
00322 Image<double> U = getU(7); print(U, "U");
00323
00324
00325 Image<double> V1;
00326 Image<double> D;
00327 Image<double> V2;
00328 svd(U, V1, D, V2, SVD_LAPACK, SVD_FULL);
00329 print(V1,"V1"); print(D, "D"); print(V2, "V2");
00330
00331 uint zeig = 0;
00332 for(uint i = 0; i < 7; i++)
00333 {
00334 LINFO("eig[%d] = %20.10f",i+1,D.getVal(i,i));
00335 if(D.getVal(i,i) < .0000001) zeig++;
00336 }
00337 if( zeig > 0)
00338 {
00339 LINFO("> 2 null spaces; points are ill conditioned");
00340 Raster::waitForKey();
00341 }
00342
00343
00344
00345 Image<double> T1 = crop(V1, Point2D<int>(7,0), Dims(1, 9)); print(T1, "T1");
00346 Image<double> T2 = crop(V1, Point2D<int>(8,0), Dims(1, 9)); print(T2, "T2");
00347
00348
00349
00350
00351
00352
00353 Image<double> T = constraint2(T1,T2); print(T,"T");
00354 checkConstraint2(U, T);
00355 }
00356
00357
00358
00359 void SIFTegomotion::checkConstraint2(Image<double> U, Image<double> T)
00360 {
00361 Image<double> Wtemp(1,3,ZEROS);
00362 Image<double> Ctemp(3,3,ZEROS);
00363 Wtemp.setVal(0,0, -T.getVal(0,8));
00364 Wtemp.setVal(0,1, T.getVal(0,7));
00365 Wtemp.setVal(0,2, -T.getVal(0,6));
00366
00367 Ctemp.setVal(0,0, T.getVal(0,0));
00368 Ctemp.setVal(0,1, T.getVal(0,1));
00369 Ctemp.setVal(0,2, T.getVal(0,2));
00370 Ctemp.setVal(1,0, T.getVal(0,1));
00371 Ctemp.setVal(1,1, T.getVal(0,3));
00372 Ctemp.setVal(1,2, T.getVal(0,4));
00373 Ctemp.setVal(2,0, T.getVal(0,2));
00374 Ctemp.setVal(2,1, T.getVal(0,4));
00375 Ctemp.setVal(2,2, T.getVal(0,5));
00376 print(Ctemp,"Ctemp"); print(Wtemp,"Wtemp");
00377 Image<double> wCw = matrixMult(matrixMult(transpose(Wtemp), Ctemp), Wtemp);
00378 print(wCw, "wCw");
00379 }
00380
00381
00382 Image<double> SIFTegomotion::constraint2(Image<double> T1)
00383 {
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 Image<double> W_hat = getW(T1); print(W_hat, "W_hat");
00397 Image<double> C_hat = getC(T1); print(C_hat, "C_hat");
00398 Raster::waitForKey();
00399
00400 Image<double> I(3,3, ZEROS);
00401 I.setVal(0,0, 1.0);I.setVal(1,1, 1.0);I.setVal(2,2, 1.0);
00402 Image<double> omega = getOmega(T1); print(omega, "omega");
00403 Raster::waitForKey();
00404
00405 double magOmega = 1.0;
00406 LINFO("magOmega: %f",magOmega);
00407 Image<double> P = I - matrixMult(W_hat,W_hat) * magOmega; print(P, "P");
00408 Raster::waitForKey();
00409
00410 Image<double> C = C_hat - matrixMult(matrixMult(P,C_hat),P); ;
00411 Image<double> W = W_hat;
00412 double magT = getMag(getThetaCW(C,W));
00413 W = W/magT;
00414 C = C/magT;
00415 Image<double> T = getThetaCW(C,W);
00416 Raster::waitForKey();
00417
00418 return T;
00419 }
00420
00421
00422 Image<double> SIFTegomotion::constraint2(Image<double> T1, Image<double> T2)
00423 {
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 Image<double> T(1, 9, ZEROS);
00453
00454
00455
00456 double p = 0.0, q = 0.0, r = 0.0, s = 0.0;
00457 double aa, bb, cc, dd, ee, ff;
00458
00459
00460
00461 uint indI, indJ, indK; double sign;
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 for(uint i = 0; i < 9; i++)
00478 {
00479 if(i == 0)
00480 {
00481
00482
00483 indI = 8, indJ = 8, indK = 0; sign = 1.0;
00484 }
00485 else if(i == 1)
00486 {
00487
00488
00489 indI = 7, indJ = 8, indK = 1; sign = -1.0;
00490 }
00491 else if(i == 2)
00492 {
00493
00494
00495 indI = 6, indJ = 8, indK = 2; sign = 1.0;
00496 }
00497 else if(i == 3)
00498 {
00499
00500
00501 indI = 8, indJ = 7, indK = 1; sign = -1.0;
00502 }
00503 else if(i == 4)
00504 {
00505
00506
00507 indI = 7, indJ = 7, indK = 3; sign = 1.0;
00508 }
00509 else if(i == 5)
00510 {
00511
00512
00513 indI = 6, indJ = 7, indK = 4; sign = -1.0;
00514 }
00515 else if(i == 6)
00516 {
00517
00518
00519 indI = 8, indJ = 6, indK = 2; sign = 1.0;
00520 }
00521 else if(i == 7)
00522 {
00523
00524
00525 indI = 7, indJ = 6, indK = 4; sign = -1.0;
00526 }
00527 else
00528 {
00529
00530
00531 indI = 6, indJ = 6, indK = 5; sign = 1.0;
00532 }
00533
00534 aa = T2.getVal(0, indI);
00535 bb = T1.getVal(0, indI) - T2.getVal(0, indI);
00536 cc = T2.getVal(0, indJ);
00537 dd = T1.getVal(0, indJ) - T2.getVal(0, indJ);
00538 ee = T2.getVal(0, indK);
00539 ff = T1.getVal(0, indK) - T2.getVal(0, indK);
00540
00541 p+= sign * (bb*dd*ff);
00542 q+= sign * (aa*dd*ff + bb*cc*ff + bb*dd*ee);
00543 r+= sign * (aa*cc*ff + aa*dd*ee + bb*cc*ee);
00544 s+= sign * (aa*cc*ee);
00545
00546 LINFO(" %f*alpha^3 + %f*alpha^2 + %f*alpha + %f",
00547 sign * (bb*dd*ff),
00548 sign * (aa*dd*ff + bb*cc*ff + bb*dd*ee),
00549 sign * (aa*cc*ff + aa*dd*ee + bb*cc*ee),
00550 sign * (aa*cc*ee));
00551
00552 LINFO("%d:[%d,%d,%d] (%f,%f,%f,%f,%f,%f) sign:(%f) p:%f, q:%f r:%f s:%f",
00553 i, indI, indJ, indK,
00554 aa, bb, cc, dd, ee, ff, sign, p,q,r,s);
00555 }
00556
00557
00558 std::vector<std::complex<double> > alpha;
00559 uint numSoln = solveCubic(p, q, r, s, alpha);
00560 LINFO("Number of real solutions: %d",numSoln);
00561 LINFO("X1 = %f + %fi, X2 = %f + %fi, X3 = %f + %fi",
00562 alpha[0].real(), alpha[0].imag(),
00563 alpha[1].real(), alpha[1].imag(),
00564 alpha[2].real(), alpha[2].imag() );
00565
00566
00567 for(uint ns = 0; ns < numSoln; ns++)
00568 {
00569
00570 for(uint i= 0; i < 9; i++)
00571 T.setVal(0,i, (alpha[ns].real()*T1.getVal(0,i) +
00572 (1.0 - alpha[ns].real())*T2.getVal(0,i)));
00573
00574
00575 if(itsCip.is_valid())
00576 {
00577 itsVel = getVel(T);
00578 itsOmega = getOmega(T);
00579 }
00580 else
00581 getUncalibCW(T);
00582 }
00583 Raster::waitForKey();
00584
00585 return T;
00586 }
00587
00588 Image<double> SIFTegomotion::getThetaCW(Image<double> C, Image<double> W)
00589 {
00590 Image<double> T(1,9, ZEROS);
00591
00592 T.setVal(0,0, C.getVal(0,0));
00593 T.setVal(0,1, C.getVal(0,1));
00594 T.setVal(0,2, C.getVal(0,2));
00595 T.setVal(0,3, C.getVal(1,1));
00596 T.setVal(0,4, C.getVal(1,2));
00597 T.setVal(0,5, C.getVal(2,2));
00598
00599 T.setVal(0,6, W.getVal(1,0));
00600 T.setVal(0,7, W.getVal(2,0));
00601 T.setVal(0,8, W.getVal(2,1));
00602
00603 return T;
00604 }
00605
00606
00607 Image<double> SIFTegomotion::getC(Image<double> T)
00608 {
00609 Image<double> C(3,3, ZEROS);
00610 C.setVal(0,0, T.getVal(0,0));
00611 C.setVal(0,1, T.getVal(0,1));
00612 C.setVal(0,2, T.getVal(0,2));
00613
00614 C.setVal(1,0, T.getVal(0,1));
00615 C.setVal(1,1, T.getVal(0,3));
00616 C.setVal(1,2, T.getVal(0,4));
00617
00618 C.setVal(2,0, T.getVal(0,2));
00619 C.setVal(2,1, T.getVal(0,4));
00620 C.setVal(2,2, T.getVal(0,5));
00621 return C;
00622 }
00623
00624
00625 Image<double> SIFTegomotion::getW(Image<double> T)
00626 {
00627 Image<double> W(3,3, ZEROS);
00628 W.setVal(1,0, T.getVal(0,6));
00629 W.setVal(2,0, T.getVal(0,7));
00630 W.setVal(2,1, T.getVal(0,8));
00631 W.setVal(0,1, -T.getVal(0,6));
00632 W.setVal(0,2, -T.getVal(0,7));
00633 W.setVal(1,2, -T.getVal(0,8));
00634 return W;
00635 }
00636
00637
00638 Image<double> SIFTegomotion::getThetaVelOmega
00639 (Image<double> vel, Image<double> omega)
00640 {
00641 Image<double> T(1,9, ZEROS);
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656 return T;
00657 }
00658
00659
00660 Image<double> SIFTegomotion::getVel(Image<double> T)
00661 {
00662
00663
00664 double v1 = -T.getVal(0,8);
00665 double v2 = T.getVal(0,7);
00666 double v3 = -T.getVal(0,6);
00667
00668 LINFO("translational velocity (%f,%f,%f)", v1, v2, v3);
00669 Image<double> vel(1,3,ZEROS);
00670 vel.setVal(0,0, v1);
00671 vel.setVal(0,1, v2);
00672 vel.setVal(0,2, v3);
00673 return vel;
00674 }
00675
00676
00677 Image<double> SIFTegomotion::getOmega(Image<double> T)
00678 {
00679
00680
00681 double v1 = -T.getVal(0,8);
00682 double v2 = T.getVal(0,7);
00683 double v3 = -T.getVal(0,6);
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697 double omega1 = 0.0, omega2 = 0.0, omega3 = 0.0;
00698 if(v1 == 0.0 && v2 == 0.0 && v3 == 0.0)
00699 {
00700
00701
00702 }
00703 else if(v1 == 0.0 && v2 == 0.0)
00704 {
00705 omega1 = T.getVal(0,2)/v3;
00706 omega2 = T.getVal(0,4)/v3;
00707 omega3 = -T.getVal(0,3)/v3;
00708 }
00709 else if(v1 == 0.0 && v3 == 0.0)
00710 {
00711 omega1 = T.getVal(0,1)/v2;
00712 omega2 = -T.getVal(0,0)/v2;
00713 omega3 = T.getVal(0,4)/v2;
00714 }
00715 else if(v2 == 0.0 && v3 == 0.0)
00716 {
00717 omega1 = -T.getVal(0,5)/v1;
00718 omega2 = T.getVal(0,1)/v1;
00719 omega3 = T.getVal(0,2)/v1;
00720 }
00721 else if(v1 == 0.0)
00722 {
00723 omega1 = T.getVal(0,1)/v2;
00724 omega2 = T.getVal(0,4)/v3;
00725 omega3 = T.getVal(0,3)/v2;
00726 }
00727 else if(v2 == 0.0)
00728 {
00729 omega1 = T.getVal(0,2)/v3;
00730 omega2 = T.getVal(0,4)/v3;
00731 omega3 = T.getVal(0,3)/v1;
00732 }
00733 else
00734 {
00735 omega1 = T.getVal(0,1)/v2;
00736 omega2 = T.getVal(0,1)/v1;
00737 omega3 = T.getVal(0,2)/v1;
00738 }
00739
00740 LINFO("angular velocity: (%f,%f,%f)", omega1, omega2, omega3);
00741 Image<double> omega(1,3,ZEROS);
00742 omega.setVal(0,0, omega1);
00743 omega.setVal(0,1, omega2);
00744 omega.setVal(0,2, omega3);
00745 return omega;
00746 }
00747
00748
00749 void SIFTegomotion::getUncalibCW(Image<double> T)
00750 {
00751
00752
00753
00754
00755
00756 double c11 = T.getVal(0,0);
00757 double c12 = T.getVal(0,1);
00758 double c13 = T.getVal(0,2);
00759 double c22 = T.getVal(0,3);
00760 double c23 = T.getVal(0,4);
00761 double c33 = T.getVal(0,5);
00762 double w12 = T.getVal(0,6);
00763 double w13 = T.getVal(0,7);
00764 double w23 = T.getVal(0,8);
00765 double w1 = w12;
00766 double w2 = w13;
00767 double w3 = w23;
00768
00769
00770 double delta1 = (2*c12*w2 - (c22 - c11)*w1) / (w1*w1 + w2*w2);
00771 double delta2 = (2*c12*w1 + (c22 - c11)*w2) / (w1*w1 + w2*w2);
00772 double delta3 = (c11*w1*w1 + 2*c12*w1*w2 + c22*w2*w2) / (w3*(w1*w1 + w2*w2));
00773 double psi = (w1*w1 + w2*w2 + w3*w3)*(w2*delta1 + w2*delta2);
00774 double d1 = 2*c13 + w1*delta3;
00775 double d2 = 2*c23 + w2*delta3;
00776 double d3 = c33;
00777 double delta4 = - d3 / (w1*delta1 + w3*delta2);
00778 double delta5 = (1.0/psi) * ((w1*w2*delta1 + (w2*w2 + w3*w3)*delta2)*d1
00779 - ((w1*w1 + w3*w3)*delta1 + w1*w2*delta2)*d2
00780 + (w2*w3*delta1 - w1*w3*delta2)*d3);
00781
00782 LINFO("d1: %f, d2: %f, d3: %f", d1, d2, d3);
00783 LINFO("psi: %f",psi);
00784 LINFO("delta:(1: %f, 2: %f, 3: %f, 4:%f, 5:%f",
00785 delta1, delta2, delta3, delta4, delta5);
00786
00787 double flen = sqrt(delta4);
00788 double omega1 = delta1 * sqrt(flen);
00789 double omega2 = delta2 * sqrt(flen);
00790 double omega3 = delta3;
00791 double flen_dot = delta5 * sqrt(flen);
00792
00793 double v1 = -w1 / flen;
00794 double v2 = -w2 / flen;
00795 double v3 = w3;
00796
00797 LINFO("focal length: %f, flen_dot: %f",flen, flen_dot);
00798 LINFO("angular velocity: (%f,%f,%f)", omega1, omega2, omega3);
00799 LINFO("translational velocity (%f,%f,%f)", v1, v2, v3);
00800 }
00801
00802
00803
00804 double sgn(double x)
00805 {
00806 if (x < 0.0) return -1.0;
00807 return 1.0;
00808 }
00809
00810
00811 uint SIFTegomotion::solveCubic(double p, double q, double r, double s,
00812 std::vector<std::complex<double> >& x)
00813 {
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823 double A,B,C;
00824 if(p != 0.0)
00825 {
00826 A = q/p;
00827 B = r/p;
00828 C = s/p;
00829 }
00830 else if(q != 0.0)
00831 {
00832
00833
00834
00835
00836 double temp = r*r - 4.0*q*s;
00837 if(temp == 0.0)
00838 {
00839 x.push_back(std::complex<double>(-r/(2.0*q), 0.0));
00840 return 1;
00841 }
00842 else if(temp > 0.0)
00843 {
00844 x.push_back(std::complex<double>((-r + sqrt(temp))/(2.0*q), 0.0));
00845 x.push_back(std::complex<double>((-r - sqrt(temp))/(2.0*q), 0.0));
00846 return 2;
00847 }
00848 else
00849 {
00850 x.push_back(std::complex<double>(-r/(2.0*q), sqrt(-temp)/(2.0*q)));
00851 x.push_back(std::complex<double>(-r/(2.0*q), -sqrt(-temp)/(2.0*q)));
00852 return 0;
00853 }
00854 }
00855 else if(r != 0.0)
00856 {
00857
00858 x.push_back(std::complex<double>(-s/r, 0.0));
00859 return 1;
00860 }
00861 else
00862
00863 return 0;
00864
00865 double X1, X2, X3, Im;
00866 double Q, R, D, S, T;
00867
00868 Q = (3*B - (A*A))/9.0;
00869 R = (9*A*B - 27*C - 2*(A*A*A))/54.0;
00870 D = (Q*Q*Q) + (R*R);
00871
00872 if (D >= 0)
00873 {
00874 S = sgn(R + sqrt(D)) * pow(fabs(R + sqrt(D)),(1.0/3.0));
00875 T = sgn(R - sqrt(D)) * pow(fabs(R - sqrt(D)),(1.0/3.0));
00876
00877 X1 = -A/3.0 + (S + T);
00878 X2 = -A/3.0 - (S + T)/2.0;
00879 X3 = -A/3.0 - (S + T)/2.0;
00880 Im = fabs(sqrt(3)*(S - T)/2.0);
00881 }
00882 else
00883 {
00884 double th = acos(R/sqrt(-pow(Q, 3)));
00885
00886 X1 = 2*sqrt(-Q) * cos(th/3.0) - A/3.0;
00887 X2 = 2*sqrt(-Q) * cos((th + 2*M_PI)/3) - A/3.0;
00888 X3 = 2*sqrt(-Q) * cos((th + 4*M_PI)/3) - A/3.0;
00889 Im = 0.0;
00890 }
00891
00892
00893 if (Im == 0.0)
00894 {
00895 x.push_back(std::complex<double>(X1, 0.0));
00896 x.push_back(std::complex<double>(X2, 0.0));
00897 x.push_back(std::complex<double>(X3, 0.0));
00898 LDEBUG("X1 = %f, X2 = %f, X3 = %f", X1, X2, X3);
00899 return 3;
00900 }
00901 else
00902 {
00903 x.push_back(std::complex<double>(X1, 0.0));
00904 x.push_back(std::complex<double>(X2, Im));
00905 x.push_back(std::complex<double>(X3, -Im));
00906 LDEBUG("X1 = %f, X2 = %f + %fi, X3 = %f - %fi", X1, X2, Im, X3, Im);
00907 return 1;
00908 }
00909 }
00910
00911
00912 void SIFTegomotion::print(Image<double> img, const std::string& name)
00913 {
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923 }
00924
00925
00926
00927
00928
00929