Camera tracking integration
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 17 Aug 2011 07:16:11 +0000 (07:16 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 17 Aug 2011 07:16:11 +0000 (07:16 +0000)
===========================

- Bundle new version of libmv.
- Use image from nearest track's keyframe as reference for tracking.
  This should reduce drifting.
- Added option to switch to new SAD tracker.
  This tracker doesn't support pattern with variable size (yet?)
  and always uses pattern 16x16px.
  Tracker could be choosed in Tracking Settings panel.

12 files changed:
extern/libmv/CMakeLists.txt
extern/libmv/ChangeLog
extern/libmv/files.txt
extern/libmv/libmv-capi.cpp
extern/libmv/libmv-capi.h
extern/libmv/libmv/simple_pipeline/camera_intrinsics.h
extern/libmv/libmv/tracking/sad.cc [new file with mode: 0644]
extern/libmv/libmv/tracking/sad.h [new file with mode: 0644]
release/scripts/startup/bl_ui/space_clip.py
source/blender/blenkernel/intern/tracking.c
source/blender/makesdna/DNA_tracking_types.h
source/blender/makesrna/intern/rna_tracking.c

index 3574aac85d21240829179610463847af89a57cd4..56a6fbfe74119e019074ed63a3dc0c49b72f77ea 100644 (file)
@@ -52,6 +52,7 @@ set(SRC
        libmv/image/convolve.cc
        libmv/image/array_nd.cc
        libmv/tracking/pyramid_region_tracker.cc
+       libmv/tracking/sad.cc
        libmv/tracking/trklt_region_tracker.cc
        libmv/tracking/klt_region_tracker.cc
        libmv/tracking/retrack_region_tracker.cc
@@ -97,6 +98,7 @@ set(SRC
        libmv/image/image.h
        libmv/tracking/region_tracker.h
        libmv/tracking/retrack_region_tracker.h
+       libmv/tracking/sad.h
        libmv/tracking/pyramid_region_tracker.h
        libmv/tracking/trklt_region_tracker.h
        libmv/tracking/klt_region_tracker.h
index 228ae54c06a09b62073c10396824524bee2220c7..5db3c420ea59ce517595485e8686c52650130bbc 100644 (file)
@@ -1,3 +1,22 @@
+commit a1d9a8fa8b01ef7cf2a79b3b891633fc333fc9cf
+Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
+Date:   Tue Aug 16 21:24:51 2011 +0200
+
+    Fix SAD tracker. Pattern was transposed by affine pattern sampler.
+
+commit c3b794da2e7fd23f2fbdf90dbd71de0e6b3bc811
+Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
+Date:   Tue Aug 16 21:19:02 2011 +0200
+
+    Fix SAD tracker. Pattern was transposed by affine pattern sampler.
+
+commit a9b61bf3356f27174cdd983f562f99c3a6a2cc35
+Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
+Date:   Sun Aug 14 09:56:51 2011 +0200
+
+    Clarify CameraIntrinsics documentation.
+    Edit CameraInstrinsics test to fail.
+
 commit 10bdad9ad2cea2603896263cde5a5339169a9af0
 Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
 Date:   Fri Aug 12 21:05:32 2011 +0200
@@ -342,79 +361,3 @@ Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
 Date:   Sun Jul 17 16:35:48 2011 +0200
 
     Use deprecated FFmpeg API.
-
-commit 09b090a20134a8ccef273d802752bbf475ff5280
-Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
-Date:   Sat Jul 16 21:19:14 2011 +0200
-
-    Fix loading cache directly after creation.
-
-commit 1190584f6ca60fb74188cac36c61333951244026
-Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
-Date:   Sat Jul 16 20:02:36 2011 +0200
-
-    Add custom FileDialog to handle multiple files and folders selection in the same dialog
-
-commit 50504af3d0fc11665483aed524d52d076f38ffa8
-Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
-Date:   Fri Jul 15 23:34:41 2011 +0200
-
-    Fix mistake.
-
-commit a8e322a2c37cc87acd864d94a354334d611b9750
-Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
-Date:   Fri Jul 15 22:25:51 2011 +0200
-
-    Use cache even on first run (i.e don't load all images on the heap).
-
-commit 66ac3b5833a1fd4fbd97b082db6ddf859b33811c
-Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
-Date:   Fri Jul 15 21:15:45 2011 +0200
-
-    Improve Zoom View.
-
-commit dec996966d5466717a813da2d8b9962115dfc8ac
-Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
-Date:   Fri Jul 15 20:04:06 2011 +0200
-
-    Detect API documentation.
-
-commit bfc07bd0940bba0d5439ccd0297368607db514be
-Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
-Date:   Fri Jul 15 16:22:52 2011 +0200
-
-    Refactor Qt Tracker.
-    Create Detect API.
-    Improve CameraIntrinsics API.
-    Put Calibration settings UI in a QDockWidget.
-    Support anamorphic.
-    
-    TODO: Finish new Zoom widget.
-
-commit e59595806c045916ab4ef15ef7047c1a728b2da9
-Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
-Date:   Thu Jul 14 22:29:06 2011 +0200
-
-    Use FAST detector.
-    
-    FAST is much faster and works much better than the "Good Features to Track algorithm".
-
-commit 17c036e9f8c6529c2f771fdd9dc73f3022e36c77
-Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
-Date:   Wed Jul 13 22:23:40 2011 +0200
-
-    Add visualization of image filtering operations.
-
-commit c4f71e17b6b72acc0f863906c01c87d53e8bbb2c
-Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
-Date:   Wed Jul 13 10:37:26 2011 +0200
-
-    Simplify feature detection.
-
-commit d8109b7a4fede1660e0dbd73735f1a9e3fd79eec
-Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
-Date:   Wed Jul 13 10:21:52 2011 +0200
-
-    Add feature detection.
-    
-    Remove unused keyframe selection code.
index 791fe98469db2cf4fd90552a239c7f91b23d2f9b..fe6be5d0b20e9aa990d57bbe7832fc0b15b14ca5 100644 (file)
@@ -34,9 +34,11 @@ libmv/image/sample.h
 libmv/image/image.h
 libmv/tracking/pyramid_region_tracker.cc
 libmv/tracking/region_tracker.h
+libmv/tracking/sad.cc
 libmv/tracking/trklt_region_tracker.cc
 libmv/tracking/klt_region_tracker.cc
 libmv/tracking/retrack_region_tracker.h
+libmv/tracking/sad.h
 libmv/tracking/pyramid_region_tracker.h
 libmv/tracking/trklt_region_tracker.h
 libmv/tracking/retrack_region_tracker.cc
index 0d1e381a10387b9e0c47363754aa98cdcfe4635a..d728d0b45d77d1e43d2ff0b3acae52c1675d1930 100644 (file)
@@ -40,6 +40,8 @@
 #include "libmv/tracking/pyramid_region_tracker.h"
 #include "libmv/tracking/retrack_region_tracker.h"
 
+#include "libmv/tracking/sad.h"
+
 #include "libmv/simple_pipeline/tracks.h"
 #include "libmv/simple_pipeline/initialize_reconstruction.h"
 #include "libmv/simple_pipeline/bundle.h"
@@ -307,6 +309,31 @@ void libmv_regionTrackerDestroy(libmv_RegionTracker *libmv_tracker)
 
 /* ************ Tracks ************ */
 
+void libmv_SADSamplePatternByte(unsigned char *image, int stride,
+                       float warp[3][3], unsigned char *pattern)
+{
+       float mat3[9];
+
+       memcpy(mat3, warp, sizeof(float)*9);
+
+       libmv::SamplePattern(image, stride, mat3, pattern);
+}
+
+int libmv_SADTrackerTrack(unsigned char *pattern, unsigned char *image, int stride,
+                       int width, int height, double *x, double *y)
+{
+       float x2, y2;
+
+       int result = libmv::Track(pattern, image, stride, width, height, &x2, &y2);
+
+       *x= x2;
+       *y= y2;
+
+       return result;
+}
+
+/* ************ Tracks ************ */
+
 libmv_Tracks *libmv_tracksNew(void)
 {
        libmv::Tracks *libmv_tracks = new libmv::Tracks();
index a63cbd020830a289ff5680d0c34361f0aeb920c9..87ae90d6ef64af0950cae400ada2f0379f8e8bb1 100644 (file)
@@ -50,6 +50,12 @@ int libmv_regionTrackerTrack(struct libmv_RegionTracker *libmv_tracker, const fl
                        double  x1, double  y1, double *x2, double *y2);
 void libmv_regionTrackerDestroy(struct libmv_RegionTracker *libmv_tracker);
 
+/* SAD Tracker */
+void libmv_SADSamplePatternByte(unsigned char *image, int stride,
+                       float warp[3][3], unsigned char *pattern);
+int libmv_SADTrackerTrack(unsigned char *pattern, unsigned char *image, int stride,
+                       int width, int height, double *x, double *y);
+
 /* Tracks */
 struct libmv_Tracks *libmv_tracksNew(void);
 void libmv_tracksInsert(struct libmv_Tracks *libmv_tracks, int image, int track, double x, double y);
index 6ff40fb723210a0d37885c33158d3aa33a59238c..29bc8a1cea471abede8e64ff951e118c9a37271c 100644 (file)
@@ -65,7 +65,7 @@ class CameraIntrinsics {
   /*!
       Apply camera intrinsics to the normalized point to get image coordinates.
 
-      This applies the camera intrinsics to a point which is in normalized
+      This applies the lens distortion to a point which is in normalized
       camera coordinates (i.e. the principal point is at (0, 0)) to get image
       coordinates in pixels.
   */
@@ -75,7 +75,7 @@ class CameraIntrinsics {
   /*!
       Invert camera intrinsics on the image point to get normalized coordinates.
 
-      This reverses the effect of camera intrinsics on a point which is in image
+      This reverses the effect of lens distortion on a point which is in image
       coordinates to get normalized camera coordinates.
   */
   void InvertIntrinsics(double image_x, double image_y,
diff --git a/extern/libmv/libmv/tracking/sad.cc b/extern/libmv/libmv/tracking/sad.cc
new file mode 100644 (file)
index 0000000..0bcf3cb
--- /dev/null
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (c) 2011 libmv authors.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to
+** deal in the Software without restriction, including without limitation the
+** rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+** sell copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+** IN THE SOFTWARE.
+**
+****************************************************************************/
+
+#include "libmv/tracking/sad.h"
+#include <stdlib.h>
+#include <math.h>
+
+namespace libmv {
+
+struct vec2 {
+  float x,y;
+  inline vec2(float x, float y):x(x),y(y){}
+};
+static vec2 operator*(mat3 m, vec2 v) {
+  float z = v.x*m[6]+v.y*m[7]+m[8];
+  return vec2((v.x*m[0]+v.y*m[1]+m[2])/z,(v.x*m[3]+v.y*m[4]+m[5])/z);
+}
+
+//! fixed point bilinear sample with precision k
+template <int k> inline int sample(const ubyte* image,int stride, int x, int y, int u, int v) {
+  const ubyte* s = &image[y*stride+x];
+  return ((s[     0] * (k-u) + s[       1] * u) * (k-v)
+        + (s[stride] * (k-u) + s[stride+1] * u) * (  v) ) / (k*k);
+}
+
+void SamplePattern(const ubyte* image, int stride, mat3 warp, ubyte* pattern) {
+  const int k = 256;
+  for (int i = 0; i < 16; i++) for (int j = 0; j < 16; j++) {
+    vec2 p = warp*vec2(j-8,i-8);
+    int fx = lround(p.x*k), fy = lround(p.y*k);
+    int ix = fx/k, iy = fy/k;
+    int u = fx%k, v = fy%k;
+    pattern[i*16+j] = sample<k>(image,stride,ix,iy,u,v);
+  }
+}
+
+#ifdef __SSE2__
+#include <emmintrin.h>
+static uint SAD(const ubyte* pattern, const ubyte* image, int stride) {
+  __m128i a = _mm_setzero_si128();
+  for(int i = 0; i < 16; i++) {
+    a = _mm_adds_epu16(a, _mm_sad_epu8( _mm_loadu_si128((__m128i*)(pattern+i*16)),
+                                        _mm_loadu_si128((__m128i*)(image+i*stride))));
+  }
+  return _mm_extract_epi16(a,0) + _mm_extract_epi16(a,4);
+}
+#else
+static uint SAD(const ubyte* pattern, const ubyte* image, int stride) {
+  uint sad=0;
+  for(int i = 0; i < 16; i++) {
+    for(int j = 0; j < 16; j++) {
+      sad += abs((int)pattern[i*16+j] - image[i*stride+j]);
+    }
+  }
+  return sad;
+}
+#endif
+
+//float sq( float x ) { return x*x; }
+bool Track(const ubyte* pattern, const ubyte* image, int stride, int w, int h, float* px, float* py) {
+  int ix = *px-8, iy = *py-8;
+  uint min=-1;
+  // integer pixel
+  for(int y = 0; y < h-16; y++) {
+    for(int x = 0; x < w-16; x++) {
+      uint d = SAD(pattern,&image[y*stride+x],stride); //image L1 distance
+      //d += sq(x-w/2-8)+sq(y-h/2-8); //spatial L2 distance
+      if(d < min) {
+        min = d;
+        ix = x, iy = y;
+      }
+    }
+  }
+
+  const int kPrecision = 4; //subpixel precision in bits
+  const int kScale = 1<<kPrecision;
+  int fx=0,fy=0;
+  for(int k = 1; k <= kPrecision; k++) {
+    fx *= 2, fy *= 2;
+    int nx = fx, ny = fy;
+    int p = kPrecision-k;
+    for(int y = -1; y <= 1; y++) {
+      for(int x = -1; x <= 1; x++) {
+        uint sad=0;
+        int sx = ix, sy = iy;
+        int u = (fx+x)<<p, v = (fy+y)<<p;
+        if( u < 0 ) u+=kScale, sx--;
+        if( v < 0 ) v+=kScale, sy--;
+        for(int i = 0; i < 16; i++) {
+          for(int j = 0; j < 16; j++) {
+            sad += abs((int)pattern[i*16+j] - sample<kScale>(image,stride,sx+j,sy+i,u,v));
+          }
+        }
+        if(sad < min) {
+          min = sad;
+          nx = fx + x, ny = fy + y;
+        }
+      }
+    }
+    fx = nx, fy = ny;
+  }
+
+  *px = float((ix*kScale)+fx)/kScale+8;
+  *py = float((iy*kScale)+fy)/kScale+8;
+  return true;
+}
+
+}  // namespace libmv
diff --git a/extern/libmv/libmv/tracking/sad.h b/extern/libmv/libmv/tracking/sad.h
new file mode 100644 (file)
index 0000000..4b82d6c
--- /dev/null
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (c) 2011 libmv authors.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to
+** deal in the Software without restriction, including without limitation the
+** rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+** sell copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+** IN THE SOFTWARE.
+**
+****************************************************************************/
+
+#ifndef LIBMV_TRACKING_SAD_H_
+#define LIBMV_TRACKING_SAD_H_
+
+#ifdef __cplusplus
+namespace libmv {
+#endif
+
+typedef unsigned char ubyte;
+typedef float mat3[9];
+
+/*!
+    Sample \a pattern from \a image.
+
+    \a pattern is a 16x16 buffer
+    \a warp is the transformation to apply when sampling the \a pattern in \a image.
+
+    \note \a warp might be used by higher level tracking methods (e.g planar)
+*/
+void SamplePattern(const ubyte* image, int stride, mat3 warp, ubyte* pattern);
+
+/*!
+    Track \a pattern in \a image.
+
+    This template matcher computes the
+    \link http://en.wikipedia.org/wiki/Sum_of_absolute_differences Sum of Absolute Differences (SAD) \endlink
+    for each integer pixel position in the search region and then iteratively
+    refine subpixel position using a square search.
+    A similar method is used for motion estimation in video encoders.
+
+    \a pattern is a 16x16 single channel image to track.
+    \a x, \a y is the initial estimated position in \a image.
+    On return, \a x, \a y is the tracked position.
+    \a image is a reference to the single channel image to search.
+    \a stride is size of \a image lines.
+
+    \note For a 16x speedup, compile this tracker with SSE2 support.
+    \note \a stride allow you to reference your search region instead of copying.
+*/
+bool Track(const ubyte* pattern, const ubyte* image, int stride, int width, int height, float* x, float* y);
+
+#ifdef __cplusplus
+}  // namespace libmv
+#endif
+
+#endif  // LIBMV_TRACKING_SAD_H_
index a778eb43792a1e2efd786d7553cbd828d92dff14..72b9b8f6bbb612dc61961a100df0380fe90284e8 100644 (file)
@@ -518,6 +518,7 @@ class CLIP_PT_track_settings(Panel):
         clip = context.space_data.clip
         settings = clip.tracking.settings
 
+        layout.prop(settings, "tracker")
         layout.prop(settings, "speed")
         layout.prop(settings, "frames_limit")
 
index dcce824c46e71ed34aa3b40a39493fea354cf1f1..c5a80d1c96f593d2cd4b314e4733b27f1e4b979a 100644 (file)
@@ -461,7 +461,12 @@ typedef struct TrackContext {
        MovieTrackingTrack *track;
 
 #ifdef WITH_LIBMV
+       /* ** KLT tracker ** */
        struct libmv_RegionTracker *region_tracker;
+       float *patch;                   /* keyframed patch */
+
+       /* ** SAD tracker ** */
+       unsigned char *pattern; /* keyframed pattern */
 #endif
 } TrackContext;
 
@@ -526,14 +531,19 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u
 
 #ifdef WITH_LIBMV
                                        {
-                                               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;
-
-                                               track_context->region_tracker= libmv_regionTrackerNew(100, level, 0.2);
+                                               if(context->settings.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;
+
+                                                       track_context->region_tracker= libmv_regionTrackerNew(100, level, 0.2);
+                                               }
+                                               else if(context->settings.tracker==TRACKER_SAD) {
+                                                       /* notfing to initialize */
+                                               }
                                        }
 #endif
 
@@ -562,7 +572,14 @@ void BKE_tracking_context_free(MovieTrackingContext *context)
                BKE_tracking_free_track(context->track_context[a].track);
 
 #if WITH_LIBMV
-               libmv_regionTrackerDestroy(track_context->region_tracker);
+               if(track_context->region_tracker)
+                       libmv_regionTrackerDestroy(track_context->region_tracker);
+
+               if(track_context->patch)
+                       MEM_freeN(track_context->patch);
+
+               if(track_context->pattern)
+                       MEM_freeN(track_context->pattern);
 #endif
 
                MEM_freeN(track_context->track);
@@ -696,6 +713,72 @@ static float *acquire_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mo
 
        return pixels;
 }
+
+static unsigned char *acquire_search_bytebuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
+                       int *width_r, int *height_r, float pos[2], int origin[2])
+{
+       ImBuf *tmpibuf;
+       unsigned char *pixels, *fp;
+       int x, y, width, height;
+
+       width= (track->search_max[0]-track->search_min[0])*ibuf->x;
+       height= (track->search_max[1]-track->search_min[1])*ibuf->y;
+
+       tmpibuf= BKE_tracking_acquire_search_imbuf(ibuf, track, marker, 0, pos, origin);
+       disable_imbuf_channels(tmpibuf, track);
+
+       *width_r= width;
+       *height_r= height;
+
+       fp= pixels= MEM_callocN(width*height*sizeof(unsigned char), "tracking byteBuf");
+       for(y= 0; y<(int)height; y++) {
+               for (x= 0; x<(int)width; x++) {
+                       int pixel= tmpibuf->x*y + x;
+
+                       if(tmpibuf->rect_float) {
+                               float *rrgbf= ibuf->rect_float + pixel*4;
+
+                               *fp= (0.2126*rrgbf[0] + 0.7152*rrgbf[1] + 0.0722*rrgbf[2]);
+                       } else {
+                               char *rrgb= (char*)tmpibuf->rect + pixel*4;
+
+                               *fp= (0.2126*rrgb[0] + 0.7152*rrgb[1] + 0.0722*rrgb[2]);
+                       }
+
+                       fp++;
+               }
+       }
+
+       IMB_freeImBuf(tmpibuf);
+
+       return pixels;
+}
+
+static ImBuf *acquire_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, MovieTrackingMarker *marker)
+{
+       int framenr_old= context->user.framenr, framenr= marker->framenr;
+       int a= marker-track->markers;
+       ImBuf *ibuf;
+
+       while(a>=0 && a<track->markersnr) {
+               if(marker->flag&MARKER_TRACKED) {
+                       framenr= marker->framenr;
+                       break;
+               }
+
+               if(context->backwards) a++;
+               else a--;
+       }
+
+       context->user.framenr= framenr;
+
+       ibuf= BKE_movieclip_acquire_ibuf_flag(context->clip, &context->user, 0);
+
+       context->user.framenr= framenr_old;
+
+       return ibuf;
+}
+
 #endif
 
 void BKE_tracking_sync(MovieTrackingContext *context)
@@ -793,7 +876,7 @@ void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context)
 
 int BKE_tracking_next(MovieTrackingContext *context)
 {
-       ImBuf *ibuf, *ibuf_new;
+       ImBuf *ibuf_new;
        int curfra= context->user.framenr;
        int a, ok= 0;
 
@@ -801,19 +884,14 @@ int BKE_tracking_next(MovieTrackingContext *context)
        if(!context->num_tracks)
                return 0;
 
-       ibuf= BKE_movieclip_acquire_ibuf_flag(context->clip, &context->user, 0);
-       if(!ibuf) return 0;
-
        if(context->backwards) context->user.framenr--;
        else context->user.framenr++;
 
        ibuf_new= BKE_movieclip_acquire_ibuf_flag(context->clip, &context->user, 0);
-       if(!ibuf_new) {
-               IMB_freeImBuf(ibuf);
+       if(!ibuf_new)
                return 0;
-       }
 
-       #pragma omp parallel for private(a) shared(ibuf, ibuf_new, ok)
+       #pragma omp parallel for private(a) shared(ibuf_new, ok) if(context->num_tracks>1)
        for(a= 0; a<context->num_tracks; a++) {
                TrackContext *track_context= &context->track_context[a];
                MovieTrackingTrack *track= track_context->track;
@@ -821,28 +899,70 @@ int BKE_tracking_next(MovieTrackingContext *context)
 
                if(marker && (marker->flag&MARKER_DISABLED)==0 && marker->framenr==curfra) {
 #ifdef WITH_LIBMV
-                       int width, height, origin[2];
+                       int width, height, origin[2], tracked= 0;
                        float pos[2];
-                       float *patch, *patch_new;
                        double x1, y1, x2, y2;
-                       int wndx, wndy;
+                       ImBuf *ibuf= NULL;
                        MovieTrackingMarker marker_new;
 
-                       patch= acquire_search_floatbuf(ibuf, track, marker, &width, &height, pos, origin);
-                       patch_new= acquire_search_floatbuf(ibuf_new, track, marker, &width, &height, pos, origin);
+                       if(context->settings.tracker==TRACKER_KLT) {
+                               int wndx, wndy;
+                               float *patch_new;
+
+                               if(!track_context->patch) {
+                                       /* calculate patch for keyframed position */
+                                       ibuf= acquire_keyframed_ibuf(context, track, marker);
+                                       track_context->patch= acquire_search_floatbuf(ibuf, track, marker, &width, &height, pos, origin);
+                                       IMB_freeImBuf(ibuf);
+                               }
+
+                               patch_new= acquire_search_floatbuf(ibuf_new, track, marker, &width, &height, pos, origin);
+
+                               x1= pos[0];
+                               y1= pos[1];
+
+                               x2= x1;
+                               y2= y1;
+
+                               wndx= (int)((track->pat_max[0]-track->pat_min[0])*ibuf_new->x)/2;
+                               wndy= (int)((track->pat_max[1]-track->pat_min[1])*ibuf_new->y)/2;
+
+                               tracked= libmv_regionTrackerTrack(track_context->region_tracker, track_context->patch, patch_new,
+                                                       width, height, MAX2(wndx, wndy), x1, y1, &x2, &y2);
+
+                               MEM_freeN(patch_new);
+                       }
+                       else if(context->settings.tracker==TRACKER_SAD) {
+                               unsigned char *image_new;
 
-                       x1= pos[0];
-                       y1= pos[1];
+                               if(track_context->pattern==NULL) {
+                                       unsigned char *image;
+                                       float warp[3][3];
 
-                       x2= x1;
-                       y2= y1;
+                                       /* calculate pattern for keyframed position */
 
-                       wndx= (int)((track->pat_max[0]-track->pat_min[0])*ibuf->x)/2;
-                       wndy= (int)((track->pat_max[1]-track->pat_min[1])*ibuf->y)/2;
+                                       ibuf= acquire_keyframed_ibuf(context, track, marker);
+                                       image= acquire_search_bytebuf(ibuf, track, marker, &width, &height, pos, origin);
 
-                       if(libmv_regionTrackerTrack(track_context->region_tracker, patch, patch_new,
-                                               width, height, MAX2(wndx, wndy),
-                                               x1, y1, &x2, &y2)) {
+                                       unit_m3(warp);
+                                       warp[0][2]= pos[0];
+                                       warp[1][2]= pos[1];
+
+                                       track_context->pattern= MEM_callocN(sizeof(unsigned char)*16*16, "trackking pattern");
+                                       libmv_SADSamplePatternByte(image, width, warp, track_context->pattern);
+
+                                       MEM_freeN(image);
+                                       IMB_freeImBuf(ibuf);
+                               }
+
+                               image_new= acquire_search_bytebuf(ibuf_new, track, marker, &width, &height, pos, origin);
+
+                               tracked= libmv_SADTrackerTrack(track_context->pattern, image_new, width, width, height, &x2, &y2);
+
+                               MEM_freeN(image_new);
+                       }
+
+                       if(tracked) {
                                memset(&marker_new, 0, sizeof(marker_new));
                                marker_new.pos[0]= (origin[0]+x2)/ibuf_new->x;
                                marker_new.pos[1]= (origin[1]+y2)/ibuf_new->y;
@@ -870,15 +990,11 @@ int BKE_tracking_next(MovieTrackingContext *context)
                                }
                        }
 
-                       MEM_freeN(patch);
-                       MEM_freeN(patch_new);
-
                        ok= 1;
 #endif
                }
        }
 
-       IMB_freeImBuf(ibuf);
        IMB_freeImBuf(ibuf_new);
 
        return ok;
index 83fe543fdcd6278a2a5f55389de65a5cc0cbba48..087f0b4b3bf861dd825f54daeba6a05d5ee72a99 100644 (file)
@@ -100,6 +100,9 @@ typedef struct MovieTrackingTrack {
 } MovieTrackingTrack;
 
 typedef struct MovieTrackingSettings {
+       short tracker;  /* tracker to use */
+       short pad;
+
        short speed;    /* speed of tracking */
        short frames_limit;     /* number of frames to be tarcked during single tracking session (if TRACKING_FRAMES_LIMIT is set) */
        int keyframe1, keyframe2;       /* two keyframes for reconstrution initialization */
@@ -112,8 +115,6 @@ typedef struct MovieTrackingSettings {
        /* cleanup */
        int clean_frames, clean_action;
        float clean_error;
-
-       int pad;
 } MovieTrackingSettings;
 
 typedef struct MovieTrackingStabilization {
@@ -169,6 +170,10 @@ enum {
 #define TRACK_CUSTOMCOLOR      (1<<7)
 #define TRACK_USE_2D_STAB      (1<<8)
 
+/* MovieTrackingSettings->tracker */
+#define TRACKER_KLT            0
+#define TRACKER_SAD            1
+
 /* MovieTrackingSettings->speed */
 #define TRACKING_SPEED_FASTEST         0
 #define TRACKING_SPEED_REALTIME                1
index 5031f041999cc526fa20d1b76c702cf71332292a..c46e9a86ae0037b02436a64656f1a537d267063e 100644 (file)
@@ -217,6 +217,11 @@ static void rna_def_trackingSettings(BlenderRNA *brna)
        StructRNA *srna;
        PropertyRNA *prop;
 
+       static EnumPropertyItem tracker_items[] = {
+               {TRACKER_KLT, "KLT", 0, "KLT", "Kanade–Lucas–Tomasi racker"},
+               {TRACKER_SAD, "SAD", 0, "SAD", "Sum of Absolute Differences tracker"},
+               {0, NULL, 0, NULL, NULL}};
+
        static EnumPropertyItem speed_items[] = {
                {0, "FASTEST", 0, "Fastest", "Track as fast as it's possible"},
                {TRACKING_SPEED_REALTIME, "REALTIME", 0, "Realtime", "Track with realtime speed"},
@@ -225,15 +230,21 @@ static void rna_def_trackingSettings(BlenderRNA *brna)
                {0, NULL, 0, NULL, NULL}};
 
        static EnumPropertyItem cleanup_items[] = {
-                       {TRACKING_CLEAN_SELECT, "SELECT", 0, "Select", "Select un-clean tracks"},
-                       {TRACKING_CLEAN_DELETE_TRACK, "DELETE_TRACK", 0, "Delete Track", "Delete un-clean tracks"},
-                       {TRACKING_CLEAN_DELETE_SEGMENT, "DELETE_SEGMENTS", 0, "Delete Segments", "Delete un-clean segments of tracks"},
-                       {0, NULL, 0, NULL, NULL}
+               {TRACKING_CLEAN_SELECT, "SELECT", 0, "Select", "Select un-clean tracks"},
+               {TRACKING_CLEAN_DELETE_TRACK, "DELETE_TRACK", 0, "Delete Track", "Delete un-clean tracks"},
+               {TRACKING_CLEAN_DELETE_SEGMENT, "DELETE_SEGMENTS", 0, "Delete Segments", "Delete un-clean segments of tracks"},
+               {0, NULL, 0, NULL, NULL}
        };
 
        srna= RNA_def_struct(brna, "MovieTrackingSettings", NULL);
        RNA_def_struct_ui_text(srna, "Movie tracking settings", "Match-moving tracking 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);