peh.cpp
Go to the documentation of this file.
00001 #include <posest/peh.h>
00002 #include <sba/sba.h>
00003 #include <Eigen/SVD>
00004 #include <Eigen/LU>
00005 #include <iostream>
00006 #include <opencv2/core/core.hpp>
00007 #include <opencv2/features2d/features2d.hpp>
00008 
00009 using namespace Eigen;
00010 using namespace sba;
00011 using namespace frame_common;
00012 using namespace std;
00013 using namespace cv;
00014 
00015 namespace pe
00016 {
00017 
00018 void invert(Mat& rvec, Mat& tvec)
00019 {
00020   Mat R, RInv;
00021   Rodrigues(rvec, R);
00022   RInv = R.inv();
00023   Rodrigues(RInv, rvec);
00024   tvec = RInv * tvec;
00025   tvec = tvec * (-1);
00026 }
00027 
00028 int PoseEstimatorH::estimate(const Frame& frame1, const Frame& frame2)
00029 {
00030   matches.clear();
00031   inliers.clear();
00032 
00033   Mat mask;
00034   if (windowed)
00035     mask = cv::windowedMatchingMask(frame1.kpts, frame2.kpts, wx, wy);
00036   howardMatcher->match(frame1, frame2, matches, filteredIndices, mask);
00037   return estimate(frame1, frame2, matches);
00038 }
00039 
00040 void project3dPoints(const vector<Point3f>& points, const Mat& rvec, const Mat& tvec, vector<Point3f>& modif_points)
00041 {
00042   modif_points.clear();
00043   modif_points.resize(points.size());
00044   Mat R(3, 3, CV_64FC1);
00045   Rodrigues(rvec, R);
00046   for (size_t i = 0; i < points.size(); i++)
00047   {
00048     modif_points[i].x = R.at<double> (0, 0) * points[i].x + R.at<double> (0, 1) * points[i].y + R.at<double> (0, 2)
00049         * points[i].z + tvec.at<double> (0, 0);
00050     modif_points[i].y = R.at<double> (1, 0) * points[i].x + R.at<double> (1, 1) * points[i].y + R.at<double> (1, 2)
00051         * points[i].z + tvec.at<double> (1, 0);
00052     modif_points[i].z = R.at<double> (2, 0) * points[i].x + R.at<double> (2, 1) * points[i].y + R.at<double> (2, 2)
00053         * points[i].z + tvec.at<double> (2, 0);
00054   }
00055 }
00056 
00057 int PoseEstimatorH::estimate(const Frame& f0, const Frame& f1, const std::vector<cv::DMatch> &peMatches)
00058 {
00059   int nmatch = (int)peMatches.size();
00060   //cout << "Filtered matches size = " << filteredIndices.size() << endl;
00061   std::vector<cv::DMatch> matches;
00062 
00063   for (size_t i = 0; i < filteredIndices.size(); i++)
00064   {
00065     if (f0.disps[peMatches[filteredIndices[i]].queryIdx] > minMatchDisp
00066         && f1.disps[peMatches[filteredIndices[i]].trainIdx] > minMatchDisp)
00067     {
00068       if (f0.goodPts[peMatches[filteredIndices[i]].queryIdx] && f1.goodPts[peMatches[filteredIndices[i]].trainIdx])
00069         matches.push_back(peMatches[filteredIndices[i]]);
00070     }
00071   }
00072   //cout << "Matches size after disparity filtering = " << matches.size() << endl;
00073   vector<Point3f> opoints;
00074   vector<Point3f> opointsFrame2;
00075   vector<Point2f> ipoints;
00076   vector<cv::DMatch> inls;
00077   vector<int> indices;
00078 
00079   for (size_t i = 0; i < matches.size(); ++i)
00080   {
00081     if (f0.goodPts[matches[i].queryIdx] && f1.goodPts[matches[i].trainIdx])
00082     {
00083       ipoints.push_back(f1.kpts[matches[i].trainIdx].pt);
00084       Eigen::Vector4d vec = f0.pts[matches[i].queryIdx];
00085       Point3f op(vec(0), vec(1), vec(2));
00086       opoints.push_back(op);
00087 
00088       Eigen::Vector4d vec2 = f1.pts[matches[i].trainIdx];
00089       Point3f op2(vec2(0), vec2(1), vec2(2));
00090       opointsFrame2.push_back(op2);
00091 
00092       indices.push_back(i);
00093     }
00094   }
00095 
00096   bool matched = (int)matches.size() > minMatchesCount;
00097 
00098 #if 0
00099   if (matched)
00100   {
00101     cout << "Clique matches size = " << ipoints.size() << endl;
00102     Mat rvec, tvec;
00103     Mat intrinsic = Mat::zeros(Size(3, 3), CV_64F);
00104     intrinsic.at<double>(0, 0) = f1.cam.fx;
00105     intrinsic.at<double>(0, 2) = f1.cam.cx;
00106     intrinsic.at<double>(1, 1) = f1.cam.fy;
00107     intrinsic.at<double>(1, 2) = f1.cam.cy;
00108     intrinsic.at<double>(2, 2) = 1.0;
00109     solvePnP(Mat(opoints), Mat(ipoints), intrinsic, Mat::zeros(Size(1, 5), CV_64F), rvec, tvec, false);
00110     vector<Point2f> projectedPoints;
00111     projectPoints(Mat(opoints), rvec, tvec, intrinsic, Mat::zeros(Size(1, 5), CV_64F), projectedPoints);
00112 
00113     vector<Point3f> inliersOpoints;
00114     vector<Point2f> inliersIpoints;
00115     for (size_t pointInd = 0; pointInd < projectedPoints.size(); pointInd++)
00116     {
00117       double dx = ipoints[pointInd].x - projectedPoints[pointInd].x;
00118       double dy = ipoints[pointInd].y - projectedPoints[pointInd].y;
00119       double dd = f1.disps[matches[indices[pointInd]].trainIdx] - f1.cam.fx*f1.cam.tx/opoints[pointInd].z;
00120 
00121       if (dx*dx < maxInlierXDist2 && dy*dy < maxInlierXDist2 &&
00122           dd*dd < maxInlierDDist2 && norm(projectedPoints[pointInd] - ipoints[pointInd]) < 1.)
00123       {
00124         inliersIpoints.push_back(ipoints[pointInd]);
00125         inliersOpoints.push_back(opoints[pointInd]);
00126       }
00127     }
00128     cout << "Inliers matches size = " << inliersIpoints.size() << endl;
00129 
00130     if (inliersIpoints.size() > 5)
00131     {
00132       solvePnP(Mat(inliersOpoints), Mat(inliersIpoints), intrinsic, Mat::zeros(Size(1, 5), CV_64F), rvec, tvec, true);
00133       projectedPoints.clear();
00134       projectPoints(Mat(inliersOpoints), rvec, tvec, intrinsic, Mat::zeros(Size(1, 5), CV_64F), projectedPoints);
00135 
00136       float reprojectionError = 0.0;
00137       float avgReprojectionError = 0.0;
00138       for (size_t pointInd = 0; pointInd < projectedPoints.size(); pointInd++)
00139       {
00140         float error = norm(projectedPoints[pointInd] - inliersIpoints[pointInd]);
00141         avgReprojectionError += error;
00142         if (error > reprojectionError)
00143         {
00144           reprojectionError = error;
00145         }
00146       }
00147       avgReprojectionError /= projectedPoints.size();
00148       cout << "Reprojection error = " << reprojectionError << ", avg = " << avgReprojectionError << endl;
00149     }
00150     else
00151     {
00152       inls.clear();
00153       matched = false;
00154     }
00155 
00156     if (matched)
00157     {
00158       vector<Point3f> mopoints;
00159       vector<Point2f> mipoints;
00160       vector<int> mindices;
00161       for (size_t i = 0; i < peMatches.size(); ++i)
00162       {
00163         if (f0.goodPts[peMatches[i].queryIdx] && f1.goodPts[peMatches[i].trainIdx])
00164         {
00165           mipoints.push_back(f1.kpts[peMatches[i].trainIdx].pt);
00166           Eigen::Vector4d vec = f0.pts[peMatches[i].queryIdx];
00167           Point3f op(vec(0), vec(1), vec(2));
00168           mopoints.push_back(op);
00169           mindices.push_back(i);
00170         }
00171       }
00172       vector<Point2f> mprojectedPoints;
00173       projectPoints(Mat(mopoints), rvec, tvec, intrinsic, Mat::zeros(Size(1, 5), CV_64F), mprojectedPoints);
00174       for (size_t pointInd = 0; pointInd < mprojectedPoints.size(); pointInd++)
00175       {
00176         double dx = mipoints[pointInd].x - mprojectedPoints[pointInd].x;
00177         double dy = mipoints[pointInd].y - mprojectedPoints[pointInd].y;
00178         double dd = f1.disps[peMatches[mindices[pointInd]].trainIdx] - f1.cam.fx*f1.cam.tx/mopoints[pointInd].z;
00179 
00180         if (dx*dx < maxInlierXDist2 && dy*dy < maxInlierXDist2 &&
00181             dd*dd < maxInlierDDist2)
00182         {
00183           inls.push_back(peMatches[mindices[pointInd]]);
00184         }
00185       }
00186       cout << "inls size = " << inls.size() << endl;
00187 
00188       if (norm(tvec) > 1.0)
00189       {
00190         cout << "*****************************************************************" << endl;
00191         cout << endl << endl << "Removed from tvec!!!!" << endl << endl;
00192         cout << "*****************************************************************" << endl;
00193         inls.clear();
00194         return 0;
00195       }
00196 
00197       invert(rvec, tvec);
00198       Mat R;
00199       cv::Rodrigues(rvec, R);
00200       Matrix3d R2;
00201       Vector3d tr;
00202       R2 << R.at<double>(0,0), R.at<double>(0,1), R.at<double>(0,2),
00203       R.at<double>(1,0), R.at<double>(1,1), R.at<double>(1,2),
00204       R.at<double>(2,0), R.at<double>(2,1), R.at<double>(2,2);
00205       tr << tvec.at<double>(0,0), tvec.at<double>(0,1), tvec.at<double>(0,2);
00206       rot = R2;
00207       trans = tr;
00208       inliers = inls;
00209       return inliers.size();
00210     }
00211     else
00212       return 0;
00213   }
00214 #endif
00215 
00216 #if 0
00217   if (matched)
00218   {
00219     int bestinl = 0;
00220     cout << "RANSAC iterations count = " << numRansac << endl;
00221     for (int iter = 0; iter < numRansac; iter++)
00222     {
00223       vector<int> randomIndices(3);
00224       randomIndices[0] = rand() % opoints.size();
00225       randomIndices[1] = randomIndices[0];
00226       while (randomIndices[0] == randomIndices[1])
00227         randomIndices[1] = rand() % opoints.size();
00228       randomIndices[2] = randomIndices[0];
00229       while (randomIndices[0] == randomIndices[2] || randomIndices[1] == randomIndices[2])
00230         randomIndices[2] = rand() % opoints.size();
00231 
00232       vector<Vector3d> pointsFrame0(randomIndices.size()), pointsFrame1(randomIndices.size());
00233       Vector3d c0, c1;
00234       for (size_t pointInd = 0; pointInd < randomIndices.size(); pointInd++)
00235       {
00236         Vector3d pf0(opoints[randomIndices[pointInd]].x, opoints[randomIndices[pointInd]].y, opoints[randomIndices[pointInd]].z);
00237         pointsFrame0[pointInd] = pf0;
00238         Vector3d pf1(opointsFrame2[randomIndices[pointInd]].x, opointsFrame2[randomIndices[pointInd]].y,
00239                      opointsFrame2[randomIndices[pointInd]].z);
00240         pointsFrame1[pointInd] = pf1;
00241         c0 += pf0;
00242         c1 += pf1;
00243       }
00244 
00245       c0 *= 1.0 / randomIndices.size();
00246       c1 *= 1.0 / randomIndices.size();
00247 
00248       Matrix3d H;
00249       H << 0, 0, 0, 0, 0, 0, 0, 0, 0;
00250       for (size_t pointInd = 0; pointInd < pointsFrame0.size(); pointInd++)
00251       {
00252         pointsFrame0[pointInd] -= c0;
00253         pointsFrame1[pointInd] -= c1;
00254         H += pointsFrame1[pointInd] * pointsFrame0[pointInd].transpose();
00255       }
00256       JacobiSVD<Matrix3d> svd(H, ComputeFullU | ComputeFullV);
00257       Matrix3d V = svd.matrixV();
00258       Matrix3d R = V * svd.matrixU().transpose();
00259       double det = R.determinant();
00260       if (det < 0.0)
00261       {
00262         //nneg++;
00263         V.col(2) = V.col(2) * -1.0;
00264         R = V * svd.matrixU().transpose();
00265       }
00266       Vector3d tr = c0 - R * c1; // translation
00267 
00268       // transformation matrix, 3x4
00269       Matrix<double, 3, 4> tfm;
00270       tfm.block<3, 3> (0, 0) = R;
00271       tfm.col(3) = tr;
00272       // find inliers, based on image reprojection
00273       int inl = 0;
00274       for (int i = 0; i < peMatches.size(); i++)
00275       {
00276         Vector3d pt = tfm * f1.pts[peMatches[i].trainIdx];
00277         Vector3d ipt = f0.cam2pix(pt);
00278         const cv::KeyPoint &kp = f0.kpts[peMatches[i].queryIdx];
00279         double dx = kp.pt.x - ipt.x();
00280         double dy = kp.pt.y - ipt.y();
00281         double dd = f0.disps[peMatches[i].queryIdx] - ipt.z();
00282         if (dx * dx < maxInlierXDist2 && dy * dy < maxInlierXDist2 && dd * dd < maxInlierDDist2)
00283           if (f0.goodPts[peMatches[i].queryIdx] && f1.goodPts[peMatches[i].trainIdx])
00284             inl += (int)sqrt(ipt.z()); // clever way to weight closer points
00285         //              inl++;
00286       }
00287 
00288 #pragma omp critical
00289       if (inl > bestinl)
00290       {
00291         //cout << "1 - 2 " << abs(norm(opoints[randomIndices[0]] - opoints[randomIndices[1]]) - norm(opointsFrame2[randomIndices[0]] - opointsFrame2[randomIndices[1]])) << endl;
00292         //cout << "1 - 3 " << abs(norm(opoints[randomIndices[0]] - opoints[randomIndices[2]]) - norm(opointsFrame2[randomIndices[0]] - opointsFrame2[randomIndices[2]])) << endl;
00293         //cout << "2 - 3 " << abs(norm(opoints[randomIndices[1]] - opoints[randomIndices[2]]) - norm(opointsFrame2[randomIndices[1]] - opointsFrame2[randomIndices[2]])) << endl;
00294         bestinl = inl;
00295         rot = R;
00296         trans = tr;
00297       }
00298     }
00299 
00300     inliers.clear();
00301     inls.clear();
00302     Matrix<double,3,4> tfm;
00303     tfm.block<3,3>(0,0) = rot;
00304     tfm.col(3) = trans;
00305     for (int i=0; i<peMatches.size(); i++)
00306     {
00307       Vector3d pt = tfm*f1.pts[peMatches[i].trainIdx];
00308       Vector3d ipt = f0.cam2pix(pt);
00309       const cv::KeyPoint &kp = f0.kpts[peMatches[i].queryIdx];
00310       double dx = kp.pt.x - ipt.x();
00311       double dy = kp.pt.y - ipt.y();
00312       double dd = f0.disps[peMatches[i].queryIdx] - ipt.z();
00313       if (dx*dx < maxInlierXDist2 && dy*dy < maxInlierXDist2 &&
00314           dd*dd < maxInlierDDist2)
00315       {
00316         if (f0.goodPts[peMatches[i].queryIdx] && f1.goodPts[peMatches[i].trainIdx])
00317           inls.push_back(peMatches[i]);
00318       }
00319     }
00320     inliers = inls;
00321     cout << "Found " << inls.size() << " inliers" << endl;
00322   }
00323 #endif
00324 
00325 #if 1
00326   if (matched)
00327     {
00328         cout << "Clique size = " << opoints.size() << endl;
00329         vector<Vector3d> pointsFrame0(opoints.size()), pointsFrame1(opoints.size());
00330         Vector3d c0, c1;
00331         for (size_t pointInd = 0; pointInd < opoints.size(); pointInd++)
00332         {
00333           Vector3d pf0(opoints[pointInd].x, opoints[pointInd].y, opoints[pointInd].z);
00334           pointsFrame0[pointInd] = pf0;
00335           Vector3d pf1(opointsFrame2[pointInd].x, opointsFrame2[pointInd].y, opointsFrame2[pointInd].z);
00336           pointsFrame1[pointInd] = pf1;
00337           c0 += pf0;
00338           c1 += pf1;
00339         }
00340         c0 *= 1.0/opoints.size();
00341         c1 *= 1.0/opoints.size();
00342 
00343         Matrix3d H;
00344         H << 0, 0, 0,
00345         0, 0, 0,
00346         0, 0, 0;
00347         for (size_t pointInd = 0; pointInd < pointsFrame0.size(); pointInd++)
00348         {
00349           pointsFrame0[pointInd] -= c0;
00350           pointsFrame1[pointInd] -= c1;
00351           H += pointsFrame1[pointInd]*pointsFrame0[pointInd].transpose();
00352         }
00353         JacobiSVD<Matrix3d> svd(H, ComputeFullU | ComputeFullV);
00354         Matrix3d V = svd.matrixV();
00355         Matrix3d R = V * svd.matrixU().transpose();
00356         double det = R.determinant();
00357         if (det < 0.0)
00358         {
00359           V.col(2) = V.col(2)*-1.0;
00360           R = V * svd.matrixU().transpose();
00361         }
00362         Vector3d tr = c0-R*c1; // translation
00363         // transformation matrix, 3x4
00364         Matrix<double,3,4> tfm;
00365         tfm.block<3,3>(0,0) = R;
00366         tfm.col(3) = tr;
00367 
00368         // find inliers, based on image reprojection
00369         vector<DMatch>::iterator m;
00370         for (m = matches.begin(); m != matches.end(); )
00371         {
00372           Vector3d pt = tfm*f1.pts[(*m).trainIdx];
00373           Vector3d ipt = f0.cam2pix(pt);
00374           const cv::KeyPoint &kp = f0.kpts[(*m).queryIdx];
00375           double dx = kp.pt.x - ipt.x();
00376           double dy = kp.pt.y - ipt.y();
00377           double dd = f0.disps[(*m).queryIdx] - ipt.z();
00378           bool condition = dx * dx < maxInlierXDist2 && dy * dy < maxInlierXDist2 && dd * dd < maxInlierDDist2;
00379           if (!condition)
00380           {
00381             m = matches.erase(m);
00382           }
00383           else
00384           {
00385             m++;
00386           }
00387         }
00388 
00389         ipoints.clear();
00390         opoints.clear();
00391         opointsFrame2.clear();
00392         indices.clear();
00393         for (size_t i = 0; i < matches.size(); ++i)
00394         {
00395           ipoints.push_back(f1.kpts[matches[i].trainIdx].pt);
00396           Eigen::Vector4d vec = f0.pts[matches[i].queryIdx];
00397           Point3f op(vec(0), vec(1), vec(2));
00398           opoints.push_back(op);
00399 
00400           Eigen::Vector4d vec2 = f1.pts[matches[i].trainIdx];
00401           Point3f op2(vec2(0), vec2(1), vec2(2));
00402           opointsFrame2.push_back(op2);
00403 
00404           indices.push_back(i);
00405         }
00406         cout << "Clique size after filtering using found transformation matrix = " << opoints.size() << endl;
00407         if (opoints.size() < 5)
00408           return 0;
00409         pointsFrame0.resize(opoints.size());
00410         pointsFrame1.resize(opoints.size());
00411         c0 = Vector3d(0, 0, 0);
00412         c1 = Vector3d(0, 0, 0);
00413         for (size_t pointInd = 0; pointInd < opoints.size(); pointInd++)
00414         {
00415           Vector3d pf0(opoints[pointInd].x, opoints[pointInd].y, opoints[pointInd].z);
00416           pointsFrame0[pointInd] = pf0;
00417           Vector3d pf1(opointsFrame2[pointInd].x, opointsFrame2[pointInd].y, opointsFrame2[pointInd].z);
00418           pointsFrame1[pointInd] = pf1;
00419           c0 += pf0;
00420           c1 += pf1;
00421         }
00422         c0 *= 1.0/opoints.size();
00423         c1 *= 1.0/opoints.size();
00424 
00425         H << 0, 0, 0,
00426         0, 0, 0,
00427         0, 0, 0;
00428         for (size_t pointInd = 0; pointInd < pointsFrame0.size(); pointInd++)
00429         {
00430           pointsFrame0[pointInd] -= c0;
00431           pointsFrame1[pointInd] -= c1;
00432           H += pointsFrame1[pointInd]*pointsFrame0[pointInd].transpose();
00433         }
00434         JacobiSVD<Matrix3d> svdR(H, ComputeFullU | ComputeFullV);
00435         V = svdR.matrixV();
00436         R = V * svdR.matrixU().transpose();
00437         det = R.determinant();
00438         if (det < 0.0)
00439         {
00440           V.col(2) = V.col(2)*-1.0;
00441           R = V * svdR.matrixU().transpose();
00442         }
00443         tr = c0-R*c1; // translation
00444         tfm.block<3,3>(0,0) = R;
00445         tfm.col(3) = tr;
00446 
00447 
00448         // find inliers, based on image reprojection
00449         inls.clear();
00450         for (int i=0; i<nmatch; i++)
00451         {
00452           Vector3d pt = tfm*f1.pts[peMatches[i].trainIdx];
00453           Vector3d ipt = f0.cam2pix(pt);
00454           const cv::KeyPoint &kp = f0.kpts[peMatches[i].queryIdx];
00455           double dx = kp.pt.x - ipt.x();
00456           double dy = kp.pt.y - ipt.y();
00457           double dd = f0.disps[peMatches[i].queryIdx] - ipt.z();
00458           if (dx*dx < maxInlierXDist2 && dy*dy < maxInlierXDist2 &&
00459               dd*dd < maxInlierDDist2)
00460           {
00461             if (f0.goodPts[peMatches[i].queryIdx] && f1.goodPts[peMatches[i].trainIdx])
00462               inls.push_back(peMatches[i]);
00463           }
00464         }
00465         rot = R;
00466         trans = tr;
00467         inliers = inls;
00468         cout << "Found " << inls.size() << " inliers" << endl;
00469     }
00470 #endif
00471 
00472   if (polish)
00473   {
00474     SysSBA sba;
00475     sba.verbose = 0;
00476 
00477     // set up nodes
00478     // should have a frame => node function
00479     Vector4d v0 = Vector4d(0, 0, 0, 1);
00480     Quaterniond q0 = Quaternion<double> (Vector4d(0, 0, 0, 1));
00481     sba.addNode(v0, q0, f0.cam, true);
00482 
00483     Quaterniond qr1(rot); // from rotation matrix
00484     Vector4d temptrans = Vector4d(trans(0), trans(1), trans(2), 1.0);
00485 
00486     //        sba.addNode(temptrans, qr1.normalized(), f1.cam, false);
00487     qr1.normalize();
00488     sba.addNode(temptrans, qr1, f1.cam, false);
00489 
00490     int in = 3;
00491     if (in > (int)inls.size())
00492       in = inls.size();
00493 
00494     for (int i = 0; i < (int)inls.size(); i++)
00495     {
00496       int i0 = inls[i].queryIdx;
00497       int i1 = inls[i].trainIdx;
00498       Vector4d pt = f0.pts[i0];
00499       sba.addPoint(pt);
00500 
00501       Vector3d ipt;
00502       ipt(0) = f0.kpts[i0].pt.x;
00503       ipt(1) = f0.kpts[i0].pt.y;
00504       ipt(2) = ipt(0) - f0.disps[i0];
00505 
00506       sba.addStereoProj(0, i, ipt);
00507 
00508       ipt(0) = f1.kpts[i1].pt.x;
00509       ipt(1) = f1.kpts[i1].pt.y;
00510       ipt(2) = ipt(0) - f1.disps[i1];
00511       sba.addStereoProj(1, i, ipt);
00512     }
00513 
00514     sba.huber = 2.0;
00515     sba.doSBA(5, 10e-4, SBA_DENSE_CHOLESKY);
00516     sba.removeBad(2.0);
00517 
00518     sba.doSBA(5, 10e-5, SBA_DENSE_CHOLESKY);
00519 
00520     trans = sba.nodes[1].trans.head(3);
00521     Quaterniond q1;
00522     q1 = sba.nodes[1].qrot;
00523     rot = q1.toRotationMatrix();
00524 
00525     inliers.clear();
00526     for (int i = 0; i < (int)inls.size(); i++)
00527     {
00528       ProjMap &prjs = sba.tracks[i].projections;
00529       if (prjs[0].isValid && prjs[1].isValid) // valid track
00530         inliers.push_back(inls[i]);
00531     }
00532 #if 0
00533     cout << "Inliers: " << inls.size() << ", after polish: " << inliers.size() << endl;
00534 #endif
00535     return inliers.size();
00536   }
00537   return inliers.size();
00538 }
00539 } // ends namespace pe


posest
Author(s): Kurt Konolige
autogenerated on Thu Jan 2 2014 12:12:17