pnp_ransac.cpp
Go to the documentation of this file.
00001 #include "posest/pnp_ransac.h"
00002 #include <iostream>
00003 #include "tbb/parallel_for.h"
00004 #include "tbb/blocked_range.h"
00005 #include "tbb/task_scheduler_init.h"
00006 #include "tbb/mutex.h"
00007 
00008 using namespace std;
00009 using namespace cv;
00010 using namespace tbb;
00011 
00012 void project3dPoints(const vector<Point3f>& points, const Mat& rvec, const Mat& tvec, vector<Point3f>& modif_points)
00013 {
00014   modif_points.clear();
00015   modif_points.resize(points.size());
00016   Mat R(3, 3, CV_64FC1);
00017   Rodrigues(rvec, R);
00018   for (size_t i = 0; i < points.size(); i++)
00019   {
00020     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)
00021         * points[i].z + tvec.at<double> (0, 0);
00022     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)
00023         * points[i].z + tvec.at<double> (1, 0);
00024     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)
00025         * points[i].z + tvec.at<double> (2, 0);
00026   }
00027 }
00028 
00029 void generateVar(vector<char>& mask, RNG& rng)
00030 {
00031   size_t size = mask.size();
00032   for (size_t i = 0; i < size; i++)
00033   {
00034         int i1 = rng.uniform(0, size);
00035         int i2 = rng.uniform(0, size);
00036         char curr = mask[i1];
00037         mask[i1] = mask[i2];
00038         mask[i2] = curr;
00039   }
00040 }
00041 
00042 void pnpTask(const vector<char>& used_points_mask, const Mat& camera_matrix, const Mat& dist_coeffs,
00043                 const vector<Point3f>& object_points, const vector<Point2f>& image_points, vector<int>& inliers,
00044                 float max_dist, cv::Mat& rvec, cv::Mat& tvec, bool use_extrinsic_guess, const Mat& rvecInit,
00045                 const Mat& tvecInit, tbb::mutex& Mutex)
00046 {
00047   vector<Point3f> model_object_points;
00048   vector<Point2f> model_image_points;
00049   for (size_t i = 0; i < used_points_mask.size(); i++)
00050   {
00051     if (used_points_mask[i])
00052     {
00053       model_image_points.push_back(image_points[i]);
00054       model_object_points.push_back(object_points[i]);
00055     }
00056   }
00057 
00058   Mat rvecl, tvecl;
00059   rvecInit.copyTo(rvecl);
00060   tvecInit.copyTo(tvecl);
00061 
00062   //filter same 3d points, hang in solvePnP
00063   double eps = 1e-10;
00064   int num_same_points = 0;
00065   for (int i = 0; i < MIN_POINTS_COUNT; i++)
00066     for (int j = i + 1; j < MIN_POINTS_COUNT; j++)
00067       if (norm(model_object_points[i] - model_object_points[j]) < eps)
00068         num_same_points++;
00069   if (num_same_points > 0)
00070     return;
00071   
00072   solvePnP(Mat(model_object_points), Mat(model_image_points), camera_matrix, dist_coeffs, rvecl, tvecl, use_extrinsic_guess);
00073 
00074   vector<Point2f> projected_points;
00075   projected_points.resize(object_points.size());
00076   projectPoints(Mat(object_points), rvecl, tvecl, camera_matrix, dist_coeffs, projected_points);
00077 
00078   vector<Point3f> rotated_points;
00079   project3dPoints(object_points, rvecl, tvecl, rotated_points);
00080 
00081   vector<int> inliers_indexes;
00082   for (size_t i = 0; i < object_points.size(); i++)
00083   {
00084     if ((norm(image_points[i] - projected_points[i]) < max_dist) && (rotated_points[i].z > 0))
00085     {
00086       inliers_indexes.push_back(i);
00087     }
00088   }
00089 
00090   if (inliers_indexes.size() > inliers.size())
00091   {
00092     mutex::scoped_lock lock;
00093     lock.acquire(Mutex);
00094 
00095     inliers.clear();
00096     inliers.resize(inliers_indexes.size());
00097     memcpy(&inliers[0], &inliers_indexes[0], sizeof(int) * inliers_indexes.size());
00098     rvecl.copyTo(rvec);
00099     tvecl.copyTo(tvec);
00100 
00101     lock.release();
00102   }
00103 }
00104 void Iterate(const vector<Point3f>& object_points, const vector<Point2f>& image_points,
00105                 const Mat& camera_matrix, const Mat& dist_coeffs, Mat& rvec, Mat& tvec, const float max_dist, const int min_inlier_num,
00106                 vector<int>* inliers, bool use_extrinsic_guess, const Mat& rvecInit, const Mat& tvecInit, RNG& rng, tbb::mutex& Mutex)
00107 {
00108         vector<char> used_points_mask(object_points.size(), 0);
00109         memset(&used_points_mask[0], 1, MIN_POINTS_COUNT );
00110         generateVar(used_points_mask, rng);
00111         pnpTask(used_points_mask, camera_matrix, dist_coeffs, object_points, image_points,
00112                 *inliers, max_dist, rvec, tvec, use_extrinsic_guess, rvecInit, tvecInit, Mutex);
00113         if ((int)inliers->size() > min_inlier_num)
00114                 task::self().cancel_group_execution();
00115 }
00116 
00117 class Iterator
00118 {
00119         const vector<Point3f>* object_points;
00120         const vector<Point2f>* image_points;
00121         const Mat* camera_matrix;
00122         const Mat* dist_coeffs;
00123         Mat* resultRvec, rvecInit;
00124         Mat* resultTvec, tvecInit;
00125         const float max_dist;
00126         const int min_inlier_num;
00127         vector<int>* inliers;
00128         bool use_extrinsic_guess;
00129         RNG* rng;
00130         static mutex ResultsMutex;
00131 public:
00132     void operator()( const blocked_range<size_t>& r ) const {
00133         for( size_t i=r.begin(); i!=r.end(); ++i )
00134         {
00135                 Iterate(*object_points, *image_points, *camera_matrix, *dist_coeffs,
00136                         *resultRvec, *resultTvec, max_dist, min_inlier_num,
00137                         inliers, use_extrinsic_guess, rvecInit, tvecInit, *rng, ResultsMutex);
00138         }
00139     }
00140     Iterator(const vector<Point3f>* tobject_points, const vector<Point2f>* timage_points,
00141             const Mat* tcamera_matrix, const Mat* tdist_coeffs, Mat* rvec, Mat* tvec,
00142             float tmax_dist, int tmin_inlier_num, vector<int>* tinliers,
00143             bool tuse_extrinsic_guess, RNG* trng):
00144                 object_points(tobject_points), image_points(timage_points),
00145                 camera_matrix(tcamera_matrix), dist_coeffs(tdist_coeffs), resultRvec(rvec), resultTvec(tvec),
00146                 max_dist(tmax_dist), min_inlier_num(tmin_inlier_num), inliers(tinliers),
00147                 use_extrinsic_guess(tuse_extrinsic_guess), rng(trng)
00148     {
00149       resultRvec->copyTo(rvecInit);
00150       resultTvec->copyTo(tvecInit);
00151     }
00152 };
00153 mutex Iterator::ResultsMutex;
00154 
00155 bool solvePnPRansac(const vector<Point3f>& object_points, const vector<Point2f>& image_points,
00156                     const Mat& camera_matrix, const Mat& dist_coeffs, Mat& rvec, Mat& tvec, bool use_extrinsic_guess,
00157                     int num_iterations, float max_dist, int min_inlier_num, vector<int>* inliers)
00158 {
00159   assert(object_points.size() == image_points.size());
00160 
00161   if (object_points.size() < MIN_POINTS_COUNT)
00162     return false;
00163 
00164   if (!use_extrinsic_guess)
00165   {
00166     rvec.create(3, 1, CV_64FC1);
00167     tvec.create(3, 1, CV_64FC1);
00168   }
00169   else
00170   {
00171     assert(rvec.rows == 3);
00172     assert(tvec.rows == 3);
00173     assert(rvec.cols == 1);
00174     assert(tvec.cols == 1);
00175     assert(rvec.type() == CV_64FC1);
00176   }
00177 
00178   if (min_inlier_num == -1)
00179     min_inlier_num = object_points.size();
00180 
00181   vector<int> local_inliers;
00182   if (!inliers)
00183   {
00184     inliers = &local_inliers;
00185   }
00186 
00187   RNG rng;
00188   Mat rvecl(3, 1, CV_64FC1), tvecl(3, 1, CV_64FC1);
00189   rvec.copyTo(rvecl);
00190   tvec.copyTo(tvecl);
00191 
00192   task_scheduler_init TBBinit;
00193   parallel_for(blocked_range<size_t>(0,num_iterations), Iterator(&object_points, &image_points,
00194                &camera_matrix, &dist_coeffs, &rvecl, &tvecl, max_dist,
00195                min_inlier_num, inliers, use_extrinsic_guess, &rng));
00196 
00197   if ((int)(*inliers).size() >= MIN_POINTS_COUNT)
00198   {
00199     vector<Point3f> model_object_points;
00200     vector<Point2f> model_image_points;
00201     int index;
00202     for (size_t i = 0; i < (*inliers).size(); i++)
00203     {
00204       index = (*inliers)[i];
00205       model_image_points.push_back(image_points[index]);
00206       model_object_points.push_back(object_points[index]);
00207     }
00208     rvecl.copyTo(rvec);
00209     tvecl.copyTo(tvec);
00210     solvePnP(Mat(model_object_points), Mat(model_image_points), camera_matrix, dist_coeffs, rvec, tvec, true);
00211   }
00212   else
00213   {
00214     rvec.setTo(Scalar::all(0));
00215     tvec.setTo(Scalar::all(0));
00216     return false;
00217   }
00218   return true;
00219 }


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