simulated.cpp
Go to the documentation of this file.
00001 /*
00002  *  main.cpp
00003  *  outlet_detection
00004  *
00005  *  Created by Victor  Eruhimov on 4/16/10.
00006  *  Copyright 2010 Argus Corp. All rights reserved.
00007  *
00008  */
00009 
00010 
00011 #include "posest/planarSFM.h"
00012 #include <iostream>
00013 #include <numeric>
00014 #include <functional>
00015 #include <stdio.h>
00016 #include <posest/test/simulated.h>
00017 
00018 using namespace cv;
00019 
00020 namespace pe
00021 {
00022 
00023 void test()
00024 {
00025     vector<Point2f> points1, points2;
00026 
00027     points1.resize(6);
00028     points2.resize(6);
00029 
00030     points1[0] = Point2f(0, 0);
00031     points1[1] = Point2f(0, 1);
00032     points1[2] = Point2f(1, 0);
00033     points1[3] = Point2f(1, 1);
00034     points1[4] = Point2f(3, 0);
00035     points1[5] = Point2f(3, 1);
00036 
00037     points2 = points1;
00038 
00039     Mat H = findHomography(Mat(points1), Mat(points2), CV_RANSAC);
00040 
00041     for(int i = 0; i < 3; i++)
00042         for(int j = 0; j < 3; j++)
00043             printf("%f ", H.at<float>(i, j));
00044 
00045 }
00046 
00047 void generatePlanarObject(vector<Point3f>& points, Point3f N, float d)
00048 {
00049     // choose normal
00050 //    Point3f N(0, 0, 1);//(1.0f - 2*float(rand())/RAND_MAX, 1.0f - 2*float(rand())/RAND_MAX, float(rand())/RAND_MAX);
00051 //    float d = 10.0f;
00052 
00053     // generate points such that N*p - d = 0
00054     Point3f N0 = N*(d/norm(N));
00055     for(size_t i = 0; i < points.size(); i++)
00056     {
00057         Point3f p(float(rand())/RAND_MAX, float(rand())/RAND_MAX, float(rand())/RAND_MAX);
00058         Point3f p_plane = crossProduct(p, N);
00059         points[i] = p_plane + N0;
00060     }
00061 }
00062 
00063 void generatePlanarObject(vector<Point3f>& points, Point3f v1, Point3f v2, Vec2f limits1, Vec2f limits2, Point3f t)
00064 {
00065   for(size_t i = 0; i < points.size(); i++)
00066   {
00067     float scale1 = float(rand())/RAND_MAX*(limits1[1] - limits1[0]) + limits1[0];
00068     float scale2 = float(rand())/RAND_MAX*(limits2[1] - limits2[0]) + limits2[0];
00069     points[i] = v1*scale1 + v2*scale2 + t;
00070   }
00071 }
00072 
00073 // generate points in a cube
00074 void generate3DPointCloud(vector<Point3f>& points, Point3f pmin, Point3f pmax)
00075 {
00076     const Point3f delta = pmax - pmin;
00077     for(size_t i = 0; i < points.size(); i++)
00078     {
00079         Point3f p(float(rand())/RAND_MAX, float(rand())/RAND_MAX, float(rand())/RAND_MAX);
00080         p.x *= delta.x;
00081         p.y *= delta.y;
00082         p.z *= delta.z;
00083         p = p + pmin;
00084 
00085         points[i] = p;
00086     }
00087 }
00088 
00089 void addPointNoise(vector<Point2f>& points, double sigma = 3.0)
00090 {
00091     RNG rng(1);
00092     for(size_t i = 0; i < points.size(); i++)
00093     {
00094         points[i].x += 2*rand()*sigma/RAND_MAX - sigma;
00095         points[i].y += 2*rand()*sigma/RAND_MAX - sigma;
00096     }
00097 }
00098 
00099 void addLinkNoise(vector<int>& indices, double ratio = 0.05)
00100 {
00101     const int count = int(indices.size()*ratio/2);
00102     for(size_t i = 0; i < count; i++)
00103     {
00104         int index1 = rand()%indices.size();
00105         int index2 = rand()%indices.size();
00106         std::swap(indices[index1], indices[index2]);
00107     }
00108 }
00109 
00110 void addLinkNoise(vector<cv::DMatch>& indices, double ratio)
00111 {
00112     const int count = int(indices.size()*ratio/2);
00113     for(size_t i = 0; i < count; i++)
00114     {
00115         int index1 = rand()%indices.size();
00116         int index2 = rand()%indices.size();
00117         std::swap(indices[index1].trainIdx, indices[index2].trainIdx);
00118     }
00119 }
00120 
00121 void generateIntrinsics(Mat& intrinsics)
00122 {
00123   intrinsics = Mat::eye(3, 3, CV_32F);
00124   intrinsics.at<float>(0, 0) = 400.0;
00125   intrinsics.at<float>(1, 1) = 400.0;
00126   intrinsics.at<float>(0, 2) = 640/2;
00127   intrinsics.at<float>(1, 2) = 480/2;
00128 }
00129 
00130 void generateData(Mat& intrinsics, Mat& R, Mat& T, vector<KeyPoint>& points1, vector<KeyPoint>& points2, vector<int>& indices, vector<Point3f>& points)
00131 {
00132 //    test();
00133 
00134     Mat rvec1 = Mat::zeros(3, 1, CV_32F);
00135     Mat tvec1 = Mat::zeros(3, 1, CV_32F);
00136     Mat rvec2 = Mat::zeros(3, 1, CV_32F);
00137     Mat tvec2 = Mat::zeros(3, 1, CV_32F);
00138     tvec2.at<float>(0, 0) = 1.0f;
00139     rvec2.at<float>(0, 0) = 0.0f;
00140     tvec2.at<float>(1, 0) = 0.0f;
00141     generateIntrinsics(intrinsics);
00142     Mat dist_coeffs = Mat::zeros(5, 1, CV_32F);
00143 
00144     vector<Point3f> planarPoints, pointCloud;
00145     planarPoints.resize(100);
00146     generatePlanarObject(planarPoints);
00147     pointCloud.resize(500);
00148     generate3DPointCloud(pointCloud);
00149 
00150     points = planarPoints;
00151     points.insert(points.end(), pointCloud.begin(), pointCloud.end());
00152 
00153     points1.resize(points.size());
00154     points2.resize(points.size());
00155     vector<Point2f> _points1, _points2;
00156     _points1.resize(points.size());
00157     _points2.resize(points.size());
00158 
00159     projectPoints(Mat(points), rvec1, tvec1, intrinsics, dist_coeffs, _points1);
00160     projectPoints(Mat(points), rvec2, tvec2, intrinsics, dist_coeffs, _points2);
00161 
00162     addPointNoise(_points1, 2.0);
00163     addPointNoise(_points2, 2.0);
00164 
00165     indices.resize(points.size());
00166 
00167     for(size_t i = 0; i < points1.size(); i++)
00168     {
00169         points1[i].pt = _points1[i];
00170         points2[i].pt = _points2[i];
00171         indices[i] = (int)i;
00172 
00173 //        printf("point %d: %f %f %f\n", points[i].x, points[i].y, points[i].z);
00174     }
00175 
00176 //    addLinkNoise(indices, 0.05);
00177 
00178     vector<Point2f> _final1, _final2;
00179     keyPoints2Point2f(points1, _final1);
00180     keyPoints2Point2f(points2, _final2);
00181 
00182     Rodrigues(rvec2, R);
00183     T = tvec2;
00184     Mat E = calcEssentialMatrix(intrinsics.inv(), R, tvec2);
00185     double error = avgSampsonusError(E, _final1, _final2);//_points1, _points2);
00186     printf("Initial epipolar error: %f\n", error);
00187 }
00188 
00189 void testReprojectPoints()
00190 {
00191     Mat intrinsics, R, T;
00192     vector<KeyPoint> _points1, _points2;
00193     vector<int> indices;
00194     vector<Point3f> points;
00195 
00196     generateData(intrinsics, R, T, _points1, _points2, indices, points);
00197 
00198     vector<Point2f> points1, points2;
00199     matchesFromIndices(_points1, _points2, indices, points1, points2);
00200 
00201     vector<Point3f> _points;
00202     vector<bool> valid;
00203     reprojectPoints(intrinsics, R, T, points1, points2, _points, valid);
00204     float dist = norm(Mat(points) - Mat(_points))/sqrt(double(points.size()));
00205 
00206     for(size_t i = 0; i < points.size(); i++)
00207     {
00208         printf("%d %f\n", i, norm(points[i] - _points[i]));
00209     }
00210     printf("%f %f %f | %f %f %f\n", points[0].x, points[0].y, points[0].z, _points[0].x, _points[0].y, _points[0].z);
00211     printf("reprojectPoints test: error is %f\n", dist);
00212 }
00213 
00214 void generateProjections(const Mat& intrinsics, const Mat& rvec, const Mat& tvec, const vector<Point3f>& cloud, vector<KeyPoint>& keypoints)
00215 {
00216   Mat distCoeffs = Mat::zeros(5, 1, CV_32F);
00217   vector<Point2f> imagePoints;
00218   imagePoints.resize(cloud.size());
00219   projectPoints(Mat(cloud), rvec, tvec, intrinsics, distCoeffs, imagePoints);
00220 
00221   for(size_t i = 0; i < imagePoints.size(); i++)
00222   {
00223     keypoints.push_back(KeyPoint(imagePoints[i], 1.0f));
00224   }
00225 }
00226 
00227 void applyRT(const Mat& R, const Mat& T, const vector<Point3f>& points, vector<Point3f>& pointsRT)
00228 {
00229   Point3f t = T.at<Point3f>(0, 0);
00230   pointsRT.resize(points.size());
00231   for(size_t i = 0; i < points.size(); i++)
00232   {
00233     Point3f p = mult(R, points[i]);
00234     p = p + t;
00235     pointsRT[i] = p;
00236 
00237 //    printf("%f %f %f %f %f %f\n", points[i].x, points[i].y, points[i].z, pointsRT[i].x, pointsRT[i].y, pointsRT[i].z);
00238   }
00239 }
00240 
00241 void calcVisible(const Mat& intrinsics, const Mat& R, const Mat& T,
00242         const vector<Point3f>& objectPoints, const vector<cv::KeyPoint>& imagePoints, vector<int>& visible)
00243 {
00244   visible.resize(imagePoints.size());
00245   vector<Point3f> cloudRT;
00246   applyRT(R, T, objectPoints, cloudRT);
00247 
00248   float cx = intrinsics.at<float>(0, 2);
00249   float cy = intrinsics.at<float>(1, 2);
00250 
00251   for(size_t i = 0; i < visible.size(); i++)
00252   {
00253     Point2f p = imagePoints[i].pt;
00254     if(cloudRT[i].z < 0 || p.x < 0 || p.y < 0 || p.x > 2*cx || p.y > 2*cy)
00255     {
00256       visible[i] = 0;
00257     }
00258     else
00259     {
00260       visible[i] = 1;
00261     }
00262 
00263 //    printf("point %f %f %f, projection %f %f, visible %d\n",
00264 //           objectPoints[i].x, objectPoints[i].y, objectPoints[i].z, p.x, p.y, visible[i]);
00265   }
00266 }
00267 
00268 void generateCube(std::vector<cv::Point3f>& cloud)
00269 {
00270   const int facetCount = 10000;
00271   std::vector<cv::Point3f> facet;
00272   facet.resize(facetCount);
00273 
00274   Vec2f limits(-1, 1);
00275   pe::generatePlanarObject(facet, Point3f(1, 0, 0), Point3f(0, 0, 1), limits, limits, Point3f(0, 1, 0));
00276   cloud.insert(cloud.end(), facet.begin(), facet.end());
00277   pe::generatePlanarObject(facet, Point3f(1, 0, 0), Point3f(0, 0, 1), limits, limits, Point3f(0, -1, 0));
00278   cloud.insert(cloud.end(), facet.begin(), facet.end());
00279   pe::generatePlanarObject(facet, Point3f(1, 0, 0), Point3f(0, 1, 0), limits, limits, Point3f(0, 0, 1));
00280   cloud.insert(cloud.end(), facet.begin(), facet.end());
00281   pe::generatePlanarObject(facet, Point3f(1, 0, 0), Point3f(0, 1, 0), limits, limits, Point3f(0, 0, -1));
00282   cloud.insert(cloud.end(), facet.begin(), facet.end());
00283 
00284   printf("Generated %d points\n", (int)cloud.size());
00285 }
00286 
00287 void generateRing(std::vector<cv::Point3f>& cloud, cv::Point3f center)
00288 {
00289   const int pointsCount = 10000;
00290   const float minRadius = 0.8;
00291   const float maxRadius = 1.1;
00292   for(int i = 0; i < 10000; i++)
00293   {
00294     float radius = float(rand())/RAND_MAX*(maxRadius - minRadius) + minRadius;
00295     float angle = float(rand())/RAND_MAX*2*CV_PI;
00296     float x = rand()%5 == 0 ? 0.05 : 0.0f;
00297 
00298     cv::Point3f p(x, radius*cos(angle), radius*sin(angle));
00299     cloud.push_back(p + center);
00300   }
00301 }
00302 
00303 
00304 CircleCameraSimulator::CircleCameraSimulator(const cv::Mat& intrinsics, const std::vector<cv::Point3f>& cloud) :
00305     intrinsics_(intrinsics), cloud_(cloud), radius_(0.9f)
00306 {
00307   initRT();
00308 }
00309 
00310 void CircleCameraSimulator::initRT()
00311 {
00312   rvec_ = Mat::zeros(3, 1, CV_32F);
00313   tvec_ = Mat::zeros(3, 1, CV_32F);
00314 
00315 //  tvec_ = -0.5f;
00316   tvec_.at<float>(0, 0) = 0.1;
00317   tvec_.at<float>(1, 0) = -radius_;
00318   angle_ = 0.0f;
00319 }
00320 
00321 void CircleCameraSimulator::updateRT()
00322 {
00323   Mat oldTvec = tvec_.clone();
00324   Mat oldRvec = rvec_.clone();
00325 
00326   angle_ -= 0.1f;
00327   rvec_.at<float>(0, 0) = angle_;
00328 //  tvec_.at<float>(2, 0) += 0.1;
00329 
00330   Mat drvec, dtvec;
00331   calcRelativeRT(oldRvec, oldTvec, rvec_, tvec_, drvec, dtvec);
00332   dumpFltMat("Ground truth relative rvec", drvec);
00333   dumpFltMat("Ground truth relative tvec", dtvec);
00334 }
00335 
00336 void CircleCameraSimulator::getNextFrame(std::vector<cv::KeyPoint>& imagePoints, std::vector<cv::DMatch>& matches)
00337 {
00338   updateRT();
00339 
00340   std::vector<cv::KeyPoint> _imagePoints;
00341   generateProjections(intrinsics_, rvec_, tvec_, cloud_, _imagePoints);
00342 
00343   Mat R;
00344   Rodrigues(rvec_, R);
00345   std::vector<int> visible;
00346   calcVisible(intrinsics_, R, tvec_, cloud_, _imagePoints, visible);
00347 
00348   printf("%d points visible\n", std::accumulate(visible.begin(), visible.end(), 0));
00349   filterVector(_imagePoints, visible, imagePoints);
00350 
00351   if(visible_.size() > 0)
00352   {
00353     calcMatches(visible, matches);
00354   }
00355   visible_ = visible;
00356 }
00357 
00358 void CircleCameraSimulator::calcMatches(const std::vector<int>& newVisible, std::vector<cv::DMatch>& matches)
00359 {
00360   assert(visible_.size() == newVisible.size());
00361 
00362   int index1 = 0, index2 = 0;
00363   for(size_t i = 0; i < newVisible.size(); i++)
00364   {
00365     if(visible_[i] && newVisible[i])
00366     {
00367       matches.push_back(cv::DMatch(index1, index2, 0.f));
00368     }
00369 
00370     if(visible_[i]) index1++;
00371     if(newVisible[i]) index2++;
00372   }
00373 }
00374 
00375 }


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