run_stereo.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 * Software License Agreement (BSD License)
00003 *
00004 *  Copyright (c) 2009, Willow Garage, Inc.
00005 *  All rights reserved.
00006 *
00007 *  Redistribution and use in source and binary forms, with or without
00008 *  modification, are permitted provided that the following conditions
00009 *  are met:
00010 *
00011 *   * Redistributions of source code must retain the above copyright
00012 *     notice, this list of conditions and the following disclaimer.
00013 *   * Redistributions in binary form must reproduce the above
00014 *     copyright notice, this list of conditions and the following
00015 *     disclaimer in the documentation and/or other materials provided
00016 *     with the distribution.
00017 *   * Neither the name of the Willow Garage nor the names of its
00018 *     contributors may be used to endorse or promote products derived
00019 *     from this software without specific prior written permission.
00020 *
00021 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 *  POSSIBILITY OF SUCH DAMAGE.
00033 *********************************************************************/
00034 
00035 
00036 //
00037 // runs a sequence of stereo images into an SBA engine
00038 //
00039 
00040 #include <posest/pe3d.h>
00041 #include <features_2d/features_2d.h>
00042 #include <opencv/highgui.h>
00043 #include <boost/shared_ptr.hpp>
00044 #include <cstdio>
00045 #include <fstream>
00046 #include <dirent.h>
00047 #include <fnmatch.h>
00048 
00049 namespace f2d = features_2d;
00050 using namespace std;
00051 
00052 // elapsed time in milliseconds
00053 #include <sys/time.h>
00054 static double mstime()
00055 {
00056   timeval tv;
00057   gettimeofday(&tv,NULL);
00058   long long ts = tv.tv_sec;
00059   ts *= 1000000;
00060   ts += tv.tv_usec;
00061   return (double)ts*.001;
00062 }
00063 
00064 // Names of left and right files in directory (with wildcards)
00065 char *lreg, *rreg;
00066 
00067 // Filters for scandir
00068 int getleft(struct dirent const *entry)
00069 {
00070   if (!fnmatch(lreg,entry->d_name,0))
00071     return 1;
00072   return 0;
00073 }
00074 
00075 int getright(struct dirent const *entry)
00076 {
00077   if (!fnmatch(rreg,entry->d_name,0))
00078     return 1;
00079   return 0;
00080 }
00081 
00082 
00083 int main(int argc, char** argv)
00084 {
00085   if (argc < 5)
00086     {
00087       printf("Args are: <param file> <image dir> <left image file template> <right image file template> \n");
00088       exit(0);
00089     }
00090 
00091   // get camera parameters, in the form: fx fy cx cy tx
00092   fstream fstr;
00093   fstr.open(argv[1],fstream::in);
00094   if (!fstr.is_open())
00095     {
00096       printf("Can't open camera file %s\n",argv[1]);
00097       exit(0);
00098     }
00099   CamParams camp;
00100   fstr >> camp.fx;
00101   fstr >> camp.fy;
00102   fstr >> camp.cx;
00103   fstr >> camp.cy;
00104   fstr >> camp.tx;
00105 
00106   cout << "Cam params: " << camp.fx << " " << camp.fy << " " << camp.cx
00107        << " " << camp.cy << " " << camp.tx << endl;
00108 
00109 
00110   // get left/right image file names, sorted
00111   char *dir = argv[2];
00112   lreg = argv[3];
00113   rreg = argv[4];
00114   struct dirent **lims, **rims;
00115   int nlim, nrim;
00116   nlim = scandir(dir,&lims,getleft,alphasort);
00117   printf("Found %d left images\n", nlim);
00118   printf("%s\n",lims[0]->d_name);
00119 
00120   nrim = scandir(argv[2],&rims,getright,alphasort);
00121   printf("Found %d right images\n", nrim);
00122   printf("%s\n",rims[0]->d_name);
00123 
00124   if (nlim != nrim)
00125     {
00126       printf("Number of left/right images does not match: %d vs. %d\n", nlim, nrim);
00127       exit(0);
00128     }
00129 
00130   // Calonder tree setup, don't count in computation time
00131   cout << "Setting up Calonder tree..." << flush;
00132   static const char TREES[] = "/u/mihelich/ros/pkgs/wg-ros-pkg-trunk/stacks/visual_feature_detectors/calonder_descriptor/current.rtc";
00133   f2d::CalonderDescriptorExtractor<float> *cd = new f2d::CalonderDescriptorExtractor<float>(TREES);
00134   cout << "done" << endl;
00135 
00136   // set up match structures
00137 
00138   // Detect keypoints
00139   // this returns no keypoints on my sample images...
00140   // boost::shared_ptr<f2d::FeatureDetector> detector( new f2d::StarFeatureDetector(16, 100) );
00141   //  boost::shared_ptr<f2d::FeatureDetector> detector( new f2d::StarFeatureDetector );
00142   //  boost::shared_ptr<f2d::FeatureDetector> detector( new f2d::SurfFeatureDetector(4000.0) );
00143   //  boost::shared_ptr<f2d::FeatureDetector> detector( new f2d::HarrisFeatureDetector(300, 5) );
00144   boost::shared_ptr<f2d::FeatureDetector> detector( new f2d::FastFeatureDetector(50) );
00145   std::vector<cv::KeyPoint> keypoints1, keypoints2;
00146 
00147   // descriptors
00148   boost::shared_ptr<f2d::DescriptorExtractor> extractor(cd); // this is the calonder descriptor
00149   //  boost::shared_ptr<f2d::DescriptorExtractor> extractor( new f2d::SurfDescriptorExtractor(3, 4, true) );
00150   cv::Mat descriptors1, descriptors2;
00151 
00152   // matcher
00153   boost::shared_ptr<f2d::DescriptorMatcher> matcher(new f2d::BruteForceMatcher< f2d::L2<float> >);
00154   std::vector<f2d::Match> matches;
00155 
00156   // window
00157   const std::string window_name = "matches";
00158   cv::namedWindow(window_name, CV_WINDOW_AUTOSIZE);
00159 
00160   for (int i=0; i<nlim-1; i++)
00161     {
00162       // Load images
00163       char fn[2048];
00164       sprintf(fn,"%s/%s",dir,lims[i]->d_name);
00165       cv::Mat image1 = cv::imread(fn,0);
00166       sprintf(fn,"%s/%s",dir,lims[i+1]->d_name);
00167       cv::Mat image2 = cv::imread(fn,0);
00168       sprintf(fn,"%s/%s",dir,rims[i]->d_name);
00169       cv::Mat image1r = cv::imread(fn,0);
00170       sprintf(fn,"%s/%s",dir,rims[i+1]->d_name);
00171       cv::Mat image2r = cv::imread(fn,0);
00172 
00173 #if 0
00174       printf("Image size: %d x %d\n", image1.cols, image1.rows);
00175       printf("Image size: %d x %d\n", image1r.cols, image1r.rows);
00176       printf("Image size: %d x %d\n", image2.cols, image2.rows);
00177       printf("Image size: %d x %d\n", image2r.cols, image2r.rows);
00178 #endif
00179 
00180       if (image1.rows == 0 || image1r.rows == 0 || image2.rows == 0 || image2r.rows == 0)
00181         exit(0);
00182 
00183 
00184       // get keypoints
00185       double t0 = mstime();
00186       keypoints1.clear();
00187       keypoints2.clear();
00188       detector->detect(image1, keypoints1);
00189       detector->detect(image2, keypoints2);
00190       double t1 = mstime();
00191       printf("%d keypoints in ref image\n", (int)keypoints1.size());
00192       printf("%d keypoints in new image\n", (int)keypoints2.size());
00193 
00194       // Compute descriptors
00195       extractor->compute(image1, keypoints1, descriptors1);
00196       extractor->compute(image2, keypoints2, descriptors2);
00197       double t2 = mstime();
00198 
00199       printf("%d keypoints remaining in ref image\n", (int)keypoints1.size());
00200       printf("%d keypoints remaining new image\n", (int)keypoints2.size());
00201 
00202       // Perform matching
00203       matches.clear();
00204       matcher->matchWindowed(keypoints1, descriptors1, keypoints2, descriptors2, 64, 32, matches);
00205       double t3 = mstime();
00206       printf("%d matches\n", (int)matches.size());
00207 
00208       printf("Detector: %0.2f ms;  Descriptor: %0.2f ms;  Matcher: %0.2f ms\n", 
00209              t1-t0, t2-t1, t3-t2);
00210 
00211 
00212       //
00213       // do pose estimation
00214       //
00215 
00216       srand(mstime());
00217 
00218       // set up frames
00219       Frame f0, f1;
00220       f0.setCamParams(camp);        // this sets the projection and reprojection matrices
00221       f1.setCamParams(camp);
00222       f0.img = image1;
00223       f0.imgRight = image1r;
00224       f1.img = image2;
00225       f1.imgRight = image2r;
00226       f0.kpts = keypoints1;
00227       f1.kpts = keypoints2;
00228 
00229       // set stereo on keypoints
00230       f0.setStereoPoints(64);      // search range
00231       f1.setStereoPoints(64);
00232       int n0=0, n1=0;
00233       for (int i=0; i<(int)f0.goodPts.size(); i++)
00234         if (f0.goodPts[i]) n0++;
00235       for (int i=0; i<(int)f1.goodPts.size(); i++)
00236         if (f1.goodPts[i]) n1++;
00237       printf("%d/%d, %d/%d good stereo points\n", n0, (int)f0.goodPts.size(), 
00238              n1, (int)f1.goodPts.size());
00239 
00240       // save matches
00241       std::vector<f2d::Match> ms = matches;
00242 
00243       // do pose estimation
00244       pe::PoseEstimator pe(500,true,2.0e-1,6.0,6.0);
00245       int inl = pe.estimate(f0,f1,matches,true);
00246       double t4 = mstime();
00247       printf("\n");
00248       printf("Number of inliers: %d; RANSAC+polish time is %0.2f ms\n", inl, t4-t3);
00249       printf("Total time: %0.2f ms\n", t4-t0);
00250 
00251       cout << pe.trans.transpose().start(3) << endl << endl;
00252       //      cout << pe.rot << endl;
00253 
00254 
00255       // Visualize
00256       cv::Mat display;
00257       //  f2d::drawMatchesFlow(image1, keypoints1, image2, keypoints2, matches, display);
00258       //  f2d::drawMatches(image1, keypoints1, image2, keypoints2, matches, display);
00259       f2d::drawMatchesFlow(image1, keypoints1, image2, keypoints2, matches, ms, display);
00260       cv::imshow(window_name, display);
00261       cv::waitKey(10);
00262 
00263     }
00264   return 0;
00265 }


vslam_system
Author(s): Kurt Konolige, Patrick Mihelich, Helen Oleynikova
autogenerated on Thu Jan 2 2014 12:12:31