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 #include <posest/pe3d.h>
00037 #include <sba/sba.h>
00038 #include <Eigen/SVD>
00039 #include <Eigen/LU>
00040 #include <iostream>
00041 
00042 
00043 using namespace Eigen;
00044 using namespace sba;
00045 using namespace frame_common;
00046 using namespace std;
00047 
00048 namespace pe
00049 {
00050 
00051 
00052   
00053   
00054   
00055   
00056   
00057   
00058   
00059   
00060 
00061   int PoseEstimator3d::estimate(const Frame& f0, const Frame& f1, 
00062                                 const std::vector<cv::DMatch> &matches)
00063   {
00064     
00065     std::vector<Vector4d, aligned_allocator<Vector4d> > p0; 
00066     std::vector<Vector4d, aligned_allocator<Vector4d> > p1;
00067 
00068     int nmatch = matches.size();
00069 
00070     
00071     
00072     vector<int> m0, m1;
00073     for (int i=0; i<nmatch; i++)
00074       {
00075         if (f0.disps[matches[i].queryIdx] > minMatchDisp && 
00076             f1.disps[matches[i].trainIdx] > minMatchDisp)
00077           {
00078             m0.push_back(matches[i].queryIdx);
00079             m1.push_back(matches[i].trainIdx);
00080           }
00081       }
00082 
00083     nmatch = m0.size();
00084     if (nmatch < 3) return 0;   
00085 
00086     int bestinl = 0;
00087 
00088     
00089     #pragma omp parallel for shared( bestinl )
00090     for (int i=0; i<numRansac; i++) 
00091       {
00092         
00093         int a=rand()%nmatch;
00094         int b = a;
00095         while (a==b)
00096           b=rand()%nmatch;
00097         int c = a;
00098         while (a==c || b==c)
00099           c=rand()%nmatch;
00100 
00101         int i0a = m0[a];
00102         int i0b = m0[b];
00103         int i0c = m0[c];
00104         int i1a = m1[a];
00105         int i1b = m1[b];
00106         int i1c = m1[c];
00107 
00108         if (i0a == i0b || i0a == i0c || i0b == i0c ||
00109             i1a == i1b || i1a == i1c || i1b == i1c)
00110           continue;
00111 
00112         
00113         Vector3d p0a = f0.pts[i0a].head<3>();
00114         Vector3d p0b = f0.pts[i0b].head<3>();
00115         Vector3d p0c = f0.pts[i0c].head<3>();
00116         Vector3d p1a = f1.pts[i1a].head<3>();
00117         Vector3d p1b = f1.pts[i1b].head<3>();
00118         Vector3d p1c = f1.pts[i1c].head<3>();
00119 
00120         Vector3d c0 = (p0a+p0b+p0c)*(1.0/3.0);
00121         Vector3d c1 = (p1a+p1b+p1c)*(1.0/3.0);
00122 
00123         
00124         p0a -= c0;
00125         p0b -= c0;
00126         p0c -= c0;
00127         p1a -= c1;
00128         p1b -= c1;
00129         p1c -= c1;
00130 
00131         Matrix3d H = p1a*p0a.transpose() + p1b*p0b.transpose() +
00132                      p1c*p0c.transpose();
00133 
00134 #if 0
00135         cout << p0a.transpose() << endl;
00136         cout << p0b.transpose() << endl;
00137         cout << p0c.transpose() << endl;
00138 #endif
00139 
00140         
00141         JacobiSVD<Matrix3d> svd(H, ComputeFullU | ComputeFullV);
00142         Matrix3d V = svd.matrixV();
00143         Matrix3d R = V * svd.matrixU().transpose();          
00144         double det = R.determinant();
00145         
00146         if (det < 0.0)
00147           {
00148             
00149             V.col(2) = V.col(2)*-1.0;
00150             R = V * svd.matrixU().transpose();
00151           }
00152         Vector3d tr = c0-R*c1;    
00153 
00154         
00155         
00156 
00157 #if 0
00158         R << 0.9997, 0.002515, 0.02418,
00159           -0.002474, .9999, -0.001698,
00160           -0.02418, 0.001638, 0.9997;
00161         tr << -0.005697, -0.01753, 0.05666;
00162         R = R.transpose();
00163         tr = -R*tr;
00164 #endif
00165 
00166         
00167         Matrix<double,3,4> tfm;
00168         
00169         
00170         tfm.block<3,3>(0,0) = R;
00171         tfm.col(3) = tr;
00172         
00173         
00174 
00175         
00176         int inl = 0;
00177         for (int i=0; i<nmatch; i++)
00178           {
00179             Vector3d pt = tfm*f1.pts[m1[i]];
00180             Vector3d ipt = f0.cam2pix(pt);
00181             const cv::KeyPoint &kp = f0.kpts[m0[i]];
00182             double dx = kp.pt.x - ipt.x();
00183             double dy = kp.pt.y - ipt.y();
00184             double dd = f0.disps[m0[i]] - ipt.z();
00185             if (dx*dx < maxInlierXDist2 && dy*dy < maxInlierXDist2 && 
00186                 dd*dd < maxInlierDDist2)
00187               inl+=(int)sqrt(ipt.z()); 
00188               
00189           }
00190         
00191         #pragma omp critical
00192         if (inl > bestinl) 
00193           {
00194             bestinl = inl;
00195             rot = R;
00196             trans = tr;
00197           }
00198       }
00199 
00200     
00201     
00202 
00203     
00204     vector<cv::DMatch> inls;    
00205     inliers.clear();
00206     Matrix<double,3,4> tfm;
00207     tfm.block<3,3>(0,0) = rot;
00208     tfm.col(3) = trans;
00209 
00210     nmatch = matches.size();
00211     for (int i=0; i<nmatch; i++)
00212       {
00213         if (!f0.goodPts[matches[i].queryIdx] || !f1.goodPts[matches[i].trainIdx])
00214           continue;
00215         Vector3d pt = tfm*f1.pts[matches[i].trainIdx];
00216         Vector3d ipt = f0.cam2pix(pt);
00217         const cv::KeyPoint &kp = f0.kpts[matches[i].queryIdx];
00218         double dx = kp.pt.x - ipt.x();
00219         double dy = kp.pt.y - ipt.y();
00220         double dd = f0.disps[matches[i].queryIdx] - ipt.z();
00221         if (dx*dx < maxInlierXDist2 && dy*dy < maxInlierXDist2 && 
00222             dd*dd < maxInlierDDist2)
00223           inls.push_back(matches[i]);
00224       }
00225 
00226 #if 0
00227     cout << endl << trans.transpose().head(3) << endl << endl;
00228     cout << rot << endl;
00229 #endif
00230 
00231     
00232     if (polish)
00233       {
00234         
00235         SysSBA sba;
00236         sba.verbose = 0;
00237 
00238         
00239         
00240         Vector4d v0 = Vector4d(0,0,0,1);
00241         Quaterniond q0 = Quaternion<double>(Vector4d(0,0,0,1));
00242         sba.addNode(v0, q0, f0.cam, true);
00243         
00244         Quaterniond qr1(rot);   
00245         Vector4d temptrans = Vector4d(trans(0), trans(1), trans(2), 1.0);
00246 
00247         
00248         qr1.normalize();
00249         sba.addNode(temptrans, qr1, f1.cam, false);
00250 
00251         int in = 3;
00252         if (in > (int)inls.size())
00253           in = inls.size();
00254 
00255         
00256         for (int i=0; i<(int)inls.size(); i++)
00257           {
00258             
00259             int i0 = inls[i].queryIdx;
00260             int i1 = inls[i].trainIdx;
00261             Vector4d pt = f0.pts[i0];
00262             sba.addPoint(pt);
00263             
00264             
00265             Vector3d ipt;
00266             ipt(0) = f0.kpts[i0].pt.x;
00267             ipt(1) = f0.kpts[i0].pt.y;
00268             ipt(2) = ipt(0)-f0.disps[i0];
00269             sba.addStereoProj(0, i, ipt);
00270 
00271             
00272             ipt(0) = f1.kpts[i1].pt.x;
00273             ipt(1) = f1.kpts[i1].pt.y;
00274             ipt(2) = ipt(0)-f1.disps[i1];
00275             sba.addStereoProj(1, i, ipt);
00276           }
00277 
00278         sba.huber = 2.0;
00279         sba.doSBA(5,10e-4,SBA_DENSE_CHOLESKY);
00280         int nbad = sba.removeBad(2.0);
00281 
00282         sba.doSBA(5,10e-5,SBA_DENSE_CHOLESKY);
00283 
00284 
00285 
00286         
00287               trans = sba.nodes[1].trans.head(3);
00288               Quaterniond q1;
00289               q1 = sba.nodes[1].qrot;
00290               rot = q1.toRotationMatrix();
00291 
00292         
00293         inliers.clear();
00294         for (int i=0; i<(int)inls.size(); i++)
00295           {
00296             ProjMap &prjs = sba.tracks[i].projections;
00297             if (prjs[0].isValid && prjs[1].isValid) 
00298               inliers.push_back(inls[i]);
00299           }
00300 #if 0
00301         printf("Inliers: %d   After polish: %d\n", (int)inls.size(), (int)inliers.size());
00302 #endif
00303       }
00304 
00305     return (int)inliers.size();
00306   }
00307 }