Merging remained part of hybrid tracker which adds correlation threshold
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 7 Dec 2011 14:54:03 +0000 (14:54 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 7 Dec 2011 14:54:03 +0000 (14:54 +0000)
Keir's comment:
  Add support for detecting tracking failure in the ESM tracker component of
  libmv. Since both KLT and Hybrid rely on ESM underneath, KLT and Hybrid now
  have a minimum correlation setting to match. With this fix, track failures
  should get detected quicker, with the issue that sometimes the tracker will
  give up too easily. That is fixable by reducing the required correlation (in
  the track properties).

Command used for merge: svn merge -r 42396:42397 -r 42399:42400 ^/branches/soc-2011-tomato

extern/libmv/libmv-capi.cpp
extern/libmv/libmv-capi.h
extern/libmv/libmv/tracking/esm_region_tracker.cc
extern/libmv/libmv/tracking/esm_region_tracker.h
release/scripts/startup/bl_ui/space_clip.py
source/blender/blenkernel/intern/tracking.c

index dd98d0828dcc2dcd1e66937830e1afe4c665a9e2..1835c53b53f78acc1cb168dc0421712e7d018f71 100644 (file)
@@ -111,12 +111,13 @@ void libmv_setLoggingVerbosity(int verbosity)
 
 /* ************ RegionTracker ************ */
 
-libmv_RegionTracker *libmv_pyramidRegionTrackerNew(int max_iterations, int pyramid_level, int half_window_size)
+libmv_RegionTracker *libmv_pyramidRegionTrackerNew(int max_iterations, int pyramid_level, int half_window_size, double minimum_correlation)
 {
        libmv::EsmRegionTracker *esm_region_tracker = new libmv::EsmRegionTracker;
        esm_region_tracker->half_window_size = half_window_size;
        esm_region_tracker->max_iterations = max_iterations;
        esm_region_tracker->min_determinant = 1e-4;
+       esm_region_tracker->minimum_correlation = minimum_correlation;
 
        libmv::PyramidRegionTracker *pyramid_region_tracker =
                new libmv::PyramidRegionTracker(esm_region_tracker, pyramid_level);
@@ -124,12 +125,13 @@ libmv_RegionTracker *libmv_pyramidRegionTrackerNew(int max_iterations, int pyram
        return (libmv_RegionTracker *)pyramid_region_tracker;
 }
 
-libmv_RegionTracker *libmv_hybridRegionTrackerNew(int max_iterations, int half_window_size)
+libmv_RegionTracker *libmv_hybridRegionTrackerNew(int max_iterations, int half_window_size, double minimum_correlation)
 {
        libmv::EsmRegionTracker *esm_region_tracker = new libmv::EsmRegionTracker;
        esm_region_tracker->half_window_size = half_window_size;
        esm_region_tracker->max_iterations = max_iterations;
        esm_region_tracker->min_determinant = 1e-4;
+       esm_region_tracker->minimum_correlation = minimum_correlation;
 
        libmv::BruteRegionTracker *brute_region_tracker = new libmv::BruteRegionTracker;
        brute_region_tracker->half_window_size = half_window_size;
index c5e61d69c56cdd2180e6faaabf250ad1147780b3..e10d4ef842ae3d80bddc1cb187b06275249f3344 100644 (file)
@@ -43,8 +43,8 @@ void libmv_startDebugLogging(void);
 void libmv_setLoggingVerbosity(int verbosity);
 
 /* RegionTracker */
-struct libmv_RegionTracker *libmv_pyramidRegionTrackerNew(int max_iterations, int pyramid_level, int half_window_size);
-struct libmv_RegionTracker *libmv_hybridRegionTrackerNew(int max_iterations, int half_window_size);
+struct libmv_RegionTracker *libmv_pyramidRegionTrackerNew(int max_iterations, int pyramid_level, int half_window_size, double minimum_correlation);
+struct libmv_RegionTracker *libmv_hybridRegionTrackerNew(int max_iterations, int half_window_size, double minimum_correlation);
 int libmv_regionTrackerTrack(struct libmv_RegionTracker *libmv_tracker, const float *ima1, const float *ima2,
                        int width, int height, double  x1, double  y1, double *x2, double *y2);
 void libmv_regionTrackerDestroy(struct libmv_RegionTracker *libmv_tracker);
index 844b5ff3cb9853e52110f341db4eb3845551675e..9784b61c0684fb615a4c8650cc6b171865029583 100644 (file)
@@ -273,10 +273,30 @@ bool EsmRegionTracker::Track(const FloatImage &image1,
 
     // If the step was accepted, then check for termination.
     if (d.squaredNorm() < min_update_squared_distance) {
-      if (new_error > reasonable_error) {
-        LG << "Update size shrank but reasonable error ("
-           << reasonable_error << ") not achieved; failing.";
-        return true; // XXX
+      // Compute the Pearson product-moment correlation coefficient to check
+      // for sanity.
+      // TODO(keir): Put this somewhere smarter.
+      double sX=0,sY=0,sXX=0,sYY=0,sXY=0;
+      for (int r = 0; r < width; ++r) {
+        for (int c = 0; c < width; ++c) {
+          double x = image_and_gradient1_sampled(r, c, 0);
+          double y = image_and_gradient2_sampled[new_image](r, c, 0);
+          sX += x;
+          sY += y;
+          sXX += x*x;
+          sYY += y*y;
+          sXY += x*y;
+        }
+      }
+      double N = width*width;
+      sX /= N, sY /= N, sXX /= N, sYY /= N, sXY /= N;
+      double correlation = (sXY-sX*sY)/sqrt(double((sXX-sX*sX)*(sYY-sY*sY)));
+      LG << "Final correlation: " << correlation;
+
+      if (correlation < minimum_correlation) {
+        LG << "Correlation " << correlation << " greater than "
+           << minimum_correlation << "; bailing.";
+        return false;
       }
       LG << "Successful track in " << (i + 1) << " iterations.";
       return true;
index c63417201ad8058b975fe2ef8b7a8d7432a82080..602b32f16754c7836714182109fe558401f92e97 100644 (file)
@@ -38,7 +38,8 @@ struct EsmRegionTracker : public RegionTracker {
         max_iterations(16),
         min_determinant(1e-6),
         min_update_squared_distance(1e-4),
-        sigma(0.9) {}
+        sigma(0.9),
+        minimum_correlation(0.78) {}
   
   virtual ~EsmRegionTracker() {}
 
@@ -54,6 +55,7 @@ struct EsmRegionTracker : public RegionTracker {
   double min_determinant;
   double min_update_squared_distance;
   double sigma;
+  double minimum_correlation;
 };
 
 }  // namespace libmv
index 39b78ce8cdcd6ffd2ee19eab0eb8a0e0b7595ee1..d05c93ccfe10cd720854430ac03c102401337309 100644 (file)
@@ -129,8 +129,7 @@ class CLIP_PT_tools_marker(Panel):
 
             if settings.default_tracker == 'KLT':
                 col.prop(settings, "default_pyramid_levels")
-            elif settings.default_tracker == 'SAD':
-                col.prop(settings, "default_correlation_min")
+            col.prop(settings, "default_correlation_min")
 
             col.separator()
 
@@ -497,8 +496,7 @@ class CLIP_PT_track_settings(Panel):
 
             if active.tracker == 'KLT':
                 col.prop(active, "pyramid_levels")
-            elif active.tracker == 'SAD':
-                col.prop(active, "correlation_min")
+            col.prop(active, "correlation_min")
 
             col.separator()
             col.prop(active, "frames_limit")
index 9044661f3691b93768df5df487c8886207acb553..cacea980fe2906359082524753224687512ff12f 100644 (file)
@@ -77,7 +77,6 @@ void BKE_tracking_init_settings(MovieTracking *tracking)
        tracking->camera.units= CAMERA_UNITS_MM;
 
        tracking->settings.default_tracker= TRACKER_HYBRID;
-       tracking->settings.default_pyramid_levels= 2;
        tracking->settings.default_minimum_correlation= 0.75;
        tracking->settings.default_pattern_size= 11;
        tracking->settings.default_search_size= 51;
@@ -810,9 +809,9 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u
                                                        int level= MIN2(track->pyramid_levels, max_pyramid_levels);
 
                                                        if(track->tracker==TRACKER_KLT)
-                                                               track_context.region_tracker= libmv_pyramidRegionTrackerNew(100, level, MAX2(wndx, wndy));
+                                                               track_context.region_tracker= libmv_pyramidRegionTrackerNew(100, level, MAX2(wndx, wndy), track->minimum_correlation);
                                                        else
-                                                               track_context.region_tracker= libmv_hybridRegionTrackerNew(100, MAX2(wndx, wndy));
+                                                               track_context.region_tracker= libmv_hybridRegionTrackerNew(100, MAX2(wndx, wndy), track->minimum_correlation);
                                                }
                                                else if(track->tracker==TRACKER_SAD) {
                                                        track_context.pattern_size= MAX2(patx, paty);