[Bf-blender-cvs] [36b0c0e1d7b] tracking_average: Tracking: Implement tracks average operator

Sergey Sharybin noreply at git.blender.org
Tue Jan 5 09:50:13 CET 2021


Commit: 36b0c0e1d7bb58aece606f7baa8393fcb6b2b440
Author: Sergey Sharybin
Date:   Thu Nov 28 11:14:32 2019 +0100
Branches: tracking_average
https://developer.blender.org/rB36b0c0e1d7bb58aece606f7baa8393fcb6b2b440

Tracking: Implement tracks average operator

Average selected tracks into the new one. This can be used to improve
stability of tracking on blurry or non-very-sharp feature shapes.

Averaging happens for all position, pattern corners and search area.
Disabled markers do not take effect on averaging. Keyframed flag is
copied from source.

Gaps in the source tracks will be linearly interpolated, to reduce
result track jump. Note that this only applies to gaps "inbetween".
This means that if an input track doesn't have markers in the
beginning/end of it, there is nothing to interpolate with and the
result track will jump.

Available from the Track panel, under the Merge category.

Differential Revision: https://developer.blender.org/D6323

===================================================================

M	release/scripts/startup/bl_ui/space_clip.py
M	source/blender/blenkernel/BKE_tracking.h
M	source/blender/blenkernel/intern/tracking.c
M	source/blender/editors/space_clip/clip_intern.h
M	source/blender/editors/space_clip/space_clip.c
M	source/blender/editors/space_clip/tracking_ops.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index 35fd7333cf4..1d338bf2c3a 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -502,7 +502,9 @@ class CLIP_PT_tools_tracking(CLIP_PT_tracking_panel, Panel):
         col = layout.column(align=True)
         row = col.row(align=True)
         row.label(text="Merge:")
-        row.operator("clip.join_tracks", text="Join Tracks")
+        sub = row.column()
+        sub.operator("clip.join_tracks", text="Join Tracks")
+        sub.operator("clip.average_tracks", text="Average Tracks")
 
 
 class CLIP_PT_tools_plane_tracking(CLIP_PT_tracking_panel, Panel):
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index 5da8d969f1e..c2544c06514 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -89,6 +89,23 @@ struct MovieTrackingTrack *BKE_tracking_track_duplicate(struct MovieTrackingTrac
 void BKE_tracking_track_unique_name(struct ListBase *tracksbase, struct MovieTrackingTrack *track);
 void BKE_tracking_track_free(struct MovieTrackingTrack *track);
 
+void BKE_tracking_track_first_last_frame_get(const struct MovieTrackingTrack *track,
+                                             int *r_first_frame,
+                                             int *r_last_frame);
+
+void BKE_tracking_tracks_first_last_frame_minmax(/*const*/ struct MovieTrackingTrack **tracks,
+                                                 const int num_tracks,
+                                                 int *r_first_frame,
+                                                 int *r_last_frame);
+
+int BKE_tracking_count_selected_tracks_in_list(const struct ListBase *tracks_list);
+int BKE_tracking_count_selected_tracks_in_active_object(/*const*/ struct MovieTracking *tracking);
+
+/* Get array of selected tracks from the current active object in the tracking structure.
+ * If nothing is selected then the result is nullptr and `r_num_tracks` is set to 0. */
+struct MovieTrackingTrack **BKE_tracking_selected_tracks_in_active_object(
+    struct MovieTracking *tracking, int *r_num_tracks);
+
 void BKE_tracking_track_flag_set(struct MovieTrackingTrack *track, int area, int flag);
 void BKE_tracking_track_flag_clear(struct MovieTrackingTrack *track, int area, int flag);
 
@@ -96,10 +113,15 @@ bool BKE_tracking_track_has_marker_at_frame(struct MovieTrackingTrack *track, in
 bool BKE_tracking_track_has_enabled_marker_at_frame(struct MovieTrackingTrack *track, int framenr);
 
 void BKE_tracking_track_path_clear(struct MovieTrackingTrack *track, int ref_frame, int action);
+
 void BKE_tracking_tracks_join(struct MovieTracking *tracking,
                               struct MovieTrackingTrack *dst_track,
                               struct MovieTrackingTrack *src_track);
 
+void BKE_tracking_tracks_average(struct MovieTrackingTrack *dst_track,
+                                 /*const*/ struct MovieTrackingTrack **src_tracks,
+                                 const int num_src_tracks);
+
 struct MovieTrackingTrack *BKE_tracking_track_get_named(struct MovieTracking *tracking,
                                                         struct MovieTrackingObject *object,
                                                         const char *name);
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index bc892c7dd88..e41d8e5a162 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -587,15 +587,15 @@ MovieTrackingTrack *BKE_tracking_track_add(MovieTracking *tracking,
 {
   const MovieTrackingSettings *settings = &tracking->settings;
 
+  MovieTrackingTrack *track = BKE_tracking_track_add_empty(tracking, tracksbase);
+  MovieTrackingMarker marker;
+
   const float half_pattern_px = settings->default_pattern_size / 2.0f;
   const float half_search_px = settings->default_search_size / 2.0f;
 
   const float pattern_size[2] = {half_pattern_px / width, half_pattern_px / height};
   const float search_size[2] = {half_search_px / width, half_search_px / height};
 
-  MovieTrackingTrack *track = BKE_tracking_track_add_empty(tracking, tracksbase);
-
-  MovieTrackingMarker marker;
   memset(&marker, 0, sizeof(marker));
   marker.pos[0] = x;
   marker.pos[1] = y;
@@ -665,6 +665,86 @@ void BKE_tracking_track_free(MovieTrackingTrack *track)
   }
 }
 
+/* Get frame numbers of the very first and last markers.
+ * There is no check on whether the marker is enabled or not. */
+void BKE_tracking_track_first_last_frame_get(const MovieTrackingTrack *track,
+                                             int *r_first_frame,
+                                             int *r_last_frame)
+{
+  BLI_assert(track->markersnr > 0);
+  const int last_marker_index = track->markersnr - 1;
+  *r_first_frame = track->markers[0].framenr;
+  *r_last_frame = track->markers[last_marker_index].framenr;
+}
+
+/* Find the minimum starting frame and maximum ending frame within given set of
+ * tracks.
+ */
+void BKE_tracking_tracks_first_last_frame_minmax(/*const*/ MovieTrackingTrack **tracks,
+                                                 const int num_tracks,
+                                                 int *r_first_frame,
+                                                 int *r_last_frame)
+{
+  *r_first_frame = INT_MAX;
+  *r_last_frame = INT_MIN;
+  for (int i = 0; i < num_tracks; ++i) {
+    const struct MovieTrackingTrack *track = tracks[i];
+    int track_first_frame, track_last_frame;
+    BKE_tracking_track_first_last_frame_get(track, &track_first_frame, &track_last_frame);
+    *r_first_frame = min_ii(*r_first_frame, track_first_frame);
+    *r_last_frame = max_ii(*r_last_frame, track_last_frame);
+  }
+}
+
+int BKE_tracking_count_selected_tracks_in_list(const ListBase *tracks_list)
+{
+  int num_selected_tracks = 0;
+  LISTBASE_FOREACH (const MovieTrackingTrack *, track, tracks_list) {
+    if (TRACK_SELECTED(track)) {
+      ++num_selected_tracks;
+    }
+  }
+  return num_selected_tracks;
+}
+
+int BKE_tracking_count_selected_tracks_in_active_object(/*const*/ MovieTracking *tracking)
+{
+  ListBase *tracks_list = BKE_tracking_get_active_tracks(tracking);
+  return BKE_tracking_count_selected_tracks_in_list(tracks_list);
+}
+
+MovieTrackingTrack **BKE_tracking_selected_tracks_in_active_object(MovieTracking *tracking,
+                                                                   int *r_num_tracks)
+{
+  *r_num_tracks = 0;
+
+  ListBase *tracks_list = BKE_tracking_get_active_tracks(tracking);
+  if (tracks_list == NULL) {
+    return NULL;
+  }
+
+  /* Initialize input. */
+  const int num_selected_tracks = BKE_tracking_count_selected_tracks_in_active_object(tracking);
+  if (num_selected_tracks == 0) {
+    return NULL;
+  }
+
+  MovieTrackingTrack **source_tracks = MEM_malloc_arrayN(
+      num_selected_tracks, sizeof(MovieTrackingTrack *), "selected tracks array");
+  int source_track_index = 0;
+  LISTBASE_FOREACH (MovieTrackingTrack *, track, tracks_list) {
+    if (!TRACK_SELECTED(track)) {
+      continue;
+    }
+    source_tracks[source_track_index] = track;
+    ++source_track_index;
+  }
+
+  *r_num_tracks = num_selected_tracks;
+
+  return source_tracks;
+}
+
 /* Set flag for all specified track's areas.
  *
  * area - which part of marker should be selected. see TRACK_AREA_* constants.
@@ -918,6 +998,96 @@ void BKE_tracking_tracks_join(MovieTracking *tracking,
   BKE_tracking_dopesheet_tag_update(tracking);
 }
 
+static void accumulate_marker(MovieTrackingMarker *dst_marker,
+                              const MovieTrackingMarker *src_marker)
+{
+  BLI_assert(dst_marker->framenr == src_marker->framenr);
+
+  if (src_marker->flag & MARKER_DISABLED) {
+    return;
+  }
+
+  add_v2_v2(dst_marker->pos, src_marker->pos);
+  for (int corner = 0; corner < 4; ++corner) {
+    add_v2_v2(dst_marker->pattern_corners[corner], src_marker->pattern_corners[corner]);
+  }
+  add_v2_v2(dst_marker->search_min, src_marker->search_min);
+  add_v2_v2(dst_marker->search_max, src_marker->search_max);
+
+  BLI_assert(is_finite_v2(src_marker->search_min));
+  BLI_assert(is_finite_v2(src_marker->search_max));
+
+  dst_marker->flag &= ~MARKER_DISABLED;
+  if ((src_marker->flag & MARKER_TRACKED) == 0) {
+    dst_marker->flag &= ~MARKER_TRACKED;
+  }
+}
+
+static void multiply_marker(MovieTrackingMarker *marker, const float multiplier)
+{
+  mul_v2_fl(marker->pos, multiplier);
+  for (int corner = 0; corner < 4; ++corner) {
+    mul_v2_fl(marker->pattern_corners[corner], multiplier);
+  }
+  mul_v2_fl(marker->search_min, multiplier);
+  mul_v2_fl(marker->search_max, multiplier);
+}
+
+void BKE_tracking_tracks_average(MovieTrackingTrack *dst_track,
+                                 /*const*/ MovieTrackingTrack **src_tracks,
+                                 const int num_src_tracks)
+{
+  /* Get global range of frames within which averaging would happen. */
+  int first_frame, last_frame;
+  BKE_tracking_tracks_first_last_frame_minmax(
+      src_tracks, num_src_tracks, &first_frame, &last_frame);
+  if (last_frame < first_frame) {
+    return;
+  }
+  const int num_frames = last_frame - first_frame + 1;
+
+  /* Allocate temporary array where averaging will happen into. */
+  MovieTrackingMarker *accumulator = MEM_calloc_arrayN(
+      num_frames, sizeof(MovieTrackingMarker), "tracks average accumulator");
+  int *counters = MEM_calloc_arrayN(num_frames, sizeof(int), "tracks accumulator counters");
+  for (int frame = first_frame; frame <= last_frame; ++frame) {
+    const int frame_index = frame - first_frame;
+    accumulator[frame_index].framenr = frame;
+    accumulator[frame_index].flag |= (MARKER_DISABLED | MARKER_TRACKED);
+  }
+
+  /* Accumulate track markers. */
+  for (int track_index = 0; track_index < num_src_tracks; ++track_index) {
+    /*const*/ MovieTrackingTrack *track = src_tracks[track_index];
+    for (int frame = first_frame; frame <= last_frame; ++frame) {
+      MovieTrackingMarker interpolated_marker;
+      if (!BKE_tracking_marker_get

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list