changeset 137:445e773c9be3

created the parameter structure to parse parameters (bug remaining)
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Fri, 19 Aug 2011 01:35:45 -0400
parents 0f790de9437e
children c1b260b48d2a
files c/Makefile c/Motion.cpp c/Parameters.cpp c/feature-based-tracking.cpp c/tracking.cfg include/Parameters.hpp
diffstat 6 files changed, 216 insertions(+), 81 deletions(-) [+]
line wrap: on
line diff
--- a/c/Makefile	Thu Aug 18 22:25:21 2011 -0400
+++ b/c/Makefile	Fri Aug 19 01:35:45 2011 -0400
@@ -10,7 +10,8 @@
 
 LDFLAGS = -lm
 LDFLAGS += -lTrajectoryManagementAndAnalysis -lsqlite3
-#LDFLAGS += -lboost_program_options-mt -lboost_filesystem-mt -lboost_system-mt -lboost_unit_test_framework-mt
+LDFLAGS += -lboost_program_options-mt
+# -lboost_filesystem-mt -lboost_system-mt -lboost_unit_test_framework-mt
 #LDFLAGS += -lfltk
 
 CFLAGS = -Wall -W -Wextra
@@ -64,7 +65,7 @@
 test:
 	echo "coucou $(HOME)"
 
-feature-based-tracking: feature-based-tracking.o cvutils.o Motion.o
+feature-based-tracking: feature-based-tracking.o cvutils.o Motion.o Parameters.o
 	$(CXX) $(CFLAGS) $(LIBS) $^ -o $(BUILD_DIR)/$@ $(LDFLAGS)
 
 track-features.o: track-features.cpp
--- a/c/Motion.cpp	Thu Aug 18 22:25:21 2011 -0400
+++ b/c/Motion.cpp	Fri Aug 19 01:35:45 2011 -0400
@@ -17,7 +17,7 @@
   unsigned int nPositions = positions.size();
   if (nPositions > nDisplacements) {
     float disp = 0;
-    for (int i=0; i<nDisplacements; i++)
+    for (unsigned int i=0; i<nDisplacements; i++)
       disp += displacementDistances[nPositions-2-i];
     result = disp > minTotalFeatureDisplacement;
   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/c/Parameters.cpp	Fri Aug 19 01:35:45 2011 -0400
@@ -0,0 +1,110 @@
+#include "Parameters.hpp"
+
+#include <boost/program_options.hpp>
+
+#include <iostream>
+#include <fstream>
+
+namespace po = boost::program_options;
+using namespace std;
+
+KLTFeatureTrackingParameters::KLTFeatureTrackingParameters(const int argc, char* argv[]) {
+  std::string configurationFilename;
+  po::options_description onlyCmdLine("Command line only");
+  po::options_description cmdLineAndFile("Command line and configuration file");
+
+  // configuration filename
+  onlyCmdLine.add_options()
+    ("config-file", po::value<string>(&configurationFilename)->default_value("tracking.cfg"), "configuration file")
+    ;
+
+  po::positional_options_description p;
+  p.add("config-file", 1);
+  
+  // common to cnnfiguration and command line
+  cmdLineAndFile.add_options()
+    ("help,h", "displays this help message")
+    ("video-filename", po::value<string>(&videoFilename), "filename of the video to process")
+    ("database-filename", po::value<string>(&databaseFilename), "filename of the database where results are saved")
+    ("homography-filename", po::value<string>(&homographyFilename), "filename of the homography matrix")
+    ("mask-filename", po::value<string>(&maskFilename), "filename of the mask image (where features are detected)")
+    ("load-features", po::value<bool>(&loadFeatures), "load features from database")
+    ("display", po::value<bool>(&display), "display trajectories on the video")
+    ("video-fps", po::value<float>(&videoFPS), "original video frame rate")
+    ("frame1", po::value<int>(&frame1), "first frame to process")
+    ("nframes", po::value<int>(&nFrames), "number of frame to process")
+    // feature tracking
+    ("max-nfeatures", po::value<int>(&maxNFeatures), "maximum number of features added at each frame")
+    ("feature-quality", po::value<float>(&featureQuality), "quality level of the good features to track")
+    ("min-feature-distanceklt", po::value<float>(&minFeatureDistanceKLT), "minimum distance between features")
+    ("window-size", po::value<int>(&windowSize), "size of the search window at each pyramid level")
+    ("use-harris-detector", po::value<bool>(&useHarrisDetector), "use of Harris corner detector")
+    ("k", po::value<float>(&k), "k parameter to detect good features to track (OpenCV)")
+    ("pyramid-level", po::value<int>(&pyramidLevel), "maximal pyramid level in the feature tracking algorithm")
+    ("ndisplacements", po::value<unsigned int>(&nDisplacements), "number of displacement to test minimum feature motion")
+    ("min-feature-displacement", po::value<float>(&minFeatureDisplacement), "minimum displacement to keep features")
+    ("acceleration-bound", po::value<float>(&accelerationBound), "maximum feature acceleration")
+    ("deviation-bound", po::value<float>(&deviationBound), "maximum feature deviation")
+    ("nframes-smoothing", po::value<int>(&nFramesSmoothing), "number of frames to smooth positions (half window)")
+    ("max-number-iterations", po::value<int>(&maxNumberTrackingIterations), "maximum number of iterations to stop feature tracking")
+    ("min-tracking-error", po::value<float>(&minTrackingError), "minimum error to reach to stop feature tracking")
+    ("min-feature-time", po::value<unsigned int>(&minFeatureTime), "minimum length of a feature (number of frames) to consider a feature for grouping")
+    ("mm-connection-distance", po::value<float>(&mmConnectionDistance), "connection distance in feature grouping")
+    ("mm-segmentation-distance", po::value<float>(&mmSegmentationDistance), "segmentation distance in feature grouping")
+    ("max-distance", po::value<float>(&maxDistance), "maximum distance between features for grouping")
+    ("min-velocity-cosine", po::value<float>(&minVelocityCosine), "minimum cosine of the angle between the velocity vectors for grouping")
+    ("min-nfeatures-group", po::value<int>(&minNFeaturesPerGroup), "minimum average number of features per frame to create a vehicle hypothesis")
+    ;
+    // ("max-uturn-cosine", po::value<float>(&maxUTurnCosine), "maximum cosine value to detect U-turn")
+    // ("nframes-avoid-uturn", po::value<int>(&nFramesAvoidUTurn), "number of frames over which a feature should not make a U-turn")
+
+
+  po::options_description cmdLine;
+  cmdLine.add(onlyCmdLine).add(cmdLineAndFile);
+  try {
+    po::variables_map vm;
+    store(po::command_line_parser(argc, argv).
+	  options(cmdLine).positional(p).allow_unregistered().run(), vm);
+    notify(vm);
+
+    if (vm.count("help")) {
+      cout << cmdLine << endl;
+      // cout << "Positional options:";
+      // for (unsigned int i=0; i<p.max_total_count(); i++)
+      // 	cout << " " << p.name_for_position(i);
+      // cout << endl;
+      exit(0);
+    }
+    cout << "Using configuration file " << configurationFilename << endl;
+    
+    ifstream configurationFile(configurationFilename.c_str());
+    store(po::parse_config_file(configurationFile, cmdLineAndFile), vm);
+    notify(vm);
+
+    parameterDescription = getParameterDescription(cmdLine, vm);
+  } catch(exception& e) {
+    cout << e.what() << endl;
+  }
+}
+
+string KLTFeatureTrackingParameters::getParameterDescription(po::options_description& options, const po::variables_map& vm, const string& separator /* = " " */) const {
+  stringstream stream;
+  vector<boost::shared_ptr<po::option_description> > optionsVec = options.options();
+  for (unsigned int i=0; i<optionsVec.size(); ++i) {
+    boost::any value = vm[optionsVec[i]->long_name()].value();
+    if (value.type() == typeid(bool))
+      stream << boost::any_cast<bool>(value) << separator;
+    else if (value.type() == typeid(int))
+      stream << boost::any_cast<int>(value) << separator;
+    else if (value.type() == typeid(unsigned int))
+      stream << boost::any_cast<unsigned int>(value) << separator;
+    else if (value.type() == typeid(float))
+      stream << boost::any_cast<float>(value) << separator;
+    else if (value.type() == typeid(string))
+      stream << boost::any_cast<string>(value) << separator;
+    else
+      cerr << "the type of the option variable " << i << " is not int, float or string." << endl;
+  }
+
+  return stream.str();
+}
--- a/c/feature-based-tracking.cpp	Thu Aug 18 22:25:21 2011 -0400
+++ b/c/feature-based-tracking.cpp	Fri Aug 19 01:35:45 2011 -0400
@@ -60,56 +60,56 @@
   VideoCapture capture;
   Mat frame, currentFrameBW, previousFrameBW;
 
-  KLTFeatureTrackingParameters params;
-  params.display = true;
-  params.frame1 = 0;
-  params.nFrames = -1;
-  params.maxNFeatures = 1000;
-  params.featureQuality = 0.1;
-  params.minFeatureDistanceKLT = 3;
-  params.windowSize = 3; 
-  params.useHarrisDetector = false;
-  params.k = 0.4;
-  //GoodFeaturesToTrackDetector detector(params.maxNFeatures, params.featureQuality, params.minFeatureDistanceKLT, params.windowSize, params.useHarrisDetector, params.k);
+  KLTFeatureTrackingParameters params(argc, argv);
+  cout << params.parameterDescription << endl;
+  // params.display = true;
+  // params.frame1 = 0;
+  // params.nFrames = -1;
+  // params.maxNFeatures = 1000;
+  // params.featureQuality = 0.1;
+  // params.minFeatureDistanceKLT = 3;
+  // params.windowSize = 3; 
+  // params.useHarrisDetector = false;
+  // params.k = 0.4;
+  // //GoodFeaturesToTrackDetector detector(params.maxNFeatures, params.featureQuality, params.minFeatureDistanceKLT, params.windowSize, params.useHarrisDetector, params.k);
 
-  params.pyramidLevel = 3;
-  params.nDisplacements = 3;
-  params.minFeatureDisplacement = 0.05;
-  float minTotalFeatureDisplacement = params.nDisplacements*params.minFeatureDisplacement;
+  // params.pyramidLevel = 3;
+  // params.nDisplacements = 3;
+  // params.minFeatureDisplacement = 0.05;
 
-  params.maxNumberTrackingIterations = 20; // 30
-  params.minTrackingError = 0.3; // 0.01
-  params.derivLambda = 0.5;
-  params.minFeatureTime = 20;
+  // params.maxNumberTrackingIterations = 20; // 30
+  // params.minTrackingError = 0.3; // 0.01
+  // params.minFeatureTime = 20;
 
+  float minTotalFeatureDisplacement = params.nDisplacements*params.minFeatureDisplacement;
   Size window = Size(params.windowSize, params.windowSize);
 
   BruteForceMatcher<Hamming> descMatcher;
   vector<DMatch> matches;
   Size videoSize;
 
-  if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0]))) // if no parameter or number parameter
-    capture.open(argc == 2 ? argv[1][0] - '0' : 0);
-  else if( argc >= 2 )
-    {
-      capture.open(argv[1]);
-      if( capture.isOpened() )
-	videoSize = Size(capture.get(CV_CAP_PROP_FRAME_WIDTH), capture.get(CV_CAP_PROP_FRAME_HEIGHT));
-	cout << "Video " << argv[1] <<
-	  ": width=" << videoSize.width <<
-	  ", height=" << videoSize.height <<
-	  ", nframes=" << capture.get(CV_CAP_PROP_FRAME_COUNT) << endl;
-      if( argc > 2 && isdigit(argv[2][0]) ) // could be used to reach first frame, dumping library messages to log file (2> /tmp/log.txt)
-        {
-	  sscanf(argv[2], "%d", &params.frame1);
-      	  cout << "seeking to frame #" << params.frame1 << endl;
-      	  //cap.set(CV_CAP_PROP_POS_FRAMES, pos);
-	  for (int i=0; i<params.frame1; i++)
-	    capture >> frame;
-        }
-    }
+  // if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0]))) // if no parameter or number parameter
+  //   capture.open(argc == 2 ? argv[1][0] - '0' : 0);
+  // else if( argc >= 2 )
+  //   {
+  //     capture.open(argv[1]);
+  //     if( capture.isOpened() )
+  // 	videoSize = Size(capture.get(CV_CAP_PROP_FRAME_WIDTH), capture.get(CV_CAP_PROP_FRAME_HEIGHT));
+  // 	cout << "Video " << argv[1] <<
+  // 	  ": width=" << videoSize.width <<
+  // 	  ", height=" << videoSize.height <<
+  // 	  ", nframes=" << capture.get(CV_CAP_PROP_FRAME_COUNT) << endl;
+  //     if( argc > 2 && isdigit(argv[2][0]) ) // could be used to reach first frame, dumping library messages to log file (2> /tmp/log.txt)
+  //       {
+  // 	  sscanf(argv[2], "%d", &params.frame1);
+  //     	  cout << "seeking to frame #" << params.frame1 << endl;
+  //     	  //cap.set(CV_CAP_PROP_POS_FRAMES, pos);
+  // 	  for (int i=0; i<params.frame1; i++)
+  // 	    capture >> frame;
+  //       }
+  //   }
 
-    //  capture.open(atoi(argv[1]));
+  capture.open(params.videoFilename);
   if (!capture.isOpened())
     {
       //help(argv);
@@ -149,7 +149,7 @@
       if (!prevPts.empty()) {
 	//::keyPoints2Points(prevKpts, prevPts);
 	currPts.clear();
-	calcOpticalFlowPyrLK(previousFrameBW, currentFrameBW, prevPts, currPts, status, errors, window, params.pyramidLevel, TermCriteria(3 /*static_cast<int>(TermCriteria::COUNT)+static_cast<int>(TermCriteria::EPS)*/, params.maxNumberTrackingIterations, params.minTrackingError), params.derivLambda, 0); // OPTFLOW_USE_INITIAL_FLOW
+	calcOpticalFlowPyrLK(previousFrameBW, currentFrameBW, prevPts, currPts, status, errors, window, params.pyramidLevel, TermCriteria(3 /*static_cast<int>(TermCriteria::COUNT)+static_cast<int>(TermCriteria::EPS)*/, params.maxNumberTrackingIterations, params.minTrackingError), 0.5 /* unused */, 0); // OPTFLOW_USE_INITIAL_FLOW
 
 	vector<Point2f> trackedPts;
 	vector<FeaturePointMatch>::iterator iter = featurePointMatches.begin();
--- a/c/tracking.cfg	Thu Aug 18 22:25:21 2011 -0400
+++ b/c/tracking.cfg	Fri Aug 19 01:35:45 2011 -0400
@@ -1,50 +1,64 @@
-# video file to process: videoFilenamePrefix
-video-filename = carrefour.avi
-# original video frame rate: videoFPS
+# filename of the video to process
+video-filename = ~/Research/Data/minnesota/Rice-and-University-12_50.avi
+# filename of the database where results are saved
+database-filename = ~/Research/Data/minnesota/results.sqlite
+# filename of the homography matrix
+homography-filename = ~/Research/Data/minnesota/Rice-and-University-12_50-homography.txt
+# filename of the mask image (where features are detected)
+mask-filename = ~/Research/Data/minnesota/Rice-and-University-12_50-mask.png
+# load features from database
+load-features = false
+# display trajectories on the video
+display = false
+# original video frame rate
 video-fps = 29.97
-# number of digits of precision for all measurements derived from video: measurementPrecision
-measurement-precision = 3
-# first frame to process: frame1
+# number of digits of precision for all measurements derived from video
+# measurement-precision = 3
+# first frame to process
 frame1 = 0
-# number of frame to process: nFrames
+# number of frame to process
 nframes = -1
 # feature tracking
-# maximum number of tracked features (> 500): maxNFeatures
+# maximum number of features added at each frame
 max-nfeatures = 1000
-# quality level of the good features to track: featureQuality
+# quality level of the good features to track
 feature-quality = 0.1
-# minimum distance between features: minFeatureDistanceKLT
-min-feature-distance = 5
-# size of the search window at each pyramid level: windowSize
+# minimum distance between features
+min-feature-distanceklt = 5
+# size of the search window at each pyramid level
 window-size = 7
-# maximal pyramid level in the feature tracking algorithm: pyramidLevel
+# use of Harris corner detector
+use-harris-detector = false
+# k parameter to detect good features to track (OpenCV)
+k = 0.4
+# maximal pyramid level in the feature tracking algorithm
 pyramid-level = 5
-# number of frames to compute the feature displacement: nFramesDisplacement
-nframes-displacement = 3
-# minimum displacement to keep features: minFeatureDisplacement
+# number of displacement to test minimum feature motion
+ndisplacements = 3
+# minimum displacement to keep features
 min-feature-displacement = 0.05
-# maximum feature acceleration: accelerationBound
+# maximum feature acceleration
 acceleration-bound = 3
-# maximum feature deviation: deviationBound
+# maximum feature deviation
 deviation-bound = 0.6
-# number of frames to smooth positions (half window): nFramesSmoothing
+# number of frames to smooth positions (half window)
 nframes-smoothing = 5
-# number of frames to compute velocities: nFramesVelocity
-nframes-velocity = 5
-# maximum number of iterations to stop feature tracking:  maxNumberTrackingIterations
+# number of frames to compute velocities
+#nframes-velocity = 5
+# maximum number of iterations to stop feature tracking
 max-number-iterations = 20
-# minimum error to reach to stop feature tracking: minTrackingError
+# minimum error to reach to stop feature tracking
 min-tracking-error = 0.3
-# minimum length of a feature (number of frames) to consider a feature for grouping: minFeatureTime
+# minimum length of a feature (number of frames) to consider a feature for grouping
 min-feature-time = 20
 # Min Max similarity parameters (Beymer et al. method)
-# connection distance in feature grouping: mmConnectionDistance
+# connection distance in feature grouping
 mm-connection-distance = 3.75
-# segmentation distance in feature grouping: mmSegmentationDistance
+# segmentation distance in feature grouping
 mm-segmentation-distance = 1.5
-# maximum distance between features for grouping: maxDistance
+# maximum distance between features for grouping
 max-distance = 5
-# minimum cosine of the angle between the velocity vectors for grouping: minVelocityCosine
+# minimum cosine of the angle between the velocity vectors for grouping
 min-velocity-cosine = 0.8
-# minimum average number of features per frame to create a vehicle hypothesis: minNFeaturesPerGroup
+# minimum average number of features per frame to create a vehicle hypothesis
 min-nfeatures-group = 3
--- a/include/Parameters.hpp	Thu Aug 18 22:25:21 2011 -0400
+++ b/include/Parameters.hpp	Fri Aug 19 01:35:45 2011 -0400
@@ -5,14 +5,22 @@
 
 #include <string>
 
-struct KLTFeatureTrackingParameters {
-  /// whether to load saved features, or compute them
-  bool loadFeatures;
+namespace boost{
+  namespace program_options {
+    class options_description;
+    class variables_map;
+  }
+}
 
+struct KLTFeatureTrackingParameters {
   std::string videoFilename;
-  int videoFPS;
-  int measurementPrecision;
+  std::string databaseFilename;
+  std::string homographyFilename;
+  std::string maskFilename;
+  bool loadFeatures;
   bool display;
+  float videoFPS;
+  // int measurementPrecision;
   int frame1;
   int nFrames;
   // feature tracking
@@ -28,10 +36,9 @@
   float accelerationBound;
   float deviationBound;
   int nFramesSmoothing;
-  int nFramesVelocity;
+  //int nFramesVelocity;
   int maxNumberTrackingIterations;
   float minTrackingError;
-  float derivLambda;
   unsigned int minFeatureTime;
   float mmConnectionDistance;
   float mmSegmentationDistance;
@@ -39,10 +46,13 @@
   float minVelocityCosine;
   int minNFeaturesPerGroup;
 
-  //KLTFeatureTrackingParameters(const int argc, char* argv[]);
+  std::string parameterDescription;
+
+  KLTFeatureTrackingParameters(const int argc, char* argv[]);
 
   //KLTFeatureTrackingParameters(bool loadFeatures, std::string videoFilename, int videoFPS, int measurementPrecision, int frame1, int nFrames, int maxNFeatures, float featureQuality, float minFeatureDistanceKLT, int windowSize, int pyramidLevel, int nDisplacements, float minFeatureDisplacement, float accelerationBound, float deviationBound, int nFramesSmoothing, int nFramesVelocity, int maxNumberTrackingIterations, float minTrackingError, int minFeatureTime, float mmConnectionDistance, float mmSegmentationDistance, float maxDistance, float minVelocityCosine, int minNFeaturesPerGroup);
 
+  std::string getParameterDescription(boost::program_options::options_description& options, const boost::program_options::variables_map& vm, const std::string& separator = " ") const;
 };
 
 #endif