Homography correction for track preview widget
authorSergey Sharybin <sergey.vfx@gmail.com>
Sat, 9 Jun 2012 11:14:36 +0000 (11:14 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Sat, 9 Jun 2012 11:14:36 +0000 (11:14 +0000)
Use homography transformation for pattern displayed in track preview widget.
Sampling of this pattern happens to resolution of preview widget itself,
which implied some bigger changes in how scopes are working:

- Instead of real pattern store search area in BKE_movieclip_update_scopes,
  which is later used for sampling pattern.
- Sampling of pattern happens in ui_draw_but_TRACKPREVIEW from search area
  which allows to sample it to actual resolution of preview widget.
- If size of preview widget is not changing, this sampled pattern wouldn't
  be re-sampled until scopes are tagged to update.

There are some issues with pattern sampling which seems to happen SamplePlanarPatch,
changing linear sampling to nearest removes that unwanted 1px offset.

Left commented saving of sampled image in ui_draw_but_TRACKPREVIEW which should
help figuring the issue out.

13 files changed:
extern/libmv/libmv-capi.cpp
extern/libmv/libmv-capi.h
extern/libmv/libmv/tracking/track_region.cc
extern/libmv/libmv/tracking/track_region.h
source/blender/blenkernel/BKE_tracking.h
source/blender/blenkernel/intern/movieclip.c
source/blender/blenkernel/intern/tracking.c
source/blender/blenloader/intern/readfile.c
source/blender/compositor/operations/COM_KeyingScreenOperation.cpp
source/blender/editors/interface/interface_draw.c
source/blender/editors/space_clip/space_clip.c
source/blender/makesdna/DNA_movieclip_types.h
source/blender/nodes/composite/nodes/node_composite_keyingscreen.c

index eba4698f1986410143edd2295ed650fe6ee52cef..ffa065f08fe372efcfabd1a89ff5c463e405483d 100644 (file)
@@ -163,15 +163,30 @@ libmv_RegionTracker *libmv_bruteRegionTrackerNew(int half_window_size, double mi
        return (libmv_RegionTracker *)brute_region_tracker;
 }
 
-static void floatBufToImage(const float *buf, int width, int height, libmv::FloatImage *image)
+static void floatBufToImage(const float *buf, int width, int height, int channels, libmv::FloatImage *image)
 {
-       int x, y, a = 0;
+       int x, y, k, a = 0;
 
-       image->resize(height, width);
+       image->Resize(height, width, channels);
 
        for (y = 0; y < height; y++) {
                for (x = 0; x < width; x++) {
-                       (*image)(y, x, 0) = buf[a++];
+                       for (k = 0; k < channels; k++) {
+                               (*image)(y, x, k) = buf[a++];
+                       }
+               }
+       }
+}
+
+static void imageToFloatBuf(const libmv::FloatImage *image, int channels, float *buf)
+{
+       int x, y, k, a = 0;
+
+       for (y = 0; y < image->Height(); y++) {
+               for (x = 0; x < image->Width(); x++) {
+                       for (k = 0; k < channels; k++) {
+                               buf[a++] = (*image)(y, x, k);
+                       }
                }
        }
 }
@@ -307,8 +322,8 @@ int libmv_regionTrackerTrack(libmv_RegionTracker *libmv_tracker, const float *im
        libmv::RegionTracker *region_tracker = (libmv::RegionTracker *)libmv_tracker;
        libmv::FloatImage old_patch, new_patch;
 
-       floatBufToImage(ima1, width, height, &old_patch);
-       floatBufToImage(ima2, width, height, &new_patch);
+       floatBufToImage(ima1, width, height, 1, &old_patch);
+       floatBufToImage(ima2, width, height, 1, &new_patch);
 
 #if !defined(DUMP_FAILURE) && !defined(DUMP_ALWAYS)
        return region_tracker->Track(old_patch, new_patch, x1, y1, x2, y2);
@@ -385,8 +400,8 @@ int libmv_trackRegion(const struct libmv_trackRegionOptions *options,
 
        /* Convert from raw float buffers to libmv's FloatImage. */
        libmv::FloatImage old_patch, new_patch;
-       floatBufToImage(image1, width, height, &old_patch);
-       floatBufToImage(image2, width, height, &new_patch);
+       floatBufToImage(image1, width, height, 1, &old_patch);
+       floatBufToImage(image2, width, height, 1, &new_patch);
 
        libmv::TrackRegionResult track_region_result;
        libmv::TrackRegion(old_patch, new_patch, xx1, yy1, track_region_options, xx2, yy2, &track_region_result);
@@ -420,6 +435,21 @@ int libmv_trackRegion(const struct libmv_trackRegionOptions *options,
        return tracking_result;
 }
 
+void libmv_samplePlanarPatch(const float *image, int width, int height,
+                             int channels, const double *xs, const double *ys,
+                             int num_samples_x, int num_samples_y, float *patch,
+                             double *warped_position_x, double *warped_position_y)
+{
+       libmv::FloatImage libmv_image, libmv_patch;
+
+       floatBufToImage(image, width, height, channels, &libmv_image);
+
+       libmv::SamplePlanarPatch(libmv_image, xs, ys, num_samples_x, num_samples_y,
+                                &libmv_patch, warped_position_x, warped_position_y);
+
+       imageToFloatBuf(&libmv_patch, channels, patch);
+}
+
 /* ************ Tracks ************ */
 
 libmv_Tracks *libmv_tracksNew(void)
index bbd8f0c30d07454edfa60c5b9b3cc43f378954c1..6f4b5dea3849cd6bf33a104c4ba86902b0311ba8 100644 (file)
@@ -71,6 +71,11 @@ int libmv_trackRegion(const struct libmv_trackRegionOptions *options,
                       struct libmv_trackRegionResult *result,
                       double *x2, double *y2);
 
+void libmv_samplePlanarPatch(const float *image, int width, int height,
+                             int channels, const double *xs, const double *ys,
+                             int num_samples_x, int num_samples_y, float *patch,
+                             double *warped_position_x, double *warped_position_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 b9e4f883e78e21002dc4ac0fc4a3ff45cde20cf2..679646c4c37e210b8fe5895d9982923056bcc7c5 100644 (file)
@@ -1252,7 +1252,8 @@ void TrackRegion(const FloatImage &image1,
 bool SamplePlanarPatch(const FloatImage &image,
                        const double *xs, const double *ys,
                        int num_samples_x, int num_samples_y,
-                       FloatImage *patch) {
+                       FloatImage *patch,
+                       double *warped_position_x, double *warped_position_y) {
   // Bail early if the points are outside the image.
   if (!AllInBounds(image, xs, ys)) {
     LG << "Can't sample patch: out of bounds.";
@@ -1278,6 +1279,13 @@ bool SamplePlanarPatch(const FloatImage &image,
                    &(*patch)(r, c, 0));
     }
   }
+
+  Vec3 warped_position = canonical_homography.inverse() * Vec3(xs[4], ys[4], 1);
+  warped_position /= warped_position(2);
+
+  *warped_position_x = warped_position(0);
+  *warped_position_y = warped_position(1);
+
   return true;
 }
 
index c23cde6000fad861779644b5e86480242a7f274c..04e7c7e1403ca66777500191e7bd305abb312da3 100644 (file)
@@ -121,7 +121,8 @@ void TrackRegion(const FloatImage &image1,
 bool SamplePlanarPatch(const FloatImage &image,
                        const double *xs, const double *ys,
                        int num_samples_x, int num_samples_y,
-                       FloatImage *patch);
+                       FloatImage *patch,
+                       double *warped_position_x, double *warped_position_y);
 
 }  // namespace libmv
 
index 25723b8b0e89cb67b90ae4ce0e37ac6995301de8..8c28dd93a5eceb931644c058c9d7bc60bc56e85a 100644 (file)
@@ -71,13 +71,13 @@ void BKE_tracking_clear_path(struct MovieTrackingTrack *track, int ref_frame, in
 void BKE_tracking_join_tracks(struct MovieTrackingTrack *dst_track, struct MovieTrackingTrack *src_track);
 void BKE_tracking_free(struct MovieTracking *tracking);
 
+struct ImBuf *BKE_tracking_sample_pattern_imbuf(int frame_width, int frame_height,
+                                                struct ImBuf *struct_ibuf, struct MovieTrackingMarker *marker,
+                                                int num_samples_x, int num_samples_y, float pos[2]);
 struct ImBuf *BKE_tracking_get_pattern_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track,
-                                             struct MovieTrackingMarker *marker, int margin, int anchored,
-                                             float pos[2], int origin[2]);
-struct ImBuf *BKE_tracking_get_pattern_color_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track,
-                                                   struct MovieTrackingMarker *marker, int anchored);
+                                             struct MovieTrackingMarker *marker, int anchored, int disable_channels);
 struct ImBuf *BKE_tracking_get_search_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track,
-                                            struct MovieTrackingMarker *marker);
+                                            struct MovieTrackingMarker *marker, int anchored, int disable_channels);
 struct ImBuf *BKE_tracking_track_mask_get(struct MovieTracking *tracking, struct MovieTrackingTrack *track,
                                           struct MovieTrackingMarker *marker, int width, int height);
 
index 244d2888fc63336a47619390a9e6e63538cae93e..8b91ee29c59d950833313f87e7de0264d2b948b2 100644 (file)
@@ -1032,6 +1032,11 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip
                scopes->track_preview = NULL;
        }
 
+       if (scopes->track_search) {
+               IMB_freeImBuf(scopes->track_search);
+               scopes->track_search = NULL;
+       }
+
        scopes->marker = NULL;
        scopes->track = NULL;
 
@@ -1052,7 +1057,7 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip
                                scopes->track_disabled = FALSE;
 
                                if (ibuf && (ibuf->rect || ibuf->rect_float)) {
-                                       ImBuf *tmpibuf;
+                                       ImBuf *search_ibuf;
                                        MovieTrackingMarker undist_marker = *marker;
 
                                        if (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
@@ -1070,17 +1075,18 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip
                                                undist_marker.pos[1] /= height * aspy;
                                        }
 
-                                       /* NOTE: margin should be kept in sync with value from ui_draw_but_TRACKPREVIEW */
-                                       tmpibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, &undist_marker, 3 /* margin */,
-                                                                                1 /* anchor */, scopes->track_pos, NULL);
+                                       search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, &undist_marker, TRUE, TRUE);
+
+                                       if (!search_ibuf->rect_float) {
+                                               /* sampling happens in float buffer */
+                                               IMB_float_from_rect(search_ibuf);
+                                       }
 
-                                       if (tmpibuf->rect_float)
-                                               IMB_rect_from_float(tmpibuf);
+                                       scopes->undist_marker = undist_marker;
+                                       scopes->track_search = search_ibuf;
 
-                                       if (tmpibuf->rect)
-                                               scopes->track_preview = tmpibuf;
-                                       else
-                                               IMB_freeImBuf(tmpibuf);
+                                       scopes->frame_width = ibuf->x;
+                                       scopes->frame_height = ibuf->y;
                                }
 
                                IMB_freeImBuf(ibuf);
index 01e464e77a864fa42e4cc73af4f1b46475a24615..1d4ed2c8c40cc02f3e72cd8a0452e44ca030a1b7 100644 (file)
@@ -84,10 +84,11 @@ static struct {
  * window relative coordinates in pixels, and "frame_unified" are unified 0..1
  * coordinates relative to the entire frame.
  */
-static void unified_to_pixel(const ImBuf *ibuf, const float unified_coords[2], float pixel_coords[2])
+static void unified_to_pixel(int frame_width, int frame_height,
+                             const float unified_coords[2], float pixel_coords[2])
 {
-       pixel_coords[0] = unified_coords[0] * ibuf->x;
-       pixel_coords[1] = unified_coords[1] * ibuf->y;
+       pixel_coords[0] = unified_coords[0] * frame_width;
+       pixel_coords[1] = unified_coords[1] * frame_height;
 }
 
 static void marker_to_frame_unified(const MovieTrackingMarker *marker, const float marker_unified_coords[2],
@@ -97,52 +98,117 @@ static void marker_to_frame_unified(const MovieTrackingMarker *marker, const flo
        frame_unified_coords[1] = marker_unified_coords[1] + marker->pos[1];
 }
 
-static void marker_unified_to_frame_pixel_coordinates(const ImBuf *ibuf, const MovieTrackingMarker *marker,
+static void marker_unified_to_frame_pixel_coordinates(int frame_width, int frame_height,
+                                                      const MovieTrackingMarker *marker,
                                                       const float marker_unified_coords[2], float frame_pixel_coords[2])
 {
        marker_to_frame_unified(marker, marker_unified_coords, frame_pixel_coords);
-       unified_to_pixel(ibuf, frame_pixel_coords, frame_pixel_coords);
+       unified_to_pixel(frame_width, frame_height, frame_pixel_coords, frame_pixel_coords);
 }
 
-static void get_search_origin_frame_pixel(const ImBuf *ibuf, const MovieTrackingMarker *marker, float frame_pixel[2])
+static void get_search_origin_frame_pixel(int frame_width, int frame_height,
+                                          const MovieTrackingMarker *marker, float frame_pixel[2])
 {
        /* Get the lower left coordinate of the search window and snap to pixel coordinates */
-       marker_unified_to_frame_pixel_coordinates(ibuf, marker, marker->search_min, frame_pixel);
+       marker_unified_to_frame_pixel_coordinates(frame_width, frame_height, marker, marker->search_min, frame_pixel);
        frame_pixel[0] = (int)frame_pixel[0];
        frame_pixel[1] = (int)frame_pixel[1];
 }
 
 #ifdef WITH_LIBMV
-static void pixel_to_unified(const ImBuf *ibuf, const float pixel_coords[2], float unified_coords[2])
+static void pixel_to_unified(int frame_width, int frame_height, const float pixel_coords[2], float unified_coords[2])
 {
-       unified_coords[0] = pixel_coords[0] / ibuf->x;
-       unified_coords[1] = pixel_coords[1] / ibuf->y;
+       unified_coords[0] = pixel_coords[0] / frame_width;
+       unified_coords[1] = pixel_coords[1] / frame_height;
 }
 
-static void marker_unified_to_search_pixel(const ImBuf *ibuf, const MovieTrackingMarker *marker,
+static void marker_unified_to_search_pixel(int frame_width, int frame_height,
+                                           const MovieTrackingMarker *marker,
                                            const float marker_unified[2], float search_pixel[2])
 {
        float frame_pixel[2];
        float search_origin_frame_pixel[2];
 
-       marker_unified_to_frame_pixel_coordinates(ibuf, marker, marker_unified, frame_pixel);
-       get_search_origin_frame_pixel(ibuf, marker, search_origin_frame_pixel);
+       marker_unified_to_frame_pixel_coordinates(frame_width, frame_height, marker, marker_unified, frame_pixel);
+       get_search_origin_frame_pixel(frame_width, frame_height, marker, search_origin_frame_pixel);
        sub_v2_v2v2(search_pixel, frame_pixel, search_origin_frame_pixel);
 }
 
-static void search_pixel_to_marker_unified(const ImBuf *ibuf, const MovieTrackingMarker *marker,
+static void search_pixel_to_marker_unified(int frame_width, int frame_height,
+                                           const MovieTrackingMarker *marker,
                                            const float search_pixel[2], float marker_unified[2])
 {
        float frame_unified[2];
        float search_origin_frame_pixel[2];
 
-       get_search_origin_frame_pixel(ibuf, marker, search_origin_frame_pixel);
+       get_search_origin_frame_pixel(frame_width, frame_height, marker, search_origin_frame_pixel);
        add_v2_v2v2(frame_unified, search_pixel, search_origin_frame_pixel);
-       pixel_to_unified(ibuf, frame_unified, frame_unified);
+       pixel_to_unified(frame_width, frame_height, frame_unified, frame_unified);
 
        /* marker pos is in frame unified */
        sub_v2_v2v2(marker_unified, frame_unified, marker->pos);
 }
+
+/* Each marker has 5 coordinates associated with it that get warped with
+ * tracking: the four corners ("pattern_corners"), and the cernter ("pos").
+ * This function puts those 5 points into the appropriate frame for tracking
+ * (the "search" coordinate frame).
+ */
+static void get_marker_coords_for_tracking(int frame_width, int frame_height,
+                                           const MovieTrackingMarker *marker,
+                                           double search_pixel_x[5], double search_pixel_y[5])
+{
+       int i;
+       float unified_coords[2];
+       float pixel_coords[2];
+
+       /* Convert the corners into search space coordinates. */
+       for (i = 0; i < 4; i++) {
+               marker_unified_to_search_pixel(frame_width, frame_height, marker, marker->pattern_corners[i], pixel_coords);
+               search_pixel_x[i] = pixel_coords[0];
+               search_pixel_y[i] = pixel_coords[1];
+       }
+       /* Convert the center position (aka "pos"); this is the origin */
+       unified_coords[0] = 0.0;
+       unified_coords[1] = 0.0;
+       marker_unified_to_search_pixel(frame_width, frame_height, marker, unified_coords, pixel_coords);
+
+       search_pixel_x[4] = pixel_coords[0];
+       search_pixel_y[4] = pixel_coords[1];
+}
+
+/* Inverse of above. */
+static void set_marker_coords_from_tracking(int frame_width, int frame_height, MovieTrackingMarker *marker,
+                                            const double search_pixel_x[5], const double search_pixel_y[5])
+{
+       int i;
+       float marker_unified[2];
+       float search_pixel[2];
+
+       /* Convert the corners into search space coordinates. */
+       for (i = 0; i < 4; i++) {
+               search_pixel[0] = search_pixel_x[i];
+               search_pixel[1] = search_pixel_y[i];
+               search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker->pattern_corners[i]);
+       }
+
+       /* Convert the center position (aka "pos"); this is the origin */
+       search_pixel[0] = search_pixel_x[4];
+       search_pixel[1] = search_pixel_y[4];
+       search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker_unified);
+
+       /* If the tracker tracked nothing, then "marker_unified" would be zero.
+        * Otherwise, the entire patch shifted, and that delta should be applied to
+        * all the coordinates.
+        */
+       for (i = 0; i < 4; i++) {
+               marker->pattern_corners[i][0] -= marker_unified[0];
+               marker->pattern_corners[i][1] -= marker_unified[1];
+       }
+
+       marker->pos[0] += marker_unified[0];
+       marker->pos[1] += marker_unified[1];
+}
 #endif
 
 /*********************** common functions *************************/
@@ -1178,102 +1244,75 @@ static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int g
                        track->flag & TRACK_DISABLE_GREEN, track->flag & TRACK_DISABLE_BLUE, grayscale);
 }
 
-static ImBuf *get_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
-                             float min[2], float max[2], int margin, int anchored,
-                                                        int grayscale, float pos[2], int origin[2])
+ImBuf *BKE_tracking_sample_pattern_imbuf(int frame_width, int frame_height,
+                                         ImBuf *search_ibuf, MovieTrackingMarker *marker,
+                                                                                int num_samples_x, int num_samples_y, float pos[2])
 {
-       ImBuf *tmpibuf;
-       int x, y;
-       int x1, y1, w, h;
-       float mpos[2];
-
-       copy_v2_v2(mpos, marker->pos);
-       if (anchored)
-               add_v2_v2(mpos, track->offset);
-
-       if (pos)
-               zero_v2(pos);
-
-       x = mpos[0]*ibuf->x;
-       y = mpos[1]*ibuf->y;
-
-       w = (max[0] - min[0]) * ibuf->x;
-       h = (max[1] - min[1]) * ibuf->y;
-
-       /* dimensions should be odd */
-       w = w | 1;
-       h = h | 1;
-
-       x1 = x - (int)(w * (-min[0] / (max[0] - min[0])));
-       y1 = y - (int)(h * (-min[1] / (max[1] - min[1])));
-
-       if (ibuf->rect_float)
-               tmpibuf = IMB_allocImBuf(w + margin * 2, h + margin * 2, 32, IB_rectfloat);
-       else
-               tmpibuf = IMB_allocImBuf(w + margin * 2, h + margin * 2, 32, IB_rect);
-
-       tmpibuf->profile = ibuf->profile;
+       ImBuf *pattern_ibuf;
+       double src_pixel_x[5], src_pixel_y[5];
+       double warped_position_x, warped_position_y;
 
-       IMB_rectcpy(tmpibuf, ibuf, 0, 0, x1 - margin, y1 - margin, w + margin * 2, h + margin * 2);
+       pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat);
+       pattern_ibuf->profile = IB_PROFILE_LINEAR_RGB;
 
-       if (pos != NULL) {
-               pos[0] = mpos[0] * ibuf->x - x1 + margin;
-               pos[1] = mpos[1] * ibuf->y - y1 + margin;
+       if (!search_ibuf->rect_float) {
+               IMB_float_from_rect(search_ibuf);
        }
 
-       if (origin != NULL) {
-               origin[0] = x1 - margin;
-               origin[1] = y1 - margin;
-       }
+       get_marker_coords_for_tracking(frame_width, frame_height, marker, src_pixel_x, src_pixel_y);
 
-       if (grayscale) {
-               if ((track->flag & TRACK_PREVIEW_GRAYSCALE) ||
-                   (track->flag & TRACK_DISABLE_RED)       ||
-                   (track->flag & TRACK_DISABLE_GREEN)     ||
-                   (track->flag & TRACK_DISABLE_BLUE))
-               {
-                       disable_imbuf_channels(tmpibuf, track, TRUE /* grayscale */);
-               }
+       libmv_samplePlanarPatch(search_ibuf->rect_float, search_ibuf->x, search_ibuf->y, 4,
+                               src_pixel_x, src_pixel_y, num_samples_x,
+                               num_samples_y, pattern_ibuf->rect_float,
+                               &warped_position_x, &warped_position_y);
+
+       if (pos) {
+               pos[0] = warped_position_x;
+               pos[1] = warped_position_y;
        }
 
-       return tmpibuf;
+       return pattern_ibuf;
 }
 
 ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
-                                      int margin, int anchored, float pos[2], int origin[2])
+                                                                         int anchored, int disable_channels)
 {
+       ImBuf *pattern_ibuf, *search_ibuf;
        float pat_min[2], pat_max[2];
+       int num_samples_x, num_samples_y;
 
-       /* XXX: need to do real quad sampling here, but currently just assume
-        *      corners represents quad pattern
-        */
        BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
 
-       return get_area_imbuf(ibuf, track, marker, pat_min, pat_max, margin, anchored, TRUE, pos, origin);
-}
+       num_samples_x = (pat_max[0] - pat_min[0]) * ibuf->x;
+       num_samples_y = (pat_max[1] - pat_min[1]) * ibuf->y;
 
-ImBuf *BKE_tracking_get_pattern_color_imbuf(ImBuf *ibuf, MovieTrackingTrack *track,
-                                            MovieTrackingMarker *marker, int anchored)
-{
-       float pat_min[2], pat_max[2];
+       search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, anchored, disable_channels);
 
-       /* see comment above */
-       BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
+       pattern_ibuf = BKE_tracking_sample_pattern_imbuf(ibuf->x, ibuf->y, search_ibuf, marker,
+                                                        num_samples_x, num_samples_y, NULL);
 
-       return get_area_imbuf(ibuf, track, marker, pat_min, pat_max, 0, anchored, FALSE, NULL, NULL);
+       IMB_freeImBuf(search_ibuf);
+
+       return pattern_ibuf;
 }
 
-ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker)
+ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
+                                     int anchored, int disable_channels)
 {
        ImBuf *searchibuf;
        int x, y, w, h;
        float search_origin[2];
 
-       get_search_origin_frame_pixel(ibuf, marker, search_origin);
+       get_search_origin_frame_pixel(ibuf->x, ibuf->y, marker, search_origin);
 
        x = search_origin[0];
        y = search_origin[1];
 
+       if (anchored) {
+               x += track->offset[0] * ibuf->x;
+               y += track->offset[1] * ibuf->y;
+       }
+
        w = (marker->search_max[0] - marker->search_min[0]) * ibuf->x;
        h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y;
 
@@ -1282,12 +1321,14 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mov
 
        IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h);
 
-       if ((track->flag & TRACK_PREVIEW_GRAYSCALE) ||
-           (track->flag & TRACK_DISABLE_RED)       ||
-           (track->flag & TRACK_DISABLE_GREEN)     ||
-           (track->flag & TRACK_DISABLE_BLUE))
-       {
-               disable_imbuf_channels(searchibuf, track, FALSE);
+       if (disable_channels) {
+               if ((track->flag & TRACK_PREVIEW_GRAYSCALE) ||
+                   (track->flag & TRACK_DISABLE_RED)       ||
+                   (track->flag & TRACK_DISABLE_GREEN)     ||
+                   (track->flag & TRACK_DISABLE_BLUE))
+               {
+                       disable_imbuf_channels(searchibuf, track, TRUE);
+               }
        }
 
        return searchibuf;
@@ -1424,7 +1465,7 @@ static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieT
        float *gray_pixels;
        int width, height;
 
-       searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker);
+       searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, FALSE, TRUE);
 
        width = searchibuf->x;
        height = searchibuf->y;
@@ -1448,66 +1489,6 @@ static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieT
        return gray_pixels;
 }
 
-/* Each marker has 5 coordinates associated with it that get warped with
- * tracking: the four corners ("pattern_corners"), and the cernter ("pos").
- * This function puts those 5 points into the appropriate frame for tracking
- * (the "search" coordinate frame).
- */
-static void get_marker_coords_for_tracking(const ImBuf *ibuf, const MovieTrackingMarker *marker,
-                                           double search_pixel_x[5], double search_pixel_y[5])
-{
-       int i;
-       float unified_coords[2];
-       float pixel_coords[2];
-
-       /* Convert the corners into search space coordinates. */
-       for (i = 0; i < 4; i++) {
-               marker_unified_to_search_pixel(ibuf, marker, marker->pattern_corners[i], pixel_coords);
-               search_pixel_x[i] = pixel_coords[0];
-               search_pixel_y[i] = pixel_coords[1];
-       }
-       /* Convert the center position (aka "pos"); this is the origin */
-       unified_coords[0] = 0.0;
-       unified_coords[1] = 0.0;
-       marker_unified_to_search_pixel(ibuf, marker, unified_coords, pixel_coords);
-
-       search_pixel_x[4] = pixel_coords[0];
-       search_pixel_y[4] = pixel_coords[1];
-}
-
-/* Inverse of above. */
-static void set_marker_coords_from_tracking(const ImBuf *ibuf, MovieTrackingMarker *marker,
-                                            const double search_pixel_x[5], const double search_pixel_y[5])
-{
-       int i;
-       float marker_unified[2];
-       float search_pixel[2];
-
-       /* Convert the corners into search space coordinates. */
-       for (i = 0; i < 4; i++) {
-               search_pixel[0] = search_pixel_x[i];
-               search_pixel[1] = search_pixel_y[i];
-               search_pixel_to_marker_unified(ibuf, marker, search_pixel, marker->pattern_corners[i]);
-       }
-
-       /* Convert the center position (aka "pos"); this is the origin */
-       search_pixel[0] = search_pixel_x[4];
-       search_pixel[1] = search_pixel_y[4];
-       search_pixel_to_marker_unified(ibuf, marker, search_pixel, marker_unified);
-
-       /* If the tracker tracked nothing, then "marker_unified" would be zero.
-        * Otherwise, the entire patch shifted, and that delta should be applied to
-        * all the coordinates.
-        */
-       for (i = 0; i < 4; i++) {
-               marker->pattern_corners[i][0] -= marker_unified[0];
-               marker->pattern_corners[i][1] -= marker_unified[1];
-       }
-
-       marker->pos[0] += marker_unified[0];
-       marker->pos[1] += marker_unified[1];
-}
-
 static unsigned char *get_ucharbuf(ImBuf *ibuf)
 {
        int x, y;
@@ -1633,6 +1614,8 @@ int BKE_tracking_next(MovieTrackingContext *context)
        int curfra =  BKE_movieclip_remap_scene_to_clip_frame(context->clip, context->user.framenr);
        int a, ok = FALSE, map_size;
 
+       int frame_width, frame_height;
+
        map_size = tracks_map_size(context->tracks_map);
 
        /* nothing to track, avoid unneeded frames reading to save time and memory */
@@ -1649,6 +1632,9 @@ int BKE_tracking_next(MovieTrackingContext *context)
        if (!destination_ibuf)
                return FALSE;
 
+       frame_width = destination_ibuf->x;
+       frame_height = destination_ibuf->y;
+
        #pragma omp parallel for private(a) shared(destination_ibuf, ok) if (map_size>1)
        for (a = 0; a < map_size; a++) {
                TrackContext *track_context = NULL;
@@ -1739,8 +1725,8 @@ int BKE_tracking_next(MovieTrackingContext *context)
                                options.sigma = 0.9;
 
                                /* Convert the marker corners and center into pixel coordinates in the search/destination images. */
-                               get_marker_coords_for_tracking(destination_ibuf, &track_context->marker, src_pixel_x, src_pixel_y);
-                               get_marker_coords_for_tracking(destination_ibuf, marker, dst_pixel_x, dst_pixel_y);
+                               get_marker_coords_for_tracking(frame_width, frame_height, &track_context->marker, src_pixel_x, src_pixel_y);
+                               get_marker_coords_for_tracking(frame_width, frame_height, marker, dst_pixel_x, dst_pixel_y);
 
                                /* Run the tracker! */
                                tracked = libmv_trackRegion(&options,
@@ -1755,7 +1741,7 @@ int BKE_tracking_next(MovieTrackingContext *context)
                        if (tracked && !onbound) {
                                memset(&marker_new, 0, sizeof(marker_new));
                                marker_new = *marker;
-                               set_marker_coords_from_tracking(destination_ibuf, &marker_new, dst_pixel_x, dst_pixel_y);
+                               set_marker_coords_from_tracking(frame_width, frame_height, &marker_new, dst_pixel_x, dst_pixel_y);
                                marker_new.flag |= MARKER_TRACKED;
                                marker_new.framenr = nextfra;
 
index a36645510c3d6540d4cb60c5f6036053293cdbd3..a1d255e67e8547ca1eee31fbc57f41dbe59f9c20 100644 (file)
@@ -5362,6 +5362,7 @@ static void lib_link_screen(FileData *fd, Main *main)
                                                sclip->clip = newlibadr_us(fd, sc->id.lib, sclip->clip);
                                                sclip->mask = newlibadr_us(fd, sc->id.lib, sclip->mask);
 
+                                               sclip->scopes.track_search = NULL;
                                                sclip->scopes.track_preview = NULL;
                                                sclip->draw_context = NULL;
                                                sclip->scopes.ok = 0;
index 4f6abdcbc228541059720e527e25e996b3708440..1bb0d90c1db39d4a213f0d5b2473522229198376 100644 (file)
@@ -116,7 +116,7 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri
        while (track) {
                VoronoiSite *site = &sites[i];
                MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenumber);
-               ImBuf *pattern_ibuf = BKE_tracking_get_pattern_color_imbuf(ibuf, track, marker, TRUE);
+               ImBuf *pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, TRUE, FALSE);
                int j;
 
                zero_v3(site->color);
index a0b418c1a9a05f894455f81f773b363ae9604d05..d652fe4a56964804fa9cea2d1ab8109de0f56c4c 100644 (file)
@@ -43,6 +43,7 @@
 
 #include "BKE_colortools.h"
 #include "BKE_texture.h"
+#include "BKE_tracking.h"
 
 
 #include "IMB_imbuf.h"
@@ -1480,36 +1481,10 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti *rect
        fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
 }
 
-static ImBuf *scale_trackpreview_ibuf(ImBuf *ibuf, float track_pos[2], int width, float height, int margin)
-{
-       ImBuf *scaleibuf;
-       const float scalex = ((float)ibuf->x - 2 * margin) / width;
-       const float scaley = ((float)ibuf->y - 2 * margin) / height;
-       /* NOTE: 1.0f = 0.5f for integer coordinate coorrection (center of pixel vs. left bottom corner of bixel)
-        *       and 0.5f for centering image in preview (cross is draving at exact center of widget so image
-        *       should be shifted by half of pixel for correct centering) - sergey */
-       float off_x = (int)track_pos[0] - track_pos[0] + 1.0f;
-       float off_y = (int)track_pos[1] - track_pos[1] + 1.0f;
-       int x, y;
-
-       scaleibuf = IMB_allocImBuf(width, height, 32, IB_rect);
-
-       for (y = 0; y < height; y++) {
-               for (x = 0; x < width; x++) {
-                       float src_x = scalex * (x) + margin - off_x;
-                       float src_y = scaley * (y) + margin - off_y;
-
-                       bicubic_interpolation(ibuf, scaleibuf, src_x, src_y, x, y);
-               }
-       }
-
-       return scaleibuf;
-}
-
 void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *recti)
 {
        rctf rect;
-       int ok = 0;
+       int ok = 0, width, height;
        GLint scissor[4];
        MovieClipScopes *scopes = (MovieClipScopes *)but->poin;
 
@@ -1518,6 +1493,9 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
        rect.ymin = (float)recti->ymin + SCOPE_RESIZE_PAD + 2;
        rect.ymax = (float)recti->ymax - 1;
 
+       width = rect.xmax - rect.xmin + 1;
+       height = rect.ymax - rect.ymin;
+
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
@@ -1535,40 +1513,52 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
 
                ok = 1;
        }
-       else if (scopes->track_preview) {
-               /* additional margin around image */
-               /* NOTE: should be kept in sync with value from BKE_movieclip_update_scopes */
-               const int margin = 3;
-               float zoomx, zoomy, track_pos[2], off_x, off_y;
-               int a, width, height;
+       else if ((!scopes->track_preview) ||
+             (scopes->track_preview->x != width || scopes->track_preview->y != height))
+       {
+               ImBuf *tmpibuf;
+
+               if (scopes->track_preview)
+                       IMB_freeImBuf(scopes->track_preview);
+
+               tmpibuf = BKE_tracking_sample_pattern_imbuf(scopes->frame_width, scopes->frame_height,
+                                                           scopes->track_search, &scopes->undist_marker,
+                                                           width, height, scopes->track_pos);
+
+               if (tmpibuf->rect_float)
+                       IMB_rect_from_float(tmpibuf);
+
+               // XXX: for debug only
+               // tmpibuf->ftype = PNG;
+               // IMB_saveiff(tmpibuf, "sample.png", IB_rect);
+
+               if (tmpibuf->rect)
+                       scopes->track_preview = tmpibuf;
+               else
+                       IMB_freeImBuf(tmpibuf);
+       }
+
+       if (!ok && scopes->track_preview) {
+               float track_pos[2];
+               int a;
                ImBuf *drawibuf;
 
                glPushMatrix();
 
-               track_pos[0] = scopes->track_pos[0] - margin;
-               track_pos[1] = scopes->track_pos[1] - margin;
+               track_pos[0] = scopes->track_pos[0];
+               track_pos[1] = scopes->track_pos[1];
 
                /* draw content of pattern area */
                glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, scissor[2], scissor[3]);
 
-               width = rect.xmax - rect.xmin + 1;
-               height = rect.ymax - rect.ymin;
-
                if (width > 0 && height > 0) {
-                       zoomx = (float)width / (scopes->track_preview->x - 2 * margin);
-                       zoomy = (float)height / (scopes->track_preview->y - 2 * margin);
-
-                       off_x = ((int)track_pos[0] - track_pos[0] + 0.5f) * zoomx;
-                       off_y = ((int)track_pos[1] - track_pos[1] + 0.5f) * zoomy;
-
-                       drawibuf = scale_trackpreview_ibuf(scopes->track_preview, track_pos, width, height, margin);
+                       drawibuf = scopes->track_preview;
 
                        glaDrawPixelsSafe(rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y,
                                          drawibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, drawibuf->rect);
-                       IMB_freeImBuf(drawibuf);
 
                        /* draw cross for pizel position */
-                       glTranslatef(off_x + rect.xmin + track_pos[0] * zoomx, off_y + rect.ymin + track_pos[1] * zoomy, 0.f);
+                       glTranslatef(rect.xmin + track_pos[0], rect.ymin + track_pos[1], 0.f);
                        glScissor(ar->winrct.xmin + rect.xmin,
                                  ar->winrct.ymin + rect.ymin,
                                  rect.xmax - rect.xmin,
index a49319abd206ece982c6340a0184debaca18d715..54724881e37bc3044a122b208f3a481ae3d384b9 100644 (file)
@@ -306,6 +306,9 @@ static void clip_free(SpaceLink *sl)
        if (sc->scopes.track_preview)
                IMB_freeImBuf(sc->scopes.track_preview);
 
+       if (sc->scopes.track_search)
+               IMB_freeImBuf(sc->scopes.track_search);
+
        ED_space_clip_free_texture_buffer(sc);
 }
 
@@ -323,6 +326,7 @@ static SpaceLink *clip_duplicate(SpaceLink *sl)
        SpaceClip *scn = MEM_dupallocN(sl);
 
        /* clear or remove stuff from old */
+       scn->scopes.track_search = NULL;
        scn->scopes.track_preview = NULL;
        scn->scopes.ok = FALSE;
        scn->draw_context = NULL;
index fd7046854ff1b143ba9f054e6f3be389090e60a8..b9d631677001c55134e0190f23cd6bf248ad1f2f 100644 (file)
@@ -92,6 +92,9 @@ typedef struct MovieClip {
 typedef struct MovieClipScopes {
        int ok;                                                 /* 1 means scopes are ok and recalculation is unneeded */
        int track_preview_height;               /* height of track preview widget */
+       int frame_width, frame_height;          /* width and height of frame for which scopes are calculated */
+       struct MovieTrackingMarker undist_marker;       /* undistorted position of marker used for pattern sampling */
+       struct ImBuf *track_search;     /* search area of a track */
        struct ImBuf *track_preview;    /* ImBuf displayed in track preview */
        float track_pos[2];                             /* sub-pizel position of marker in track ImBuf */
        short track_disabled;                   /* active track is disabled, special notifier should be drawn */
index b7ce621a9e12c613ab7b7930965341cfe0048dcb..6149285fdbc0f0314bdb30af6bd38adbdcfef41f 100644 (file)
@@ -91,7 +91,7 @@ static void compute_gradient_screen(RenderData *rd, NodeKeyingScreenData *keying
        while (track) {
                VoronoiSite *site = &sites[i];
                MovieTrackingMarker *marker = BKE_tracking_get_marker(track, rd->cfra);
-               ImBuf *pattern_ibuf = BKE_tracking_get_pattern_color_imbuf(ibuf, track, marker, TRUE);
+               ImBuf *pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, TRUE, FALSE);
                int j;
 
                zero_v3(site->color);