diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index eba4698f198..ffa065f08fe 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -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) diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index bbd8f0c30d0..6f4b5dea384 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -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); diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc index b9e4f883e78..679646c4c37 100644 --- a/extern/libmv/libmv/tracking/track_region.cc +++ b/extern/libmv/libmv/tracking/track_region.cc @@ -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; } diff --git a/extern/libmv/libmv/tracking/track_region.h b/extern/libmv/libmv/tracking/track_region.h index c23cde6000f..04e7c7e1403 100644 --- a/extern/libmv/libmv/tracking/track_region.h +++ b/extern/libmv/libmv/tracking/track_region.h @@ -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 diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 25723b8b0e8..8c28dd93a5e 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -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); diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 244d2888fc6..8b91ee29c59 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -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 (tmpibuf->rect_float) - IMB_rect_from_float(tmpibuf); + if (!search_ibuf->rect_float) { + /* sampling happens in float buffer */ + IMB_float_from_rect(search_ibuf); + } - if (tmpibuf->rect) - scopes->track_preview = tmpibuf; - else - IMB_freeImBuf(tmpibuf); + scopes->undist_marker = undist_marker; + scopes->track_search = search_ibuf; + + scopes->frame_width = ibuf->x; + scopes->frame_height = ibuf->y; } IMB_freeImBuf(ibuf); diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 01e464e77a8..1d4ed2c8c40 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -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]; + ImBuf *pattern_ibuf; + double src_pixel_x[5], src_pixel_y[5]; + double warped_position_x, warped_position_y; - copy_v2_v2(mpos, marker->pos); - if (anchored) - add_v2_v2(mpos, track->offset); + pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat); + pattern_ibuf->profile = IB_PROFILE_LINEAR_RGB; - 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; - - IMB_rectcpy(tmpibuf, ibuf, 0, 0, x1 - margin, y1 - margin, w + margin * 2, h + margin * 2); - - 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); + + 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; } - 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 */); - } - } - - 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; + + search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, anchored, disable_channels); + + pattern_ibuf = BKE_tracking_sample_pattern_imbuf(ibuf->x, ibuf->y, search_ibuf, marker, + num_samples_x, num_samples_y, NULL); + + IMB_freeImBuf(search_ibuf); + + return pattern_ibuf; } -ImBuf *BKE_tracking_get_pattern_color_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, - MovieTrackingMarker *marker, int anchored) -{ - float pat_min[2], pat_max[2]; - - /* see comment above */ - BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); - - return get_area_imbuf(ibuf, track, marker, pat_min, pat_max, 0, anchored, FALSE, NULL, NULL); -} - -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; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index a36645510c3..a1d255e67e8 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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; diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp index 4f6abdcbc22..1bb0d90c1db 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp @@ -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); diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index a0b418c1a9a..d652fe4a569 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -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, diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index a49319abd20..54724881e37 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -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; diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h index fd7046854ff..b9d63167700 100644 --- a/source/blender/makesdna/DNA_movieclip_types.h +++ b/source/blender/makesdna/DNA_movieclip_types.h @@ -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 */ diff --git a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c index b7ce621a9e1..6149285fdbc 100644 --- a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c +++ b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c @@ -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);