diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2017-05-26 16:21:15 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2017-05-26 16:27:49 +0300 |
commit | b0015686e2e48a384a0b2a03a75f6daaad7271c0 (patch) | |
tree | 62e346ef1ae840f670344ae2f81b03185386616c | |
parent | ac66fb193f80847fd4fc1b46413ebb3199ebbf1b (diff) |
Fix T50908: Motion Tracker ignored grease pencil mask
This feature got lost with new auto-track API,
Added it back by extending frame accessor class. This isn't really
a frame thing, but we don't have other type of accessor here.
Surely, we can use old-style API here and pass mask via region
tracker options for this particular case, but then it becomes much
less obvious how real auto-tracker will access this mask with old
style API.
So seems we do need an accessor for such data, just matter of
finding better place than frame accessor.
-rw-r--r-- | intern/libmv/intern/frame_accessor.cc | 53 | ||||
-rw-r--r-- | intern/libmv/intern/frame_accessor.h | 15 | ||||
-rw-r--r-- | intern/libmv/intern/stub.cc | 4 | ||||
-rw-r--r-- | intern/libmv/intern/track_region.cc | 2 | ||||
-rw-r--r-- | intern/libmv/libmv/autotrack/autotrack.cc | 23 | ||||
-rw-r--r-- | intern/libmv/libmv/autotrack/frame_accessor.h | 19 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/tracking.c | 51 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/tracking_auto.c | 17 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/tracking_util.c | 62 | ||||
-rw-r--r-- | source/blender/blenkernel/tracking_private.h | 11 |
10 files changed, 230 insertions, 27 deletions
diff --git a/intern/libmv/intern/frame_accessor.cc b/intern/libmv/intern/frame_accessor.cc index 5d274d7ccca..e7fc0ab4883 100644 --- a/intern/libmv/intern/frame_accessor.cc +++ b/intern/libmv/intern/frame_accessor.cc @@ -40,10 +40,14 @@ using mv::Region; struct LibmvFrameAccessor : public FrameAccessor { LibmvFrameAccessor(libmv_FrameAccessorUserData* user_data, libmv_GetImageCallback get_image_callback, - libmv_ReleaseImageCallback release_image_callback) + libmv_ReleaseImageCallback release_image_callback, + libmv_GetMaskForTrackCallback get_mask_for_track_callback, + libmv_ReleaseMaskCallback release_mask_callback) : user_data_(user_data), get_image_callback_(get_image_callback), - release_image_callback_(release_image_callback) { } + release_image_callback_(release_image_callback), + get_mask_for_track_callback_(get_mask_for_track_callback), + release_mask_callback_(release_mask_callback) { } virtual ~LibmvFrameAccessor() { } @@ -109,6 +113,41 @@ struct LibmvFrameAccessor : public FrameAccessor { release_image_callback_(cache_key); } + Key GetMaskForTrack(int clip, + int frame, + int track, + const Region* region, + FloatImage* destination) { + float *float_buffer; + int width, height; + libmv_Region libmv_region; + if (region) { + get_libmv_region(*region, &libmv_region); + } + Key cache_key = get_mask_for_track_callback_( + user_data_, + clip, + frame, + track, + region != NULL ? &libmv_region : NULL, + &float_buffer, + &width, + &height); + + // TODO(sergey): Dumb code for until we can set data directly. + FloatImage temp_image(float_buffer, + height, + width, + 1); + destination->CopyFrom(temp_image); + + return cache_key; + } + + void ReleaseMask(Key key) { + release_mask_callback_(key); + } + bool GetClipDimensions(int /*clip*/, int * /*width*/, int * /*height*/) { return false; } @@ -124,6 +163,8 @@ struct LibmvFrameAccessor : public FrameAccessor { libmv_FrameAccessorUserData* user_data_; libmv_GetImageCallback get_image_callback_; libmv_ReleaseImageCallback release_image_callback_; + libmv_GetMaskForTrackCallback get_mask_for_track_callback_; + libmv_ReleaseMaskCallback release_mask_callback_; }; } // namespace @@ -131,11 +172,15 @@ struct LibmvFrameAccessor : public FrameAccessor { libmv_FrameAccessor* libmv_FrameAccessorNew( libmv_FrameAccessorUserData* user_data, libmv_GetImageCallback get_image_callback, - libmv_ReleaseImageCallback release_image_callback) { + libmv_ReleaseImageCallback release_image_callback, + libmv_GetMaskForTrackCallback get_mask_for_track_callback, + libmv_ReleaseMaskCallback release_mask_callback) { return (libmv_FrameAccessor*) LIBMV_OBJECT_NEW(LibmvFrameAccessor, user_data, get_image_callback, - release_image_callback); + release_image_callback, + get_mask_for_track_callback, + release_mask_callback); } void libmv_FrameAccessorDestroy(libmv_FrameAccessor* frame_accessor) { diff --git a/intern/libmv/intern/frame_accessor.h b/intern/libmv/intern/frame_accessor.h index 3e813fe7581..c041d67f56f 100644 --- a/intern/libmv/intern/frame_accessor.h +++ b/intern/libmv/intern/frame_accessor.h @@ -61,10 +61,23 @@ typedef libmv_CacheKey (*libmv_GetImageCallback) ( typedef void (*libmv_ReleaseImageCallback) (libmv_CacheKey cache_key); +typedef libmv_CacheKey (*libmv_GetMaskForTrackCallback) ( + libmv_FrameAccessorUserData* user_data, + int clip, + int frame, + int track, + const libmv_Region* region, + float** destination, + int* width, + int* height); +typedef void (*libmv_ReleaseMaskCallback) (libmv_CacheKey cache_key); + libmv_FrameAccessor* libmv_FrameAccessorNew( libmv_FrameAccessorUserData* user_data, libmv_GetImageCallback get_image_callback, - libmv_ReleaseImageCallback release_image_callback); + libmv_ReleaseImageCallback release_image_callback, + libmv_GetMaskForTrackCallback get_mask_for_track_callback, + libmv_ReleaseMaskCallback release_mask_callback); void libmv_FrameAccessorDestroy(libmv_FrameAccessor* frame_accessor); int64_t libmv_frameAccessorgetTransformKey(const libmv_FrameTransform *transform); diff --git a/intern/libmv/intern/stub.cc b/intern/libmv/intern/stub.cc index 47e1915e072..8603cc03153 100644 --- a/intern/libmv/intern/stub.cc +++ b/intern/libmv/intern/stub.cc @@ -375,7 +375,9 @@ int libmv_autoTrackGetMarker(libmv_AutoTrack* /*libmv_autotrack*/, libmv_FrameAccessor* libmv_FrameAccessorNew( libmv_FrameAccessorUserData* /*user_data**/, libmv_GetImageCallback /*get_image_callback*/, - libmv_ReleaseImageCallback /*release_image_callback*/) + libmv_ReleaseImageCallback /*release_image_callback*/, + libmv_GetMaskForTrackCallback /*get_mask_for_track_callback*/, + libmv_ReleaseMaskCallback /*release_mask_callback*/) { return NULL; } diff --git a/intern/libmv/intern/track_region.cc b/intern/libmv/intern/track_region.cc index 8989897e09f..d395b6457d7 100644 --- a/intern/libmv/intern/track_region.cc +++ b/intern/libmv/intern/track_region.cc @@ -36,7 +36,7 @@ /* define this to generate PNG images with content of search areas on every itteration of tracking */ -#undef DUMP_ALWAYS +#define DUMP_ALWAYS using libmv::FloatImage; using libmv::TrackRegionOptions; diff --git a/intern/libmv/libmv/autotrack/autotrack.cc b/intern/libmv/libmv/autotrack/autotrack.cc index 4c7bdf1fde8..00366e0f661 100644 --- a/intern/libmv/libmv/autotrack/autotrack.cc +++ b/intern/libmv/libmv/autotrack/autotrack.cc @@ -111,6 +111,17 @@ FrameAccessor::Key GetImageForMarker(const Marker& marker, image); } +FrameAccessor::Key GetMaskForMarker(const Marker& marker, + FrameAccessor* frame_accessor, + FloatImage* mask) { + Region region = marker.search_region.Rounded(); + return frame_accessor->GetMaskForTrack(marker.clip, + marker.frame, + marker.track, + ®ion, + mask); +} + } // namespace bool AutoTrack::TrackMarker(Marker* tracked_marker, @@ -149,6 +160,11 @@ bool AutoTrack::TrackMarker(Marker* tracked_marker, return false; } + FloatImage reference_mask; + FrameAccessor::Key reference_mask_key = GetMaskForMarker(reference_marker, + frame_accessor_, + &reference_mask); + FloatImage tracked_image; FrameAccessor::Key tracked_key = GetImageForMarker(*tracked_marker, frame_accessor_, @@ -167,6 +183,10 @@ bool AutoTrack::TrackMarker(Marker* tracked_marker, if (track_options) { local_track_region_options = *track_options; } + if (reference_mask_key != NULL) { + LG << "Using mask for reference marker: " << reference_marker; + local_track_region_options.image1_mask = &reference_mask; + } local_track_region_options.num_extra_points = 1; // For center point. local_track_region_options.attempt_refine_before_brute = predicted_position; TrackRegion(reference_image, @@ -191,9 +211,10 @@ bool AutoTrack::TrackMarker(Marker* tracked_marker, tracked_marker->reference_clip = reference_marker.clip; tracked_marker->reference_frame = reference_marker.frame; - // Release the images from the accessor cache. + // Release the images and masks from the accessor cache. frame_accessor_->ReleaseImage(reference_key); frame_accessor_->ReleaseImage(tracked_key); + frame_accessor_->ReleaseMask(reference_mask_key); // TODO(keir): Possibly the return here should get removed since the results // are part of TrackResult. However, eventually the autotrack stuff will have diff --git a/intern/libmv/libmv/autotrack/frame_accessor.h b/intern/libmv/libmv/autotrack/frame_accessor.h index 8de5d865cd7..32f6349963c 100644 --- a/intern/libmv/libmv/autotrack/frame_accessor.h +++ b/intern/libmv/libmv/autotrack/frame_accessor.h @@ -76,6 +76,25 @@ struct FrameAccessor { // free the image immediately; others may hold onto the image. virtual void ReleaseImage(Key) = 0; + // Get mask image for the given track. + // + // Implementation of this method should sample mask associated with the track + // within given region to the given destination. + // + // Result is supposed to be a single channel image. + // + // If region is NULL, it it assumed to be full-frame. + virtual Key GetMaskForTrack(int clip, + int frame, + int track, + const Region* region, + FloatImage* destination) = 0; + + // Release a specified mask. + // + // Non-caching implementation may free used memory immediately. + virtual void ReleaseMask(Key key) = 0; + virtual bool GetClipDimensions(int clip, int* width, int* height) = 0; virtual int NumClips() = 0; virtual int NumFrames(int clip) = 0; diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 990d250b854..bfe8dcbb21e 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -974,8 +974,11 @@ static void track_mask_set_pixel_cb(int x, int x_end, int y, void *user_data) } static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height, - MovieTrackingMarker *marker, bGPDlayer *layer, - float *mask, int mask_width, int mask_height) + const float region_min[2], + bGPDlayer *layer, + float *mask, + int mask_width, + int mask_height) { bGPDframe *frame = layer->frames.first; TrackMaskSetPixelData data; @@ -994,8 +997,8 @@ static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height point = mask_points = MEM_callocN(2 * stroke->totpoints * sizeof(int), "track mask rasterization points"); for (int i = 0; i < stroke->totpoints; i++, point += 2) { - point[0] = (stroke_points[i].x - marker->search_min[0]) * frame_width; - point[1] = (stroke_points[i].y - marker->search_min[1]) * frame_height; + point[0] = stroke_points[i].x * frame_width - region_min[0]; + point[1] = stroke_points[i].y * frame_height - region_min[1]; } /* TODO: add an option to control whether AA is enabled or not */ BLI_bitmap_draw_2d_poly_v2i_n( @@ -1010,26 +1013,42 @@ static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height } } -float *BKE_tracking_track_get_mask(int frame_width, int frame_height, - MovieTrackingTrack *track, MovieTrackingMarker *marker) +/* Region is in pixel space, relative to marker's center. */ +float *tracking_track_get_mask_for_region(int frame_width, int frame_height, + const float region_min[2], + const float region_max[2], + MovieTrackingTrack *track) { float *mask = NULL; bGPDlayer *layer = track_mask_gpencil_layer_get(track); - int mask_width, mask_height; - - mask_width = (marker->search_max[0] - marker->search_min[0]) * frame_width; - mask_height = (marker->search_max[1] - marker->search_min[1]) * frame_height; - - if (layer) { + if (layer != NULL) { + const int mask_width = region_max[0] - region_min[0]; + const int mask_height = region_max[1] - region_min[1]; mask = MEM_callocN(mask_width * mask_height * sizeof(float), "track mask"); - - track_mask_gpencil_layer_rasterize(frame_width, frame_height, marker, layer, - mask, mask_width, mask_height); + track_mask_gpencil_layer_rasterize(frame_width, frame_height, + region_min, + layer, + mask, + mask_width, mask_height); } - return mask; } +float *BKE_tracking_track_get_mask(int frame_width, int frame_height, + MovieTrackingTrack *track, + MovieTrackingMarker *marker) +{ + /* Convert normalized space marker's search area to pixel-space region. */ + const float region_min[2] = {marker->search_min[0] * frame_width, + marker->search_min[1] * frame_height}; + const float region_max[2] = {marker->search_max[0] * frame_width, + marker->search_max[1] * frame_height}; + return tracking_track_get_mask_for_region(frame_width, frame_height, + region_min, + region_max, + track); +} + float BKE_tracking_track_get_weight_for_marker(MovieClip *clip, MovieTrackingTrack *track, MovieTrackingMarker *marker) { FCurve *weight_fcurve; diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c index 3b56ea271d0..9475925cdda 100644 --- a/source/blender/blenkernel/intern/tracking_auto.c +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -36,8 +36,9 @@ #include "DNA_movieclip_types.h" #include "DNA_object_types.h" /* SELECT */ -#include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_threads.h" #include "BLI_math.h" #include "BKE_movieclip.h" @@ -76,6 +77,9 @@ typedef struct AutoTrackContext { int num_tracks; /* Number of tracks being tracked. */ AutoTrackOptions *options; /* Per-tracking track options. */ + /* Array of all tracks, indexed by track_index. */ + MovieTrackingTrack **tracks; + bool backwards; bool sequence; int first_frame; @@ -306,8 +310,15 @@ AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip, BLI_spin_init(&context->spin_lock); + int num_total_tracks = BLI_listbase_count(tracksbase); + context->tracks = + MEM_callocN(sizeof(MovieTrackingTrack*) * num_total_tracks, + "auto track pointers"); + context->image_accessor = - tracking_image_accessor_new(context->clips, 1, user->framenr); + tracking_image_accessor_new(context->clips, 1, + context->tracks, num_total_tracks, + user->framenr); context->autotrack = libmv_autoTrackNew(context->image_accessor->libmv_accessor); @@ -361,6 +372,7 @@ AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip, options->use_keyframe_match = track->pattern_match == TRACK_MATCH_KEYFRAME; } + context->tracks[track_index] = track; ++track_index; } @@ -565,6 +577,7 @@ void BKE_autotrack_context_free(AutoTrackContext *context) libmv_autoTrackDestroy(context->autotrack); tracking_image_accessor_destroy(context->image_accessor); MEM_freeN(context->options); + MEM_freeN(context->tracks); BLI_spin_end(&context->spin_lock); MEM_freeN(context); } diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c index 1c056cda68d..a95399562d5 100644 --- a/source/blender/blenkernel/intern/tracking_util.c +++ b/source/blender/blenkernel/intern/tracking_util.c @@ -875,8 +875,64 @@ static void accessor_release_image_callback(libmv_CacheKey cache_key) IMB_freeImBuf(ibuf); } +static libmv_CacheKey accessor_get_mask_for_track_callback( + libmv_FrameAccessorUserData* user_data, + int clip_index, + int frame, + int track_index, + const libmv_Region *region, + float **r_destination, + int *r_width, + int *r_height) +{ + /* Perform sanity checks first. */ + TrackingImageAccessor *accessor = (TrackingImageAccessor *) user_data; + BLI_assert(clip_index < accessor->num_clips); + BLI_assert(track_index < accessor->num_tracks); + MovieTrackingTrack *track = accessor->tracks[track_index]; + /* Early output, track does not use mask. */ + if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) == 0) { + return NULL; + } + MovieClip *clip = accessor->clips[clip_index]; + /* Construct fake user so we can access movie clip. */ + MovieClipUser user; + int scene_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, frame); + BKE_movieclip_user_set_frame(&user, scene_frame); + user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL; + user.render_flag = 0; + /* Get frame width and height so we can convert stroke coordinates + * and other things from normalized to pixel space. + */ + int frame_width, frame_height; + BKE_movieclip_get_size(clip, &user, &frame_width, &frame_height); + /* Actual mask sampling. */ + MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, frame); + const float region_min[2] = {region->min[0] - marker->pos[0] * frame_width, + region->min[1] - marker->pos[1] * frame_height}; + const float region_max[2] = {region->max[0] - marker->pos[0] * frame_width, + region->max[1] - marker->pos[1] * frame_height}; + *r_destination = tracking_track_get_mask_for_region(frame_width, frame_height, + region_min, + region_max, + track); + *r_width = region->max[0] - region->min[0]; + *r_height = region->max[1] - region->min[1]; + return *r_destination; +} + +static void accessor_release_mask_callback(libmv_CacheKey cache_key) +{ + if (cache_key != NULL) { + float *mask = (float *)cache_key; + MEM_freeN(mask); + } +} + TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR_CLIP], int num_clips, + MovieTrackingTrack **tracks, + int num_tracks, int start_frame) { TrackingImageAccessor *accessor = @@ -891,12 +947,16 @@ TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR memcpy(accessor->clips, clips, num_clips * sizeof(MovieClip *)); accessor->num_clips = num_clips; + accessor->tracks = tracks; + accessor->num_tracks = num_tracks; accessor->start_frame = start_frame; accessor->libmv_accessor = libmv_FrameAccessorNew((libmv_FrameAccessorUserData *) accessor, accessor_get_image_callback, - accessor_release_image_callback); + accessor_release_image_callback, + accessor_get_mask_for_track_callback, + accessor_release_mask_callback); return accessor; } diff --git a/source/blender/blenkernel/tracking_private.h b/source/blender/blenkernel/tracking_private.h index 591ee4d0d01..1a68a1cac6a 100644 --- a/source/blender/blenkernel/tracking_private.h +++ b/source/blender/blenkernel/tracking_private.h @@ -105,6 +105,13 @@ struct MovieTrackingMarker *tracking_get_keyframed_marker( int current_frame, bool backwards); +/*********************** Masking *************************/ + +float *tracking_track_get_mask_for_region(int frame_width, int frame_height, + const float region_min[2], + const float region_max[2], + MovieTrackingTrack *track); + /*********************** Frame accessr *************************/ struct libmv_FrameAccessor; @@ -114,12 +121,16 @@ typedef struct TrackingImageAccessor { struct MovieCache *cache; struct MovieClip *clips[MAX_ACCESSOR_CLIP]; int num_clips; + struct MovieTrackingTrack **tracks; + int num_tracks; int start_frame; struct libmv_FrameAccessor *libmv_accessor; } TrackingImageAccessor; TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR_CLIP], int num_clips, + MovieTrackingTrack **tracks, + int num_tracks, int start_frame); void tracking_image_accessor_destroy(TrackingImageAccessor *accessor); |