changeset 127:d19d6e63dd77

simple feature tracking and drawing working
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Wed, 17 Aug 2011 01:25:13 -0400
parents 336926453b28
children 536510f60854
files c/Makefile c/cvutils.cpp c/feature-based-tracking.cpp include/Parameters.hpp include/cvutils.hpp
diffstat 5 files changed, 55 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/c/Makefile	Wed Aug 17 00:20:31 2011 -0400
+++ b/c/Makefile	Wed Aug 17 01:25:13 2011 -0400
@@ -62,7 +62,7 @@
 test:
 	echo "coucou $(HOME)"
 
-feature-based-tracking: feature-based-tracking.o
+feature-based-tracking: feature-based-tracking.o cvutils.o
 	$(CXX) $(CFLAGS) $(LIBS) $^ -o $(BUILD_DIR)/$@ $(LDFLAGS)
 
 track-features.o: track-features.cpp
--- a/c/cvutils.cpp	Wed Aug 17 00:20:31 2011 -0400
+++ b/c/cvutils.cpp	Wed Aug 17 01:25:13 2011 -0400
@@ -10,12 +10,12 @@
 using namespace std;
 using namespace cv;
 
-void keypPoints2Points(const vector<KeyPoint>& kpts, vector<Point2f>& points) {
-  points.clear();
-  points.resize(kpts.size());
+void keyPoints2Points(const vector<KeyPoint>& kpts, vector<Point2f>& pts) {
+  pts.clear();
+  pts.reserve(kpts.size());
 
   for (unsigned int i=0; i<kpts.size(); i++)
-    points[i] = kpts[i].pt;
+    pts.push_back(kpts[i].pt);
 }
 
 IplImage* allocateImage(const int& width, const int& height, const int& depth, const int& channels) { return ::allocateImage(cvSize(width, height), depth, channels);}
--- a/c/feature-based-tracking.cpp	Wed Aug 17 00:20:31 2011 -0400
+++ b/c/feature-based-tracking.cpp	Wed Aug 17 01:25:13 2011 -0400
@@ -1,9 +1,11 @@
 //#include "Feature.hpp"
 #include "Parameters.hpp"
+#include "cvutils.hpp"
 #include "utils.hpp"
 
 #include "src/Trajectory.h"
 
+#include "opencv2/core/core.hpp"
 #include "opencv2/highgui/highgui.hpp"
 //#include "opencv2/imgproc/imgproc.hpp"
 #include "opencv2/features2d/features2d.hpp"
@@ -25,29 +27,48 @@
       Point2f pt_old = train[matches[i].trainIdx].pt;
       Point2f dist = pt_new - pt_old;
       if (norm(dist) < 20) {
-	cv::line(img, pt_new, pt_old, Scalar(125, 255, 125), 1);
-	cv::circle(img, pt_new, 2, Scalar(255, 0, 125), 1);
+	line(img, pt_new, pt_old, Scalar(125, 255, 125), 1);
+	circle(img, pt_old, 2, Scalar(255, 0, 125), 1);
       }
     }
 }
 
+void drawOpticalFlow(const vector<Point2f>& prevPts, const vector<Point2f>& currPts, const vector<uchar> status, Mat& img) {
+  for (unsigned int i=0; i<status.size(); i++) {
+    if (status[i]) {
+ 	line(img, prevPts[i], currPts[i], Scalar(125, 255, 125), 1);
+	circle(img, prevPts[i], 2, Scalar(255, 0, 125), 1);     
+    }
+  }
+}
+
 int main(int argc, char *argv[]) {
   //vector<TrajectoryPoint2f> features;
-
+  
   BriefDescriptorExtractor brief(32);
   const int DESIRED_FTRS = 500;
   //shared_ptr<FeatureDetector> detector = shared_ptr<FeatureDetector>(new GridAdaptedFeatureDetector(new FastFeatureDetector(10, true), DESIRED_FTRS, 4, 4));
-  GridAdaptedFeatureDetector detector(new FastFeatureDetector(10, true), DESIRED_FTRS, 4, 4);
+  //GridAdaptedFeatureDetector detector(new FastFeatureDetector(10, true), DESIRED_FTRS, 4, 4);
 
   VideoCapture capture;
-  Mat frame, display;
+  Mat frame, currentFrameBW, previousFrameBW;
 
   KLTFeatureTrackingParameters params;
   params.frame1 = 0;
   params.nFrames = -1;
-  // TODO ajouter klt paremeters, reprendre code de opencvfeaturetracker
-  //GoodFeaturesToTrackDetector detector(Params.max_nfeatures, Params.feature_quality, Params.min_feature_distance_klt, Params.window_size, Params.useHarrisDetector_GoodFeaturesToTrackDetector, Params.k_GoodFeaturesToTrackDetector);
-  // search descriptor_match.h
+  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.maxNumberTrackingIterations = 20; // 30
+  params.minTrackingError = 0.3; // 0.01
+  params.derivLambda = 0.5;
+  Size window = Size(params.windowSize, params.windowSize);
 
   BruteForceMatcher<Hamming> descMatcher;
   vector<DMatch> matches;
@@ -81,10 +102,11 @@
     }
   
   vector<KeyPoint> prevKpts, currKpts;
+  vector<Point2f> prevPts, currPts;
+  vector<uchar> status;
+  vector<float> errors;
+  Mat prevDesc, currDesc;
   
-  Mat gray;
-  
-  Mat prevDesc, currDesc;
   // TODO structure de donnee paires pointeur trajectory, numero de keypoint
   int key = '?'; 
   for (int frameNum = 0; ((params.frame1+frameNum < params.nFrames) || (params.nFrames < 0)) && !::interruptionKey(key); frameNum++) {
@@ -93,26 +115,31 @@
       while (frame.empty())
 	capture >> frame;//break;
       
-      cvtColor(frame, gray, CV_RGB2GRAY);
+      cvtColor(frame, currentFrameBW, CV_RGB2GRAY);
       
-      detector.detect(gray, currKpts);
+      detector.detect(currentFrameBW, currKpts);
       //cout << currKpts.size() << " kpts" << endl;
       
-      brief.compute(gray, currKpts, currDesc); //Compute brief descriptors at each keypoint location
+      brief.compute(currentFrameBW, currKpts, currDesc); //Compute brief descriptors at each keypoint location
       
-      //display = frame.clone();
       if (!prevKpts.empty()) {
-	cout << matches.size() << " matches" << endl;
-	descMatcher.match(currDesc, prevDesc, matches);
-	cout << matches.size() << " matches" << endl;
+	::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
+	drawOpticalFlow(prevPts, currPts, status, frame);
+
+	// cout << matches.size() << " matches" << endl;
+	// descMatcher.match(currDesc, prevDesc, matches);
+	// cout << matches.size() << " matches" << endl;
 	drawMatchesRelative(prevKpts, currKpts, matches, frame);
 	//drawMatches(frame, prevKpts, frame, currKpts, matches, display);//, Scalar::all(-1), Scalar::all(-1), vector<vector<char> >(), DrawMatchesFlags::DRAW_OVER_OUTIMG);
       }
       
       imshow("frame", frame);
+      previousFrameBW = currentFrameBW.clone();
       prevKpts = currKpts;
       currDesc.copyTo(prevDesc);
-      key = waitKey(0);
+      key = waitKey(2);
     }  
   
   return 0;
--- a/include/Parameters.hpp	Wed Aug 17 00:20:31 2011 -0400
+++ b/include/Parameters.hpp	Wed Aug 17 01:25:13 2011 -0400
@@ -19,6 +19,8 @@
   float featureQuality;
   float minFeatureDistanceKLT;
   int windowSize;
+  bool useHarrisDetector;
+  float k;
   int pyramidLevel;
   int nFramesDisplacement;
   float minFeatureDisplacement;
@@ -28,6 +30,7 @@
   int nFramesVelocity;
   int maxNumberTrackingIterations;
   float minTrackingError;
+  float derivLambda;
   int minFeatureTime;
   float mmConnectionDistance;
   float mmSegmentationDistance;
--- a/include/cvutils.hpp	Wed Aug 17 00:20:31 2011 -0400
+++ b/include/cvutils.hpp	Wed Aug 17 01:25:13 2011 -0400
@@ -10,7 +10,7 @@
 
 //static const int flipImage = CV_CVTIMG_FLIP;
 
-void keypPoints2Points(const std::vector<cv::KeyPoint>& kpts, std::vector<cv::Point2f>& points);
+void keyPoints2Points(const std::vector<cv::KeyPoint>& kpts, std::vector<cv::Point2f>& pts);
 
 /** Allocates a new IplImage. */
 IplImage* allocateImage(const int& width, const int& height, const int& depth, const int& channels);