Improve the KLT tracking behaviour and UI
authorKeir Mierle <mierle@gmail.com>
Sun, 30 Oct 2011 12:42:56 +0000 (12:42 +0000)
committerKeir Mierle <mierle@gmail.com>
Sun, 30 Oct 2011 12:42:56 +0000 (12:42 +0000)
- Remove the overly-conservative use of libmv's re-track tracker. The re-track
  tracker would take a normal tracker such as TRKLT or KLT or pyramid KLT, and
  track from frame 1 to 2, then back from the position found in 2 back to 1.
  Then, when the reverse-track doesn't match the original track with high
  precision, the track is considered "failed". This is a good approach for
  fully automatic reconstruction, but is too conservative for supervised
  tracking.

  The retrack-tracker will return when fully automatic tracking is added.

- Always solve for (dx, dy) in the TRKLT loop even if the linear system is
  ill-conditioned. The client (Blender in this case) can still use the solved
  position, even though it is less reliable.

- Expose the pyramid level setting to the tracking UI when in KLT tracking
  mode. While it was tempting to hide this detail from the user, in reality it
  does more harm than good, since the way tracking fails depends on the pyramid
  level. For now, exposing the pyramid details is a good compromise.

- Move the settings for the tracking algorithm, including search window,
  tracking algorithm, pyramid levels, etc, into the track object instead of a
  global movie clip object.

14 files changed:
extern/libmv/libmv-capi.cpp
extern/libmv/libmv-capi.h
extern/libmv/libmv/tracking/pyramid_region_tracker.cc
extern/libmv/libmv/tracking/trklt_region_tracker.cc
extern/libmv/libmv/tracking/trklt_region_tracker.h
release/scripts/startup/bl_ui/space_clip.py
source/blender/blenkernel/BKE_tracking.h
source/blender/blenkernel/intern/movieclip.c
source/blender/blenkernel/intern/tracking.c
source/blender/editors/space_clip/clip_draw.c
source/blender/makesdna/DNA_space_types.h
source/blender/makesdna/DNA_tracking_types.h
source/blender/makesrna/intern/rna_space.c
source/blender/makesrna/intern/rna_tracking.c

index f1672581819dab9c44c7d82cd8b8c41aa4c2beb3..2e007bb47b21399a578266180671e514e510ba6f 100644 (file)
@@ -36,7 +36,6 @@
 #include "libmv/tracking/klt_region_tracker.h"
 #include "libmv/tracking/trklt_region_tracker.h"
 #include "libmv/tracking/pyramid_region_tracker.h"
-#include "libmv/tracking/retrack_region_tracker.h"
 
 #include "libmv/tracking/sad.h"
 
@@ -61,7 +60,6 @@
 
 typedef struct libmv_RegionTracker {
        libmv::TrkltRegionTracker *trklt_region_tracker;
-       libmv::PyramidRegionTracker *pyramid_region_tracker;
        libmv::RegionTracker *region_tracker;
 } libmv_RegionTracker;
 
@@ -112,22 +110,19 @@ void libmv_setLoggingVerbosity(int verbosity)
 
 /* ************ RegionTracker ************ */
 
-libmv_RegionTracker *libmv_regionTrackerNew(int max_iterations, int pyramid_level, double tolerance)
+libmv_RegionTracker *libmv_regionTrackerNew(int max_iterations, int pyramid_level)
 {
-       libmv::RegionTracker *region_tracker;
        libmv::TrkltRegionTracker *trklt_region_tracker = new libmv::TrkltRegionTracker;
 
        trklt_region_tracker->half_window_size = DEFAULT_WINDOW_HALFSIZE;
        trklt_region_tracker->max_iterations = max_iterations;
+       trklt_region_tracker->min_determinant = 1e-4;
 
-       libmv::PyramidRegionTracker *pyramid_region_tracker =
+       libmv::PyramidRegionTracker *region_tracker =
                new libmv::PyramidRegionTracker(trklt_region_tracker, pyramid_level);
 
-       region_tracker = new libmv::RetrackRegionTracker(pyramid_region_tracker, tolerance);
-
        libmv_RegionTracker *configured_region_tracker = new libmv_RegionTracker;
        configured_region_tracker->trklt_region_tracker = trklt_region_tracker;
-       configured_region_tracker->pyramid_region_tracker = pyramid_region_tracker;
        configured_region_tracker->region_tracker = region_tracker;
 
        return configured_region_tracker;
index 7d7d2fbeed8a054bb6323f0bf383872fd350b2c0..b71a66b73a683fa6204d6fac98fefb6056c5aa2d 100644 (file)
@@ -43,7 +43,7 @@ void libmv_startDebugLogging(void);
 void libmv_setLoggingVerbosity(int verbosity);
 
 /* RegionTracker */
-struct libmv_RegionTracker *libmv_regionTrackerNew(int max_iterations, int pyramid_level, double tolerance);
+struct libmv_RegionTracker *libmv_regionTrackerNew(int max_iterations, int pyramid_level);
 int libmv_regionTrackerTrack(struct libmv_RegionTracker *libmv_tracker, const float *ima1, const float *ima2,
                        int width, int height, int half_window_size,
                        double  x1, double  y1, double *x2, double *y2);
index 30e2839c5b1cc94f75aac9dfec444bcd9e7ff61d..58f42b26d7c6fe7b9346c073799cbd7272257210 100644 (file)
@@ -23,6 +23,7 @@
 #include "libmv/image/convolve.h"
 #include "libmv/image/image.h"
 #include "libmv/image/sample.h"
+#include "libmv/logging/logging.h"
 #include "libmv/tracking/pyramid_region_tracker.h"
 
 namespace libmv {
@@ -69,6 +70,7 @@ bool PyramidRegionTracker::Track(const FloatImage &image1,
       // Only fail on the highest-resolution level, because a failure on a
       // coarse level does not mean failure at a lower level (consider
       // out-of-bounds conditions).
+      LG << "Finest level of pyramid tracking failed; failing.";
       return false;
     }
   }
index 65aab37bc85ffa4de64ffd3770e6749e72746dbd..94319fcb7d3392460be4e4343c4c037d85e50d52 100644 (file)
@@ -79,19 +79,6 @@ static void ComputeTrackingEquation(const Array3Df &image_and_gradient1,
   *e = (A + lambda*Mat2f::Identity())*Di*(V - W) + 0.5*(S - R);
 }
 
-static bool SolveTrackingEquation(const Mat2f &U,
-                                  const Vec2f &e,
-                                  float min_determinant,
-                                  Vec2f *d) {
-  float det = U.determinant();
-  if (det < min_determinant) {
-    d->setZero();
-    return false;
-  }
-  *d = U.lu().solve(e);
-  return true;
-}
-
 bool TrkltRegionTracker::Track(const FloatImage &image1,
                                const FloatImage &image2,
                                double  x1, double  y1,
@@ -116,17 +103,24 @@ bool TrkltRegionTracker::Track(const FloatImage &image1,
                             &U, &e);
 
     // Solve the linear system for the best update to x2 and y2.
-    if (!SolveTrackingEquation(U, e, min_determinant, &d)) {
-      // The determinant, which indicates the trackiness of the point, is too
-      // small, so fail out.
-      LG << "Determinant too small; failing tracking.";
-      return false;
-    }
+    d = U.lu().solve(e);
 
     // Update the position with the solved displacement.
     *x2 += d[0];
     *y2 += d[1];
 
+    // Check for the quality of the solution, but not until having already
+    // updated the position with our best estimate. The reason to do the update
+    // anyway is that the user already knows the position is bad, so we may as
+    // well try our best.
+    float determinant = U.determinant();
+    if (fabs(determinant) < min_determinant) {
+      // The determinant, which indicates the trackiness of the point, is too
+      // small, so fail out.
+      LG << "Determinant " << determinant << " is too small; failing tracking.";
+      return false;
+    }
+
     // If the update is small, then we probably found the target.
     if (d.squaredNorm() < min_update_squared_distance) {
       LG << "Successful track in " << i << " iterations.";
@@ -134,7 +128,7 @@ bool TrkltRegionTracker::Track(const FloatImage &image1,
     }
   }
   // Getting here means we hit max iterations, so tracking failed.
-  LG << "Too many iterations.";
+  LG << "Too many iterations; max is set to " << max_iterations << ".";
   return false;
 }
 
index d5052395c55c9668236a3ebb6a1a1b674c29756f..5046e0f069da719b189e28d93a999fb33e6a96b0 100644 (file)
@@ -37,7 +37,7 @@ namespace libmv {
 struct TrkltRegionTracker : public RegionTracker {
   TrkltRegionTracker()
       : half_window_size(4),
-        max_iterations(16),
+        max_iterations(100),
         min_determinant(1e-6),
         min_update_squared_distance(1e-6),
         sigma(0.9),
index 2569a23db47ce2f00498211984b862e7273e09a4..561572a68913b89a8cc17dc457296b86c5d467f6 100644 (file)
@@ -387,6 +387,7 @@ class CLIP_PT_display(Panel):
 
         layout.prop(sc, "show_marker_pattern", text="Pattern")
         layout.prop(sc, "show_marker_search", text="Search")
+        layout.prop(sc, "show_pyramid_levels", text="Pyramid")
 
         layout.prop(sc, "show_track_path", text="Path")
         row = layout.column()
@@ -433,13 +434,15 @@ class CLIP_PT_track_settings(Panel):
         clip = context.space_data.clip
         settings = clip.tracking.settings
 
-        layout.prop(settings, "tracker")
+        active = clip.tracking.tracks.active
+        if active:
+          layout.prop(active, "tracker")
+          if active.tracker == "KLT":
+              layout.prop(active, "pyramid_levels")
+          if active.tracker == "SAD":
+              layout.prop(active, "correlation_min")
 
         layout.prop(settings, "frames_adjust")
-
-        if settings.tracker == "SAD":
-            layout.prop(settings, "correlation_min")
-
         layout.prop(settings, "speed")
         layout.prop(settings, "frames_limit")
         layout.prop(settings, "margin")
index 11b6c7fff65ef3cd6d5ddf7dc272b7b40916783b..84121a65dffd026f91b0b10385f4f100f81bdbee 100644 (file)
@@ -118,6 +118,7 @@ struct ImBuf *BKE_tracking_distort(struct MovieTracking *tracking, struct ImBuf
 #define CLAMP_PAT_POS          2
 #define CLAMP_SEARCH_DIM       3
 #define CLAMP_SEARCH_POS       4
+#define CLAMP_PYRAMID_LEVELS   5
 
 #define TRACK_AREA_NONE                -1
 #define TRACK_AREA_POINT       1
index 0d66f5abdd4848a9cde448343985579fc71ddb13..4834178fc7de55ad7a030e35bc476f9e470976bf 100644 (file)
@@ -382,12 +382,10 @@ static MovieClip *movieclip_alloc(const char *name)
        clip->tracking.camera.pixel_aspect= 1.0f;
        clip->tracking.camera.units= CAMERA_UNITS_MM;
 
-       clip->tracking.settings.tracker= TRACKER_SAD;
        clip->tracking.settings.frames_limit= 0;
        clip->tracking.settings.keyframe1= 1;
        clip->tracking.settings.keyframe2= 30;
        clip->tracking.settings.dist= 1;
-       clip->tracking.settings.corr= 0.75f;
 
        clip->tracking.stabilization.scaleinf= 1.0f;
        clip->tracking.stabilization.locinf= 1.0f;
index 4351ce8be334e5d4f6664a553217ee1422e2c592..abf39c5354246d40234a63b7c187716dbf291a18 100644 (file)
@@ -69,6 +69,12 @@ typedef struct MovieDistortion {
 void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event)
 {
        int a;
+       float pat_min[2];
+       float pat_max[2];
+       float max_pyramid_level_factor = 1.0;
+       if (track->tracker == TRACKER_KLT) {
+               max_pyramid_level_factor = 1 << (track->pyramid_levels - 1);
+       }
 
        /* sort */
        for(a= 0; a<2; a++) {
@@ -79,34 +85,45 @@ void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event)
                        SWAP(float, track->search_min[a], track->search_max[a]);
        }
 
+       /* compute the effective pattern size, which differs from the fine resolution
+        * pattern size for the pyramid KLT tracker */
+       for(a= 0; a<2; a++) {
+               pat_min[a] = max_pyramid_level_factor * track->pat_min[a];
+               pat_max[a] = max_pyramid_level_factor * track->pat_max[a];
+       }
+
        if(event==CLAMP_PAT_DIM) {
                for(a= 0; a<2; a++) {
-                       /* pattern shouldn't be resized bigger than search */
-                       track->pat_min[a]= MAX2(track->pat_min[a], track->search_min[a]);
-                       track->pat_max[a]= MIN2(track->pat_max[a], track->search_max[a]);
+                       /* search shouldn't be resized smaller than pattern */
+                       track->search_min[a]= MIN2(pat_min[a], track->search_min[a]);
+                       track->search_max[a]= MAX2(pat_max[a], track->search_max[a]);
                }
        }
        else if(event==CLAMP_PAT_POS) {
                float dim[2];
-               sub_v2_v2v2(dim, track->pat_max, track->pat_min);
+               sub_v2_v2v2(dim, track->pat_max, pat_min);
 
                for(a= 0; a<2; a++) {
                        /* pattern shouldn't be moved outside of search */
-                       if(track->pat_min[a] < track->search_min[a]) {
-                               track->pat_min[a]= track->search_min[a];
-                               track->pat_max[a]= track->pat_min[a]+dim[a];
+                       if(pat_min[a] < track->search_min[a]) {
+                               track->pat_min[a]= track->search_min[a] - (pat_min[a] - track->pat_min[a]);
+                               track->pat_max[a]=  (pat_min[a] - track->pat_min[a])+dim[a];
                        }
                        if(track->pat_max[a] > track->search_max[a]) {
-                               track->pat_max[a]= track->search_max[a];
-                               track->pat_min[a]= track->pat_max[a]-dim[a];
+                               track->pat_max[a]= track->search_max[a] - (pat_max[a] - track->pat_max[a]);
+                               track->pat_min[a]= track->pat_max[a]-dim[a] - (pat_min[a] - track->pat_min[a]);
                        }
                }
        }
        else if(event==CLAMP_SEARCH_DIM) {
+               float max_pyramid_level_factor = 1.0;
+               if (track->tracker == TRACKER_KLT) {
+                       max_pyramid_level_factor = 1 << (track->pyramid_levels - 1);
+               }
                for(a= 0; a<2; a++) {
                        /* search shouldn't be resized smaller than pattern */
-                       track->search_min[a]= MIN2(track->pat_min[a], track->search_min[a]);
-                       track->search_max[a]= MAX2(track->pat_max[a], track->search_max[a]);
+                       track->search_min[a]= MIN2(pat_min[a], track->search_min[a]);
+                       track->search_max[a]= MAX2(pat_max[a], track->search_max[a]);
                }
        }
        else if(event==CLAMP_SEARCH_POS) {
@@ -115,17 +132,32 @@ void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event)
 
                for(a= 0; a<2; a++) {
                        /* search shouldn't be moved inside pattern */
-                       if(track->search_min[a] > track->pat_min[a]) {
-                               track->search_min[a]= track->pat_min[a];
+                       if(track->search_min[a] > pat_min[a]) {
+                               track->search_min[a]= pat_min[a];
                                track->search_max[a]= track->search_min[a]+dim[a];
                        }
-                       if(track->search_max[a] < track->pat_max[a]) {
-                               track->search_max[a]= track->pat_max[a];
+                       if(track->search_max[a] < pat_max[a]) {
+                               track->search_max[a]= pat_max[a];
                                track->search_min[a]= track->search_max[a]-dim[a];
                        }
                }
        }
 
+       else if(event==CLAMP_PYRAMID_LEVELS || (event==CLAMP_SEARCH_DIM && track->tracker == TRACKER_KLT))  {
+               float dim[2];
+               sub_v2_v2v2(dim, track->pat_max, track->pat_min);
+               {
+                       float search_ratio = 2.3f * max_pyramid_level_factor;
+
+                       /* resize the search area to something sensible based
+                        * on the number of pyramid levels */
+                       for(a= 0; a<2; a++) {
+                               track->search_min[a]= search_ratio * track->pat_min[a];
+                               track->search_max[a]= search_ratio * track->pat_max[a];
+                       }
+               }
+       }
+
        /* marker's center should be in center of pattern */
        if(event==CLAMP_PAT_DIM || event==CLAMP_PAT_POS) {
                float dim[2];
@@ -159,17 +191,9 @@ MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, float x, flo
 {
        MovieTrackingTrack *track;
        MovieTrackingMarker marker;
-       float pat[2]= {5.5f, 5.5f}, search[2]= {80.5f, 80.5f}; /* TODO: move to default setting? */
 
-       /* XXX: not very nice to have such check here, but it will prevent
-               complaints about bad default settings for new markers */
-       if(tracking->settings.tracker==TRACKER_SAD) {
-               pat[0]= 8.0f;
-               pat[1]= 8.0f;
-
-               search[0]= 32.0f;
-               search[1]= 32.0f;
-       }
+       /* pick reasonable defaults */
+       float pat[2]= {5.5f, 5.5f}, search[2]= {25.5f, 25.5f}; /* TODO: move to default setting? */
 
        pat[0] /= (float)width;
        pat[1] /= (float)height;
@@ -180,6 +204,13 @@ MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, float x, flo
        track= MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track");
        strcpy(track->name, "Track");
 
+       /* default to KLT tracker */
+       track->tracker = TRACKER_KLT;
+       track->pyramid_levels = 2;
+
+       /* set SAD defaults even though it's not selected by default */
+       track->minimum_correlation= 0.75f;
+
        memset(&marker, 0, sizeof(marker));
        marker.pos[0]= x;
        marker.pos[1]= y;
@@ -554,21 +585,28 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u
                                        MovieTrackingTrack *new_track= BKE_tracking_copy_track(track);
 
                                        track_context->track= new_track;
-
 #ifdef WITH_LIBMV
                                        {
-                                               if(context->settings.tracker==TRACKER_KLT) {
+                                               if(track_context->track->tracker==TRACKER_KLT) {
                                                        float search_size_x= (track->search_max[0]-track->search_min[0])*width;
                                                        float search_size_y= (track->search_max[1]-track->search_min[1])*height;
                                                        float pattern_size_x= (track->pat_max[0]-track->pat_min[0])*width;
                                                        float pattern_size_y= (track->pat_max[1]-track->pat_min[1])*height;
 
-                                                       int level= (log(2.0f * MIN2(search_size_x, search_size_y) / MAX2(pattern_size_x, pattern_size_y))/M_LN2+0.5f);
-
-                                                       track_context->region_tracker= libmv_regionTrackerNew(100, level, 0.2);
+                                                       /* compute the maximum pyramid size */
+                                                       double search_to_pattern_ratio= MIN2(search_size_x,  search_size_y)
+                                                               / MAX2(pattern_size_x, pattern_size_y);
+                                                       double log2_search_to_pattern_ratio = log(floor(search_to_pattern_ratio)) / M_LN2;
+                                                       int max_pyramid_levels= floor(log2_search_to_pattern_ratio + 1);
+
+                                                       /* try to accomodate the user's choice of pyramid level in a way
+                                                        * that doesn't cause the coarsest pyramid pattern to be larger
+                                                        * than the search size */
+                                                       int level= MIN2(track_context->track->pyramid_levels, max_pyramid_levels);
+                                                       track_context->region_tracker= libmv_regionTrackerNew(100, level);
                                                }
-                                               else if(context->settings.tracker==TRACKER_SAD) {
-                                                       /* notfing to initialize */
+                                               else if(track_context->track->tracker==TRACKER_SAD) {
+                                                       /* nothing to initialize */
                                                }
                                        }
 #endif
@@ -1010,7 +1048,7 @@ int BKE_tracking_next(MovieTrackingContext *context)
                           marker->pos[1]<margin[1] || marker->pos[1]>1.0f-margin[1]) {
                                onbound= 1;
                        }
-                       else if(context->settings.tracker==TRACKER_KLT) {
+                       else if(track_context->track->tracker==TRACKER_KLT) {
                                int wndx, wndy;
                                float *patch_new;
 
@@ -1042,9 +1080,9 @@ int BKE_tracking_next(MovieTrackingContext *context)
 
                                MEM_freeN(patch_new);
                        }
-                       else if(context->settings.tracker==TRACKER_SAD) {
+                       else if(track_context->track->tracker==TRACKER_SAD) {
                                unsigned char *image_new;
-                               float corr;
+                               float correlation;
                                float warp[3][2]={{0}};
 
                                if(need_readjust) {
@@ -1095,12 +1133,12 @@ int BKE_tracking_next(MovieTrackingContext *context)
                                warp[2][0]= pos[0];
                                warp[2][1]= pos[1];
 
-                               corr= libmv_SADTrackerTrack(track_context->pattern, track_context->warped, image_new, width, width, height, warp);
+                               correlation= libmv_SADTrackerTrack(track_context->pattern, track_context->warped, image_new, width, width, height, warp);
 
                                x2= warp[2][0];
                                y2= warp[2][1];
 
-                               tracked= corr>=context->settings.corr;
+                               tracked= track_context->track->minimum_correlation < correlation;
 
                                if(tracked)
                                        get_warped(track_context, x2, y2, width, image_new);
index 30ae710ca1c65e394c5dcf6609c9df826372b0b0..90a48ec0be7b47b194b32c7b14c49c30031b1848 100644 (file)
@@ -594,6 +594,41 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
                glEnd();
        }
 
+       /* pyramid */
+       if((sel == TRACK_SELECTED(track) && sel && (sc->flag&SC_SHOW_PYRAMID_LEVELS) && (track->tracker==TRACKER_KLT))) {
+               if(track->flag&TRACK_LOCKED) {
+                       if(act) UI_ThemeColor(TH_ACT_MARKER);
+                       else if(track->pat_flag&SELECT) UI_ThemeColorShade(TH_LOCK_MARKER, 64);
+                       else UI_ThemeColor(TH_LOCK_MARKER);
+               }
+               else if(marker->flag&MARKER_DISABLED) {
+                       if(act) UI_ThemeColor(TH_ACT_MARKER);
+                       else if(track->pat_flag&SELECT) UI_ThemeColorShade(TH_DIS_MARKER, 128);
+                       else UI_ThemeColor(TH_DIS_MARKER);
+               } else {
+                       if(track->pat_flag&SELECT) glColor3fv(scol);
+                       else glColor3fv(col);
+               }
+
+               {
+                       int i = 0;
+                       glPushMatrix();
+                       glEnable(GL_LINE_STIPPLE);
+                       for (i = 1; i < track->pyramid_levels; ++i) {
+                               glScalef(2.0f, 2.0f, 1.0);
+                       }
+                       /* only draw a pattern for the coarsest level */
+                       glBegin(GL_LINE_LOOP);
+                               glVertex2f(track->pat_min[0], track->pat_min[1]);
+                               glVertex2f(track->pat_max[0], track->pat_min[1]);
+                               glVertex2f(track->pat_max[0], track->pat_max[1]);
+                               glVertex2f(track->pat_min[0], track->pat_max[1]);
+                       glEnd();
+                       glDisable(GL_LINE_STIPPLE);
+                       glPopMatrix();
+               }
+        }
+
        if(tiny)
                glDisable(GL_LINE_STIPPLE);
 
index 1e735e7f671c3efa06b2f8646f6272e679c75c30..da29241d6ada201ac8c4eff5538b841066f22210 100644 (file)
@@ -980,6 +980,7 @@ enum {
 #define SC_SHOW_FILTERS                        (1<<13)
 #define SC_SHOW_GRAPH_FRAMES   (1<<14)
 #define SC_SHOW_GRAPH_TRACKS   (1<<15)
+#define SC_SHOW_PYRAMID_LEVELS         (1<<16)
 
 /* SpaceClip->mode */
 #define SC_MODE_TRACKING               0
index 7fcbc6da996b0de752e3d9e90fc45d710a5f0bf3..b359ea3544d52046a7be16a16e844aaded994da0 100644 (file)
@@ -58,10 +58,10 @@ typedef struct MovieTrackingCamera {
 
        float sensor_width;     /* width of CCD sensor */
        float pixel_aspect;     /* pixel aspect ratio */
-       float pad2;
+       float pad;
        float focal;            /* focal length */
        short units;            /* units of focal length user is working with */
-       short pad;
+       short pad1;
        float principal[2];     /* principal point */
        float k1, k2, k3;       /* radial distortion */
 } MovieTrackingCamera;
@@ -98,21 +98,29 @@ typedef struct MovieTrackingTrack {
        short transflag;                                        /* transform flags */
        char pad3[2];
        float color[3];                                         /* custom color for track */
+
+       /* tracking algorithm to use; can be KLT or SAD */
+       short tracker;
+       char pad4[2];
+
+       /* ** SAD tracker settings ** */
+       float minimum_correlation;                      /* minimal correlation which is still treated as successful tracking */
+
+       /* ** KLT tracker settings ** */
+       int pyramid_levels;             /* number of pyramid levels to use for KLT tracking */
+       char pad5[4];
 } MovieTrackingTrack;
 
 typedef struct MovieTrackingSettings {
-       short tracker;  /* tracker to use */
-
        /* ** common tracker settings ** */
        short speed;                    /* speed of tracking */
        short frames_limit;             /* number of frames to be tarcked during single tracking session (if TRACKING_FRAMES_LIMIT is set) */
        short margin;                   /* margin from frame boundaries */
-       int adjframes;                  /* re-adjust every N frames */
+       char pad[2];
 
-       /* ** SAD tracker settings ** */
-       float corr;                                     /* minimal correlation which is still treated as successful tracking */
+       int adjframes;                  /* re-adjust every N frames */
 
-       /* ** reconstructionsettings ** */
+       /* ** reconstruction settings ** */
        int keyframe1, keyframe2;       /* two keyframes for reconstrution initialization */
 
        /* ** tool settings ** */
@@ -154,11 +162,12 @@ typedef struct MovieTrackingReconstruction {
 
 typedef struct MovieTracking {
        MovieTrackingSettings settings; /* different tracking-related settings */
+       char pad2[4];
+
        MovieTrackingCamera camera;             /* camera intrinsics */
        ListBase tracks;                                /* all tracks */
        MovieTrackingReconstruction reconstruction;     /* reconstruction data */
        MovieTrackingStabilization stabilization;       /* stabilization data */
-
        MovieTrackingTrack *act_track;          /* active track */
 } MovieTracking;
 
index daa76aec14bb0d917f7520c14af49e76ba881fa5..48fcd13f2ef94328ceb3644d4ecd4ee4af9a1bd5 100644 (file)
@@ -2798,6 +2798,12 @@ static void rna_def_space_clip(BlenderRNA *brna)
        RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_SHOW_MARKER_SEARCH);
        RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CLIP, NULL);
 
+       /* show pyramid */
+       prop= RNA_def_property(srna, "show_pyramid_levels", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Show Pyramid ", "Show patterns for each pyramid level for markers (KLT only)");
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_SHOW_PYRAMID_LEVELS);
+       RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CLIP, NULL);
+
        /* lock to selection */
        prop= RNA_def_property(srna, "lock_selection", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_ui_text(prop, "Lock to Selection", "Lock viewport to selected markers during playback");
index 8e589044790cbfdc5af2d9abd190aff2176df662..93538599f1dafd36fa1f7ee3534f435f90cb0376 100644 (file)
@@ -108,6 +108,23 @@ static void rna_tracking_trackerSearch_update(Main *UNUSED(bmain), Scene *UNUSED
        BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM);
 }
 
+static void rna_tracking_trackerAlgorithm_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+       MovieTrackingTrack *track= (MovieTrackingTrack *)ptr->data;
+
+        if(track->tracker==TRACKER_KLT)
+          BKE_tracking_clamp_track(track, CLAMP_PYRAMID_LEVELS);
+        else
+          BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM);
+}
+
+static void rna_tracking_trackerPyramid_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+       MovieTrackingTrack *track= (MovieTrackingTrack *)ptr->data;
+
+       BKE_tracking_clamp_track(track, CLAMP_PYRAMID_LEVELS);
+}
+
 static int rna_tracking_markers_length(PointerRNA *ptr)
 {
        MovieTrackingTrack *track= (MovieTrackingTrack *)ptr->data;
@@ -208,11 +225,6 @@ static void rna_def_trackingSettings(BlenderRNA *brna)
        StructRNA *srna;
        PropertyRNA *prop;
 
-       static EnumPropertyItem tracker_items[] = {
-               {TRACKER_SAD, "SAD", 0, "SAD", "Sum of Absolute Differences tracker"},
-               {TRACKER_KLT, "KLT", 0, "KLT", "Kanade–Lucas–Tomasi racker"},
-               {0, NULL, 0, NULL, NULL}};
-
        static EnumPropertyItem speed_items[] = {
                {0, "FASTEST", 0, "Fastest", "Track as fast as it's possible"},
            {TRACKING_SPEED_DOUBLE, "DOUBLE", 0, "Double", "Track with double speed"},
@@ -231,12 +243,6 @@ static void rna_def_trackingSettings(BlenderRNA *brna)
        srna= RNA_def_struct(brna, "MovieTrackingSettings", NULL);
        RNA_def_struct_ui_text(srna, "Movie tracking settings", "Match moving settings");
 
-       /* tracker */
-       prop= RNA_def_property(srna, "tracker", PROP_ENUM, PROP_NONE);
-       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
-       RNA_def_property_enum_items(prop, tracker_items);
-       RNA_def_property_ui_text(prop, "Tracker", "Tracking algorithm to use");
-
        /* speed */
        prop= RNA_def_property(srna, "speed", PROP_ENUM, PROP_NONE);
        RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
@@ -276,14 +282,6 @@ static void rna_def_trackingSettings(BlenderRNA *brna)
        RNA_def_property_int_sdna(prop, NULL, "keyframe2");
        RNA_def_property_ui_text(prop, "Keyframe B", "Second keyframe used for reconstruction initialization");
 
-       /* minmal correlation */
-       prop= RNA_def_property(srna, "correlation_min", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
-       RNA_def_property_float_sdna(prop, NULL, "corr");
-       RNA_def_property_range(prop, -1.0f, 1.0f);
-       RNA_def_property_ui_range(prop, -1.0f, 1.0f, 0.1, 3);
-       RNA_def_property_ui_text(prop, "Correlation", "Minimal value of correlation between mathed pattern and reference which is still treated as successful tracking");
-
        /* tool settings */
 
        /* distance */
@@ -422,6 +420,11 @@ static void rna_def_trackingTrack(BlenderRNA *brna)
        FunctionRNA *func;
        PropertyRNA *parm;
 
+       static EnumPropertyItem tracker_items[] = {
+               {TRACKER_SAD, "SAD", 0, "SAD", "Sum of Absolute Differences tracker"},
+               {TRACKER_KLT, "KLT", 0, "KLT", "Kanade–Lucas–Tomasi racker"},
+               {0, NULL, 0, NULL, NULL}};
+
        rna_def_trackingMarker(brna);
 
        srna= RNA_def_struct(brna, "MovieTrackingTrack", NULL);
@@ -466,6 +469,29 @@ static void rna_def_trackingTrack(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Search Max", "Right-bottom corner of search area in normalized coordinates relative to marker position");
        RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_trackerSearch_update");
 
+       /* tracking algorithm */
+       prop= RNA_def_property(srna, "tracker", PROP_ENUM, PROP_NONE);
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_enum_items(prop, tracker_items);
+       RNA_def_property_ui_text(prop, "Tracker", "Tracking algorithm to use");
+       RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_trackerAlgorithm_update");
+
+       /* pyramid level for pyramid klt tracking */
+       prop= RNA_def_property(srna, "pyramid_levels", PROP_INT, PROP_NONE);
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_int_sdna(prop, NULL, "pyramid_levels");
+       RNA_def_property_range(prop, 1, 16);
+       RNA_def_property_ui_text(prop, "Pyramid levels", "Number of pyramid levels for KLT tracking.");
+       RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_trackerPyramid_update");
+
+       /* minmal correlation - only used for SAD tracker */
+       prop= RNA_def_property(srna, "minimum_correlation", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_float_sdna(prop, NULL, "minimum_correlation");
+       RNA_def_property_range(prop, -1.0f, 1.0f);
+       RNA_def_property_ui_range(prop, -1.0f, 1.0f, 0.1, 3);
+       RNA_def_property_ui_text(prop, "Correlation", "Minimal value of correlation between mathed pattern and reference which is still treated as successful tracking");
+
        /* markers */
        prop= RNA_def_property(srna, "markers", PROP_COLLECTION, PROP_NONE);
        RNA_def_property_struct_type(prop, "MovieTrackingMarker");