Implement per-frame track reprojection error visualization

It is now possible to display per-frame track reprojection
error in curve view of clip editor. Simply enable corresponding
option in filter buttons.

Currently displayed using blue color which might confuse with
average reprojection error, further color tweaks are possible
and easy.

Also changed icon track x/y curves. Better icons here are
really appreciated.
This commit is contained in:
Sergey Sharybin 2013-10-13 22:26:29 +02:00
parent 122e2b4bfa
commit 28b671d98f
8 changed files with 152 additions and 38 deletions

View File

@ -98,7 +98,8 @@ class CLIP_HT_header(Header):
sub.active = clip.tracking.reconstruction.is_valid
sub.prop(sc, "show_graph_frames", icon='SEQUENCE', text="")
row.prop(sc, "show_graph_tracks", icon='ANIM', text="")
row.prop(sc, "show_graph_tracks_motion", icon='IPO', text="")
row.prop(sc, "show_graph_tracks_error", icon='ANIM', text="")
else:
row.prop(sc, "show_filters", icon='DISCLOSURE_TRI_RIGHT',
text="Filters")

View File

@ -116,7 +116,7 @@ static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track,
glBegin(GL_LINE_STRIP);
}
static void tracking_segment_end_cb(void *UNUSED(userdata))
static void tracking_segment_end_cb(void *UNUSED(userdata), int UNUSED(coord))
{
glEnd();
@ -151,7 +151,7 @@ static void tracking_segment_knot_cb(void *userdata, MovieTrackingTrack *track,
}
}
static void draw_tracks_curves(View2D *v2d, SpaceClip *sc)
static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc)
{
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
@ -191,6 +191,108 @@ static void draw_tracks_curves(View2D *v2d, SpaceClip *sc)
&userdata, tracking_segment_knot_cb, NULL, NULL);
}
typedef struct TrackErrorCurveUserData {
MovieTracking *tracking;
MovieTrackingObject *tracking_object;
MovieTrackingTrack *active_track;
bool matrix_initialized;
int matrix_frame;
float projection_matrix[4][4];
int width, height;
float aspy;
} TrackErrorCurveUserData;
static void tracking_error_segment_point_cb(void *userdata,
MovieTrackingTrack *track, MovieTrackingMarker *marker,
int coord, int scene_framenr, float UNUSED(value))
{
if (coord == 1) {
TrackErrorCurveUserData *data = (TrackErrorCurveUserData *) userdata;
float reprojected_position[4], bundle_position[4], marker_position[2], delta[2];
float reprojection_error;
if (!data->matrix_initialized || data->matrix_frame != scene_framenr) {
BKE_tracking_get_projection_matrix(data->tracking, data->tracking_object,
scene_framenr, data->width, data->height,
data->projection_matrix);
}
copy_v3_v3(bundle_position, track->bundle_pos);
bundle_position[3] = 1;
mul_v4_m4v4(reprojected_position, data->projection_matrix, bundle_position);
reprojected_position[0] = (reprojected_position[0] /
(reprojected_position[3] * 2.0f) + 0.5f) * data->width;
reprojected_position[1] = (reprojected_position[1] /
(reprojected_position[3] * 2.0f) + 0.5f) * data->height * data->aspy;
BKE_tracking_distort_v2(data->tracking, reprojected_position, reprojected_position);
marker_position[0] = (marker->pos[0] + track->offset[0]) * data->width;
marker_position[1] = (marker->pos[1] + track->offset[1]) * data->height * data->aspy;
sub_v2_v2v2(delta, reprojected_position, marker_position);
reprojection_error = len_v2(delta);
glVertex2f(scene_framenr, reprojection_error);
}
}
static void tracking_error_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord)
{
if (coord == 1) {
TrackErrorCurveUserData *data = (TrackErrorCurveUserData *) userdata;
float col[4] = {0.0f, 0.0f, 1.0f, 1.0f};
if (track == data->active_track) {
col[3] = 1.0f;
glLineWidth(2.0f);
}
else {
col[3] = 0.5f;
glLineWidth(1.0f);
}
glColor4fv(col);
glBegin(GL_LINE_STRIP);
}
}
static void tracking_error_segment_end_cb(void *UNUSED(userdata), int coord)
{
if (coord == 1) {
glEnd();
glLineWidth(1.0f);
}
}
static void draw_tracks_error_curves(SpaceClip *sc)
{
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
TrackErrorCurveUserData data;
data.tracking = tracking;
data.tracking_object = BKE_tracking_object_get_active(tracking);
data.active_track = BKE_tracking_track_get_active(tracking);
data.matrix_initialized = false;
BKE_movieclip_get_size(clip, &sc->user, &data.width, &data.height);
data.aspy = 1.0f / tracking->camera.pixel_aspect;
if (!data.width || !data.height) {
return;
}
clip_graph_tracking_values_iterate(sc,
(sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
(sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
&data,
tracking_error_segment_point_cb,
tracking_error_segment_start_cb,
tracking_error_segment_end_cb);
}
static void draw_frame_curves(SpaceClip *sc)
{
MovieClip *clip = ED_space_clip_get_clip(sc);
@ -237,8 +339,11 @@ void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene)
UI_view2d_grid_free(grid);
if (clip) {
if (sc->flag & SC_SHOW_GRAPH_TRACKS)
draw_tracks_curves(v2d, sc);
if (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION)
draw_tracks_motion_curves(v2d, sc);
if (sc->flag & SC_SHOW_GRAPH_TRACKS_ERROR)
draw_tracks_error_curves(sc);
if (sc->flag & SC_SHOW_GRAPH_FRAMES)
draw_frame_curves(sc);

View File

@ -130,7 +130,7 @@ static void find_nearest_tracking_segment_cb(void *userdata, MovieTrackingTrack
copy_v2_v2(data->prev_co, co);
}
static void find_nearest_tracking_segment_end_cb(void *userdata)
static void find_nearest_tracking_segment_end_cb(void *userdata, int UNUSED(coord))
{
MouseSelectUserData *data = userdata;

View File

@ -125,12 +125,12 @@ void ED_clip_tool_props_register(struct ARegionType *art);
void clip_graph_tracking_values_iterate_track(struct SpaceClip *sc, struct MovieTrackingTrack *track, void *userdata,
void (*func)(void *userdata, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int coord, int scene_framenr, float val),
void (*segment_start)(void *userdata, struct MovieTrackingTrack *track, int coord),
void (*segment_end)(void *userdata));
void (*segment_end)(void *userdata, int coord));
void clip_graph_tracking_values_iterate(struct SpaceClip *sc, bool selected_only, bool include_hidden, void *userdata,
void (*func)(void *userdata, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int coord, int scene_framenr, float val),
void (*segment_start)(void *userdata, struct MovieTrackingTrack *track, int coord),
void (*segment_end)(void *userdata));
void (*segment_end)(void *userdata, int coord));
void clip_graph_tracking_iterate(struct SpaceClip *sc, bool selected_only, bool include_hidden, void *userdata,
void (*func)(void *userdata, struct MovieTrackingMarker *marker));

View File

@ -70,7 +70,7 @@ void clip_graph_tracking_values_iterate_track(
void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord,
int scene_framenr, float val),
void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord),
void (*segment_end)(void *userdata))
void (*segment_end)(void *userdata, int coord))
{
MovieClip *clip = ED_space_clip_get_clip(sc);
int width, height, coord;
@ -89,7 +89,7 @@ void clip_graph_tracking_values_iterate_track(
if (marker->flag & MARKER_DISABLED) {
if (open) {
if (segment_end)
segment_end(userdata);
segment_end(userdata, coord);
open = false;
}
@ -121,7 +121,7 @@ void clip_graph_tracking_values_iterate_track(
if (open) {
if (segment_end)
segment_end(userdata);
segment_end(userdata, coord);
}
}
}
@ -131,7 +131,7 @@ void clip_graph_tracking_values_iterate(
void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker,
int coord, int scene_framenr, float val),
void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord),
void (*segment_end)(void *userdata))
void (*segment_end)(void *userdata, int coord))
{
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;

View File

@ -247,7 +247,7 @@ static SpaceLink *clip_new(const bContext *C)
sc = MEM_callocN(sizeof(SpaceClip), "initclip");
sc->spacetype = SPACE_CLIP;
sc->flag = SC_SHOW_MARKER_PATTERN | SC_SHOW_TRACK_PATH | SC_MANUAL_CALIBRATION |
SC_SHOW_GRAPH_TRACKS | SC_SHOW_GRAPH_FRAMES | SC_SHOW_GPENCIL;
SC_SHOW_GRAPH_TRACKS_MOTION | SC_SHOW_GRAPH_FRAMES | SC_SHOW_GPENCIL;
sc->zoom = 1.0f;
sc->path_length = 20;
sc->scopes.track_preview_height = 120;

View File

@ -1107,27 +1107,28 @@ typedef struct SpaceClip {
/* SpaceClip->flag */
typedef enum eSpaceClip_Flag {
SC_SHOW_MARKER_PATTERN = (1 << 0),
SC_SHOW_MARKER_SEARCH = (1 << 1),
SC_LOCK_SELECTION = (1 << 2),
SC_SHOW_TINY_MARKER = (1 << 3),
SC_SHOW_TRACK_PATH = (1 << 4),
SC_SHOW_BUNDLES = (1 << 5),
SC_MUTE_FOOTAGE = (1 << 6),
SC_HIDE_DISABLED = (1 << 7),
SC_SHOW_NAMES = (1 << 8),
SC_SHOW_GRID = (1 << 9),
SC_SHOW_STABLE = (1 << 10),
SC_MANUAL_CALIBRATION = (1 << 11),
SC_SHOW_GPENCIL = (1 << 12),
SC_SHOW_FILTERS = (1 << 13),
SC_SHOW_GRAPH_FRAMES = (1 << 14),
SC_SHOW_GRAPH_TRACKS = (1 << 15),
/* SC_SHOW_PYRAMID_LEVELS = (1 << 16), */ /* UNUSED */
SC_LOCK_TIMECURSOR = (1 << 17),
SC_SHOW_SECONDS = (1 << 18),
SC_SHOW_GRAPH_SEL_ONLY = (1 << 19),
SC_SHOW_GRAPH_HIDDEN = (1 << 20),
SC_SHOW_MARKER_PATTERN = (1 << 0),
SC_SHOW_MARKER_SEARCH = (1 << 1),
SC_LOCK_SELECTION = (1 << 2),
SC_SHOW_TINY_MARKER = (1 << 3),
SC_SHOW_TRACK_PATH = (1 << 4),
SC_SHOW_BUNDLES = (1 << 5),
SC_MUTE_FOOTAGE = (1 << 6),
SC_HIDE_DISABLED = (1 << 7),
SC_SHOW_NAMES = (1 << 8),
SC_SHOW_GRID = (1 << 9),
SC_SHOW_STABLE = (1 << 10),
SC_MANUAL_CALIBRATION = (1 << 11),
SC_SHOW_GPENCIL = (1 << 12),
SC_SHOW_FILTERS = (1 << 13),
SC_SHOW_GRAPH_FRAMES = (1 << 14),
SC_SHOW_GRAPH_TRACKS_MOTION = (1 << 15),
/* SC_SHOW_PYRAMID_LEVELS = (1 << 16), */ /* UNUSED */
SC_LOCK_TIMECURSOR = (1 << 17),
SC_SHOW_SECONDS = (1 << 18),
SC_SHOW_GRAPH_SEL_ONLY = (1 << 19),
SC_SHOW_GRAPH_HIDDEN = (1 << 20),
SC_SHOW_GRAPH_TRACKS_ERROR = (1 << 21),
} eSpaceClip_Flag;
/* SpaceClip->mode */

View File

@ -3745,14 +3745,21 @@ static void rna_def_space_clip(BlenderRNA *brna)
"Show curve for per-frame average error (camera motion should be solved first)");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL);
/* show graph_tracks */
prop = RNA_def_property(srna, "show_graph_tracks", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_SHOW_GRAPH_TRACKS);
RNA_def_property_ui_text(prop, "Show Tracks",
/* show graph tracks motion */
prop = RNA_def_property(srna, "show_graph_tracks_motion", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_SHOW_GRAPH_TRACKS_MOTION);
RNA_def_property_ui_text(prop, "Show Tracks Motion",
"Display the speed curves (in \"x\" direction red, in \"y\" direction green) "
"for the selected tracks");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL);
/* show graph tracks motion */
prop = RNA_def_property(srna, "show_graph_tracks_error", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_SHOW_GRAPH_TRACKS_ERROR);
RNA_def_property_ui_text(prop, "Show Tracks Error",
"Display the reprojection error curve for selected tracks");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL);
/* show_only_selected */
prop = RNA_def_property(srna, "show_graph_only_selected", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_SHOW_GRAPH_SEL_ONLY);