changeset 147:0089fb29cd26

added projection of points and reprojection for display
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Tue, 30 Aug 2011 13:38:31 -0400
parents 7150427c665e
children ad21db62b785
files c/Motion.cpp c/cvutils.cpp c/feature-based-tracking.cpp include/Motion.hpp include/cvutils.hpp
diffstat 5 files changed, 47 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/c/Motion.cpp	Tue Aug 30 13:04:36 2011 -0400
+++ b/c/Motion.cpp	Tue Aug 30 13:38:31 2011 -0400
@@ -9,8 +9,8 @@
 using namespace std;
 using namespace cv;
 
-FeatureTrajectory::FeatureTrajectory(const int& frameNum, const cv::Point2f& p) {
-  addPoint(frameNum, p);
+FeatureTrajectory::FeatureTrajectory(const int& frameNum, const cv::Point2f& p, const Mat& homography) {
+  addPoint(frameNum, p, homography);
 }
 
 bool FeatureTrajectory::smallDisplacement(const unsigned int& nDisplacements, const float& minTotalFeatureDisplacement) const {
@@ -42,8 +42,11 @@
   return result;
 }
 
-void FeatureTrajectory::addPoint(const int& frameNum, const Point2f& p) {
-  positions.add(frameNum, p);
+void FeatureTrajectory::addPoint(const int& frameNum, const Point2f& p, const Mat& homography) {
+  Point2f pp = p;
+  if (!homography.empty())
+    pp = project(p, homography);
+  positions.add(frameNum, pp);
   computeMotionData(frameNum);
   assert(positions.size() == displacementDistances.size()+1);
   assert(positions.size() == velocities.size()+1);
@@ -62,10 +65,17 @@
 
 #ifdef USE_OPENCV
 /// \todo add option for anti-aliased drawing, thickness
-void FeatureTrajectory::draw(Mat& img, const Scalar& color) const {
-  Point2f p1 = positions[0];
+void FeatureTrajectory::draw(Mat& img, const Mat& homography, const Scalar& color) const {
+  Point2f p1, p2;
+  if (!homography.empty())
+    p1 = project(positions[0], homography);
+  else
+    p1 = positions[0];
   for (unsigned int i=1; i<positions.size(); i++) {
-    Point2f p2 = positions[i];
+    if (!homography.empty())
+      p2 = project(positions[i], homography);
+    else
+      p2 = positions[i];
     line(img, p1, p2, color, 1);
     p1 = p2;
   }
--- a/c/cvutils.cpp	Tue Aug 30 13:04:36 2011 -0400
+++ b/c/cvutils.cpp	Tue Aug 30 13:38:31 2011 -0400
@@ -11,7 +11,21 @@
 using namespace std;
 using namespace cv;
 
-cv::Mat loadMat(const string& filename, const string& separator) {
+Point2f project(const Point2f& p, const Mat& homography) {
+  //Mat homogeneous(3, 1, CV_32FC1);
+  float x, y;
+  float w = homography.at<float>(2,0)*p.x+homography.at<float>(2,1)*p.y+homography.at<float>(2,2);
+  if (w != 0) {
+    x = (homography.at<float>(0,0)*p.x+homography.at<float>(0,1)*p.y+homography.at<float>(0,2))/w;
+    y = (homography.at<float>(1,0)*p.x+homography.at<float>(1,1)*p.y+homography.at<float>(1,2))/w;
+  } else {
+    x = 0;
+    y = 0;
+  }
+  return Point2f(x, y);
+}
+
+Mat loadMat(const string& filename, const string& separator) {
   vector<vector<float> > numbers = ::loadNumbers(filename, separator);
   
   Mat mat;
--- a/c/feature-based-tracking.cpp	Tue Aug 30 13:04:36 2011 -0400
+++ b/c/feature-based-tracking.cpp	Tue Aug 30 13:38:31 2011 -0400
@@ -53,6 +53,7 @@
 };
 
 inline void saveFeatures(vector<FeatureTrajectoryPtr>& features, TrajectoryDBAccess<Point2f>& db, const string& positionsTableName, const string& velocitiesTableName, const unsigned int& minNFeatures = 0) {
+  /// \todo smoothing
   if (features.size() >= minNFeatures) {
     BOOST_FOREACH(FeatureTrajectoryPtr f, features) f->write(db, positionsTableName, velocitiesTableName);
     features.clear();
@@ -70,8 +71,10 @@
   KLTFeatureTrackingParameters params(argc, argv);
   cout << params.parameterDescription << endl;
 
-  Mat m = ::loadMat(params.homographyFilename, " ");
-  //cout << m << endl;
+  Mat homography = ::loadMat(params.homographyFilename, " ");
+  Mat invHomography;
+  if (params.display && !homography.empty())
+    invHomography = homography.inv();
 
   float minTotalFeatureDisplacement = params.nDisplacements*params.minFeatureDisplacement;
   Size window = Size(params.windowSize, params.windowSize);
@@ -119,12 +122,10 @@
   //     return 1;
   //   }
 
-  // mask
   Mat mask = imread(params.maskFilename, 0);
   if (mask.empty())
     mask = Mat::ones(videoSize, CV_8UC1);
 
-  // database
   boost::shared_ptr<TrajectoryDBAccess<Point2f> > trajectoryDB = boost::shared_ptr<TrajectoryDBAccess<Point2f> >(new TrajectoryDBAccessList<Point2f>());
   //TrajectoryDBAccess<Point2f>* trajectoryDB = new TrajectoryDBAccessBlob<Point2f>();
   trajectoryDB->connect(params.databaseFilename.c_str());
@@ -171,7 +172,7 @@
 	  bool deleteFeature = false;
 	  
 	  if (status[iter->pointNum]) {
-	    iter->feature->addPoint(frameNum, currPts[iter->pointNum]);
+	    iter->feature->addPoint(frameNum, currPts[iter->pointNum], homography);
 
 	    deleteFeature |= iter->feature->smallDisplacement(params.nDisplacements, minTotalFeatureDisplacement)
 	      || !iter->feature->motionSmooth(params.accelerationBound, params.deviationBound);
@@ -184,8 +185,6 @@
 	    if (iter->feature->length() >= params.minFeatureTime) {
 	      iter->feature->setId(savedFeatureId);
 	      savedFeatureId++;
-	      /// \todo smoothing
-	      //iter->feature->write(*trajectoryDB);
 	      lostFeatures.push_back(iter->feature);
 	    }
 	    iter = featurePointMatches.erase(iter);
@@ -201,7 +200,7 @@
 	
 	if (params.display) {
 	  BOOST_FOREACH(FeaturePointMatch fp, featurePointMatches)
-	    fp.feature->draw(frame, Colors::red());
+	    fp.feature->draw(frame, invHomography, Colors::red());
 	}
 	//drawOpticalFlow(prevPts, currPts, status, frame);
 	
@@ -219,7 +218,7 @@
 	    featureMask.at<uchar>(i,j)=0;
       goodFeaturesToTrack(currentFrameBW, newPts, params.maxNFeatures, params.featureQuality, params.minFeatureDistanceKLT, featureMask, params.windowSize, params.useHarrisDetector, params.k);
       BOOST_FOREACH(Point2f p, newPts) { //for (unsigned int i=0; i<newPts.size(); i++) {
-	FeatureTrajectoryPtr f = FeatureTrajectoryPtr(new FeatureTrajectory(frameNum, p));
+	FeatureTrajectoryPtr f = FeatureTrajectoryPtr(new FeatureTrajectory(frameNum, p, homography));
 	featurePointMatches.push_back(FeaturePointMatch(f, currPts.size()));
 	currPts.push_back(p);
       }
--- a/include/Motion.hpp	Tue Aug 30 13:04:36 2011 -0400
+++ b/include/Motion.hpp	Tue Aug 30 13:38:31 2011 -0400
@@ -12,7 +12,7 @@
     before saving. */
 class FeatureTrajectory {
 public:
-  FeatureTrajectory(const int& frameNum, const cv::Point2f& p);
+  FeatureTrajectory(const int& frameNum, const cv::Point2f& p, const cv::Mat& homography);
 
   unsigned int length(void) const { return positions.size();}
 
@@ -24,14 +24,14 @@
   /// 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 addPoint(const int& frameNum, const cv::Point2f& p, const cv::Mat& homography);
 
   void shorten(void);
 
   void write(TrajectoryDBAccess<cv::Point2f>& trajectoryDB, const string& positionsTableName, const string& velocitiesTableName) const;
 
 #ifdef USE_OPENCV
-  void draw(cv::Mat& img, const cv::Scalar& color) const;
+  void draw(cv::Mat& img, const cv::Mat& homography, const cv::Scalar& color) const;
 #endif
 
 protected:
--- a/include/cvutils.hpp	Tue Aug 30 13:04:36 2011 -0400
+++ b/include/cvutils.hpp	Tue Aug 30 13:38:31 2011 -0400
@@ -10,6 +10,10 @@
 /// constant that indicates if the image should be flipped
 //static const int flipImage = CV_CVTIMG_FLIP;
 
+/** Projects a point with the homography matrix
+ use perspectiveTransform for arrays of points. */
+cv::Point2f project(const cv::Point2f& p, const cv::Mat& homography);
+
 /** Loads a cv mat from a text file where the numbers are saved line by line separated by separator */
 cv::Mat loadMat(const std::string& filename, const std::string& separator);