changeset 139:47329bd16cc0

cleaned code, added condition on smooth displacement
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Tue, 23 Aug 2011 13:14:47 -0400
parents c1b260b48d2a
children 8de5e8256224
files c/Motion.cpp c/feature-based-tracking.cpp c/tracking.cfg include/Motion.hpp include/cvutils.hpp tracking.cfg
diffstat 6 files changed, 105 insertions(+), 92 deletions(-) [+]
line wrap: on
line diff
--- a/c/Motion.cpp	Fri Aug 19 12:15:23 2011 -0400
+++ b/c/Motion.cpp	Tue Aug 23 13:14:47 2011 -0400
@@ -1,4 +1,5 @@
 #include "Motion.hpp"
+#include "cvutils.hpp"
 
 #include "opencv2/core/core.hpp"
 #include "opencv2/highgui/highgui.hpp"
@@ -24,9 +25,28 @@
   return result;
 }
 
+bool FeatureTrajectory::motionSmooth(const int& accelerationBound, const int& deviationBound) const {
+  bool result = true;
+  unsigned int nPositions = positions.size();
+  if (nPositions >= 3) {
+    float ratio;
+    if (displacementDistances[nPositions-2] > displacementDistances[nPositions-3])
+      ratio = displacementDistances[nPositions-2] / displacementDistances[nPositions-3];
+    else
+      ratio = displacementDistances[nPositions-3] / displacementDistances[nPositions-2];
+
+    float cosine = scalarProduct(velocities[nPositions-3],velocities[nPositions-2]) / (displacementDistances[nPositions-3] * displacementDistances[nPositions-2]);
+    
+    result &= (ratio < accelerationBound) & (cosine > deviationBound);
+  }
+  return result;
+}
+
 void FeatureTrajectory::addPoint(const int& frameNum, const Point2f& p) {
   positions.add(frameNum, p);
   computeMotionData(frameNum);
+  assert(positions.size() == displacementDistances.size()+1);
+  assert(positions.size() == velocities.size()+1);
 }
 
 void FeatureTrajectory::shorten(void) { 
@@ -56,10 +76,10 @@
 
 void FeatureTrajectory::computeMotionData(const int& frameNum) {
   unsigned int nPositions = positions.size();
-  if (nPositions >= 3) {
+  if (nPositions >= 2) {
     Point2f displacement = positions[nPositions-1] - positions[nPositions-2];
-    if (nPositions == 2) // duplicate first displacement so that positions and velocities have the same length
-      velocities.add(frameNum-1, displacement);
+    //if (nPositions == 2) // duplicate first displacement so that positions and velocities have the same length
+    //velocities.add(frameNum-1, displacement);
     velocities.add(frameNum, displacement);
     float dist = norm(displacement);
     displacementDistances.push_back(dist);
--- a/c/feature-based-tracking.cpp	Fri Aug 19 12:15:23 2011 -0400
+++ b/c/feature-based-tracking.cpp	Tue Aug 23 13:14:47 2011 -0400
@@ -62,24 +62,6 @@
 
   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;
-
-  // 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);
@@ -142,7 +124,6 @@
   vector<FeatureTrajectoryPtr> features;
   vector<FeaturePointMatch> featurePointMatches;
     
-  // TODO structure de donnee paires pointeur trajectory, numero de keypoint
   int key = '?';
   unsigned int savedFeatureId=0;
   for (int frameNum = params.frame1; ((params.frame1+frameNum < params.nFrames) || (params.nFrames < 0)) && !::interruptionKey(key); frameNum++) {
@@ -169,17 +150,18 @@
 	  if (status[iter->pointNum]) {
 	    iter->feature->addPoint(frameNum, currPts[iter->pointNum]);
 
-	    bool smallDisplacement = iter->feature->smallDisplacement(params.nDisplacements, minTotalFeatureDisplacement);
-	    if (smallDisplacement)
+	    deleteFeature |= iter->feature->smallDisplacement(params.nDisplacements, minTotalFeatureDisplacement)
+	      || !iter->feature->motionSmooth(params.accelerationBound, params.deviationBound);
+	    if (deleteFeature)
 	      iter->feature->shorten();
-	    deleteFeature |= smallDisplacement;
-	    // motionSmooth()
-	  } 
+	  } else
+	    deleteFeature = true;
 
 	  if (deleteFeature) {
 	    if (iter->feature->length() >= params.minFeatureTime) {
 	      iter->feature->setId(savedFeatureId);
 	      savedFeatureId++;
+	      /// \todo smoothing
 	      iter->feature->write(*trajectoryDB);
 	    }
 	    iter = featurePointMatches.erase(iter);
@@ -192,9 +174,10 @@
 	currPts = trackedPts;
 	assert(currPts.size() == featurePointMatches.size());
 	
-	if (params.display)
+	if (params.display) {
 	  BOOST_FOREACH(FeaturePointMatch fp, featurePointMatches)
 	    fp.feature->draw(frame, Colors::red());
+	}
 	//drawOpticalFlow(prevPts, currPts, status, frame);
 	
 	// cout << matches.size() << " matches" << endl;
--- a/c/tracking.cfg	Fri Aug 19 12:15:23 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-# 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
-# measurement-precision = 3
-# first frame to process
-frame1 = 0
-# number of frame to process
-nframes = -1
-# feature tracking
-# maximum number of features added at each frame
-max-nfeatures = 1000
-# quality level of the good features to track
-feature-quality = 0.1
-# minimum distance between features
-min-feature-distanceklt = 5
-# size of the search window at each pyramid level
-window-size = 7
-# 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 displacement to test minimum feature motion
-ndisplacements = 3
-# minimum displacement to keep features
-min-feature-displacement = 0.05
-# maximum feature acceleration
-acceleration-bound = 3
-# maximum feature deviation
-deviation-bound = 0.6
-# number of frames to smooth positions (half window)
-nframes-smoothing = 5
-# 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
-min-tracking-error = 0.3
-# 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
-mm-connection-distance = 3.75
-# segmentation distance in feature grouping
-mm-segmentation-distance = 1.5
-# maximum distance between features for grouping
-max-distance = 5
-# 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
-min-nfeatures-group = 3
--- a/include/Motion.hpp	Fri Aug 19 12:15:23 2011 -0400
+++ b/include/Motion.hpp	Tue Aug 23 13:14:47 2011 -0400
@@ -21,6 +21,9 @@
   /// indicates whether the sum of the last nDisplacements displacements has been inferior to minFeatureDisplacement
   bool smallDisplacement(const unsigned int& nDisplacements, const float& minTotalFeatureDisplacement) const;
 
+  /// indicates whether the last two displacements are smooth (limited acceleration and angle)
+  bool motionSmooth(const int& accelerationBound, const int& deviationBound) const;
+
   void addPoint(const int& frameNum, const cv::Point2f& p);
 
   void shorten(void);
@@ -33,8 +36,11 @@
 
 protected:
   Trajectory<cv::Point2f> positions;
+  /** one fewer velocity than position
+      v_n = p_n+1 - p_n*/
   Trajectory<cv::Point2f> velocities;
   
+  /// norms of velocities for feature constraints, one fewer positions than positions
   std::vector<float> displacementDistances;
 
   void computeMotionData(const int& frameNum);
--- a/include/cvutils.hpp	Fri Aug 19 12:15:23 2011 -0400
+++ b/include/cvutils.hpp	Tue Aug 23 13:14:47 2011 -0400
@@ -5,10 +5,14 @@
 #include "opencv2/features2d/features2d.hpp"
 
 class CvCapture;
+//template<typename T> class Point_<T>;
 
 /// constant that indicates if the image should be flipped
 //static const int flipImage = CV_CVTIMG_FLIP;
 
+template<typename T> 
+float scalarProduct(const cv::Point_<T>& v1, const cv::Point_<T>& v2) { return v1.x*v2.x+v1.y*v2.y;}
+
 void keyPoints2Points(const std::vector<cv::KeyPoint>& kpts, std::vector<cv::Point2f>& pts, const bool& clearPts = true);
 
 /** Allocates a new IplImage. */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tracking.cfg	Tue Aug 23 13:14:47 2011 -0400
@@ -0,0 +1,64 @@
+# 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
+# measurement-precision = 3
+# first frame to process
+frame1 = 0
+# number of frame to process
+nframes = -1
+# feature tracking
+# maximum number of features added at each frame
+max-nfeatures = 1000
+# quality level of the good features to track
+feature-quality = 0.1
+# minimum distance between features
+min-feature-distanceklt = 5
+# size of the search window at each pyramid level
+window-size = 7
+# 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 displacement to test minimum feature motion
+ndisplacements = 3
+# minimum displacement to keep features
+min-feature-displacement = 0.05
+# maximum feature acceleration
+acceleration-bound = 3
+# maximum feature deviation
+deviation-bound = 0.6
+# number of frames to smooth positions (half window)
+nframes-smoothing = 5
+# 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
+min-tracking-error = 0.3
+# 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
+mm-connection-distance = 3.75
+# segmentation distance in feature grouping
+mm-segmentation-distance = 1.5
+# maximum distance between features for grouping
+max-distance = 5
+# 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
+min-nfeatures-group = 3