Tracking: Sort motion tracking tracks by start and end frames

Enable sorting motion tracking tracks by start / end times.

Help identifying what cases reconstructed camera jumps, based
on information about whether any track starts/ends at the frame.

Based on revision eb0eb54d96.

{F10563305}

Reviewed By: sergey

Differential Revision: https://developer.blender.org/D12621
This commit is contained in:
Johan Walles 2021-10-01 12:35:00 +02:00 committed by Sergey Sharybin
parent f497e471f8
commit fb820496f5
3 changed files with 108 additions and 0 deletions

View File

@ -3014,6 +3014,61 @@ static int channels_average_error_sort(const void *a, const void *b)
return 0;
}
static int compare_firstlast_putting_undefined_first(
bool inverse, bool a_markerless, int a_value, bool b_markerless, int b_value)
{
if (a_markerless && b_markerless) {
/* Neither channel has not-disabled markers, return whatever. */
return 0;
}
if (a_markerless) {
/* Put the markerless channel first. */
return 0;
}
if (b_markerless) {
/* Put the markerless channel first. */
return 1;
}
/* Both channels have markers. */
if (inverse) {
if (a_value < b_value) {
return 1;
}
return 0;
}
if (a_value > b_value) {
return 1;
}
return 0;
}
static int channels_start_sort(const void *a, const void *b)
{
const MovieTrackingDopesheetChannel *channel_a = a;
const MovieTrackingDopesheetChannel *channel_b = b;
return compare_firstlast_putting_undefined_first(false,
channel_a->tot_segment == 0,
channel_a->first_not_disabled_marker_framenr,
channel_b->tot_segment == 0,
channel_b->first_not_disabled_marker_framenr);
}
static int channels_end_sort(const void *a, const void *b)
{
const MovieTrackingDopesheetChannel *channel_a = a;
const MovieTrackingDopesheetChannel *channel_b = b;
return compare_firstlast_putting_undefined_first(false,
channel_a->tot_segment == 0,
channel_a->last_not_disabled_marker_framenr,
channel_b->tot_segment == 0,
channel_b->last_not_disabled_marker_framenr);
}
static int channels_alpha_inverse_sort(const void *a, const void *b)
{
if (channels_alpha_sort(a, b)) {
@ -3053,22 +3108,51 @@ static int channels_average_error_inverse_sort(const void *a, const void *b)
return 0;
}
static int channels_start_inverse_sort(const void *a, const void *b)
{
const MovieTrackingDopesheetChannel *channel_a = a;
const MovieTrackingDopesheetChannel *channel_b = b;
return compare_firstlast_putting_undefined_first(true,
channel_a->tot_segment == 0,
channel_a->first_not_disabled_marker_framenr,
channel_b->tot_segment == 0,
channel_b->first_not_disabled_marker_framenr);
}
static int channels_end_inverse_sort(const void *a, const void *b)
{
const MovieTrackingDopesheetChannel *channel_a = a;
const MovieTrackingDopesheetChannel *channel_b = b;
return compare_firstlast_putting_undefined_first(true,
channel_a->tot_segment == 0,
channel_a->last_not_disabled_marker_framenr,
channel_b->tot_segment == 0,
channel_b->last_not_disabled_marker_framenr);
}
/* Calculate frames segments at which track is tracked continuously. */
static void tracking_dopesheet_channels_segments_calc(MovieTrackingDopesheetChannel *channel)
{
MovieTrackingTrack *track = channel->track;
int i, segment;
bool first_not_disabled_marker_framenr_set;
channel->tot_segment = 0;
channel->max_segment = 0;
channel->total_frames = 0;
channel->first_not_disabled_marker_framenr = 0;
channel->last_not_disabled_marker_framenr = 0;
/* TODO(sergey): looks a bit code-duplicated, need to look into
* logic de-duplication here.
*/
/* count */
i = 0;
first_not_disabled_marker_framenr_set = false;
while (i < track->markersnr) {
MovieTrackingMarker *marker = &track->markers[i];
@ -3086,6 +3170,12 @@ static void tracking_dopesheet_channels_segments_calc(MovieTrackingDopesheetChan
break;
}
if (!first_not_disabled_marker_framenr_set) {
channel->first_not_disabled_marker_framenr = marker->framenr;
first_not_disabled_marker_framenr_set = true;
}
channel->last_not_disabled_marker_framenr = marker->framenr;
prev_fra = marker->framenr;
len++;
i++;
@ -3203,6 +3293,12 @@ static void tracking_dopesheet_channels_sort(MovieTracking *tracking,
else if (sort_method == TRACKING_DOPE_SORT_AVERAGE_ERROR) {
BLI_listbase_sort(&dopesheet->channels, channels_average_error_inverse_sort);
}
else if (sort_method == TRACKING_DOPE_SORT_START) {
BLI_listbase_sort(&dopesheet->channels, channels_start_inverse_sort);
}
else if (sort_method == TRACKING_DOPE_SORT_END) {
BLI_listbase_sort(&dopesheet->channels, channels_end_inverse_sort);
}
}
else {
if (sort_method == TRACKING_DOPE_SORT_NAME) {
@ -3217,6 +3313,12 @@ static void tracking_dopesheet_channels_sort(MovieTracking *tracking,
else if (sort_method == TRACKING_DOPE_SORT_AVERAGE_ERROR) {
BLI_listbase_sort(&dopesheet->channels, channels_average_error_sort);
}
else if (sort_method == TRACKING_DOPE_SORT_START) {
BLI_listbase_sort(&dopesheet->channels, channels_start_sort);
}
else if (sort_method == TRACKING_DOPE_SORT_END) {
BLI_listbase_sort(&dopesheet->channels, channels_end_sort);
}
}
}

View File

@ -398,6 +398,8 @@ typedef struct MovieTrackingDopesheetChannel {
int *segments;
/** Longest segment length and total number of tracked frames. */
int max_segment, total_frames;
/** These numbers are valid only if tot_segment > 0. */
int first_not_disabled_marker_framenr, last_not_disabled_marker_framenr;
} MovieTrackingDopesheetChannel;
typedef struct MovieTrackingDopesheetCoverageSegment {
@ -592,6 +594,8 @@ enum {
TRACKING_DOPE_SORT_LONGEST = 1,
TRACKING_DOPE_SORT_TOTAL = 2,
TRACKING_DOPE_SORT_AVERAGE_ERROR = 3,
TRACKING_DOPE_SORT_START = 4,
TRACKING_DOPE_SORT_END = 5,
};
/* MovieTrackingDopesheet->flag */

View File

@ -2437,6 +2437,8 @@ static void rna_def_trackingDopesheet(BlenderRNA *brna)
0,
"Average Error",
"Sort channels by average reprojection error of tracks after solve"},
{TRACKING_DOPE_SORT_START, "START", 0, "Start Frame", "Sort channels by first frame number"},
{TRACKING_DOPE_SORT_END, "END", 0, "End Frame", "Sort channels by last frame number"},
{0, NULL, 0, NULL, NULL},
};