Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/tracking.c')
-rw-r--r--source/blender/blenkernel/intern/tracking.c329
1 files changed, 284 insertions, 45 deletions
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index 801fecc9f7c..df10d1374bb 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -141,8 +141,10 @@ static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet)
}
BLI_freelistN(&dopesheet->channels);
+ BLI_freelistN(&dopesheet->coverage_segments);
dopesheet->channels.first = dopesheet->channels.last = NULL;
+ dopesheet->coverage_segments.first = dopesheet->coverage_segments.last = NULL;
dopesheet->tot_channel = 0;
}
@@ -169,8 +171,9 @@ void BKE_tracking_settings_init(MovieTracking *tracking)
tracking->settings.default_motion_model = TRACK_MOTION_MODEL_TRANSLATION;
tracking->settings.default_minimum_correlation = 0.75;
- tracking->settings.default_pattern_size = 11;
+ tracking->settings.default_pattern_size = 15;
tracking->settings.default_search_size = 61;
+ tracking->settings.default_algorithm_flag |= TRACK_ALGORITHM_FLAG_USE_BRUTE;
tracking->settings.dist = 1;
tracking->settings.object_distance = 1;
tracking->settings.reconstruction_success_threshold = 1e-3;
@@ -258,7 +261,9 @@ void BKE_tracking_get_projection_matrix(MovieTracking *tracking, MovieTrackingOb
invert_m4_m4(imat, camera->mat);
mult_m4_m4m4(mat, winmat, imat);
}
- else copy_m4_m4(mat, winmat);
+ else {
+ copy_m4_m4(mat, winmat);
+ }
}
/* **** space transformation functions **** */
@@ -1186,6 +1191,7 @@ MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char
object->keyframe2 = 30;
BKE_tracking_object_unique_name(tracking, object);
+ BKE_tracking_dopesheet_tag_update(tracking);
return object;
}
@@ -1220,6 +1226,9 @@ int BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *obj
tracking->objectnr = index - 1;
else
tracking->objectnr = 0;
+
+ BKE_tracking_dopesheet_tag_update(tracking);
+
return TRUE;
}
@@ -1426,40 +1435,65 @@ void BKE_tracking_camera_get_reconstructed_interpolate(MovieTracking *tracking,
/*********************** Distortion/Undistortion *************************/
+#ifdef WITH_LIBMV
+static void cameraIntrinscisOptionsFromTracking(libmv_cameraIntrinsicsOptions *camera_intrinsics_options,
+ MovieTracking *tracking, int calibration_width, int calibration_height)
+{
+ MovieTrackingCamera *camera = &tracking->camera;
+ float aspy = 1.0f / tracking->camera.pixel_aspect;
+
+ camera_intrinsics_options->focal_length = camera->focal;
+
+ camera_intrinsics_options->principal_point_x = camera->principal[0];
+ camera_intrinsics_options->principal_point_y = camera->principal[1] * aspy;
+
+ camera_intrinsics_options->k1 = camera->k1;
+ camera_intrinsics_options->k2 = camera->k2;
+ camera_intrinsics_options->k3 = camera->k3;
+
+ camera_intrinsics_options->image_width = calibration_width;
+ camera_intrinsics_options->image_height = (double) (calibration_height * aspy);
+}
+#endif
+
MovieDistortion *BKE_tracking_distortion_new(void)
{
MovieDistortion *distortion;
distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
+#ifdef WITH_LIBMV
+ distortion->intrinsics = libmv_CameraIntrinsicsNewEmpty();
+#endif
+
return distortion;
}
void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking,
int calibration_width, int calibration_height)
{
- MovieTrackingCamera *camera = &tracking->camera;
- float aspy = 1.0f / tracking->camera.pixel_aspect;
-
#ifdef WITH_LIBMV
- if (!distortion->intrinsics) {
- distortion->intrinsics = libmv_CameraIntrinsicsNew(camera->focal,
- camera->principal[0], camera->principal[1] * aspy,
- camera->k1, camera->k2, camera->k3,
- calibration_width, calibration_height * aspy);
- }
- else {
- libmv_CameraIntrinsicsUpdate(distortion->intrinsics, camera->focal,
- camera->principal[0], camera->principal[1] * aspy,
- camera->k1, camera->k2, camera->k3,
- calibration_width, calibration_height * aspy);
- }
+ libmv_cameraIntrinsicsOptions camera_intrinsics_options;
+
+ cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking,
+ calibration_width, calibration_height);
+
+ libmv_CameraIntrinsicsUpdate(distortion->intrinsics, &camera_intrinsics_options);
#else
(void) distortion;
+ (void) tracking;
(void) calibration_width;
(void) calibration_height;
- (void) camera;
- (void) aspy;
+#endif
+}
+
+void BKE_tracking_distortion_set_threads(MovieDistortion *distortion, int threads)
+{
+#ifdef WITH_LIBMV
+ libmv_CameraIntrinsicsSetThreads(distortion->intrinsics, threads);
+#else
+ (void) distortion;
+ (void) threads;
#endif
}
@@ -1540,15 +1574,17 @@ void BKE_tracking_distort_v2(MovieTracking *tracking, const float co[2], float r
MovieTrackingCamera *camera = &tracking->camera;
#ifdef WITH_LIBMV
+ libmv_cameraIntrinsicsOptions camera_intrinsics_options;
double x, y;
float aspy = 1.0f / tracking->camera.pixel_aspect;
+ cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking, 0, 0);
+
/* normalize coords */
x = (co[0] - camera->principal[0]) / camera->focal;
y = (co[1] - camera->principal[1] * aspy) / camera->focal;
- libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
- camera->k1, camera->k2, camera->k3, x, y, &x, &y);
+ libmv_applyCameraIntrinsics(&camera_intrinsics_options, x, y, &x, &y);
/* result is in image coords already */
r_co[0] = x;
@@ -1565,14 +1601,16 @@ void BKE_tracking_undistort_v2(MovieTracking *tracking, const float co[2], float
MovieTrackingCamera *camera = &tracking->camera;
#ifdef WITH_LIBMV
+ libmv_cameraIntrinsicsOptions camera_intrinsics_options;
double x = co[0], y = co[1];
float aspy = 1.0f / tracking->camera.pixel_aspect;
- libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
- camera->k1, camera->k2, camera->k3, x, y, &x, &y);
+ cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking, 0, 0);
- r_co[0] = x * camera->focal + camera->principal[0];
- r_co[1] = y * camera->focal + camera->principal[1] * aspy;
+ libmv_InvertIntrinsics(&camera_intrinsics_options, x, y, &x, &y);
+
+ r_co[0] = (float)x * camera->focal + camera->principal[0];
+ r_co[1] = (float)y * camera->focal + camera->principal[1] * aspy;
#else
(void) camera;
(void) co;
@@ -1604,6 +1642,67 @@ ImBuf *BKE_tracking_distort_frame(MovieTracking *tracking, ImBuf *ibuf, int cali
calibration_height, overscan, FALSE);
}
+void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, rcti *rect, float delta[2])
+{
+ int a;
+ float pos[2], warped_pos[2];
+ const int coord_delta = 5;
+
+ delta[0] = delta[1] = -FLT_MAX;
+
+ for (a = rect->xmin; a <= rect->xmax + coord_delta; a += coord_delta) {
+ if (a > rect->xmax)
+ a = rect->xmax;
+
+ /* bottom edge */
+ pos[0] = a;
+ pos[1] = rect->ymin;
+
+ BKE_tracking_undistort_v2(tracking, pos, warped_pos);
+
+ delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
+ delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
+
+ /* top edge */
+ pos[0] = a;
+ pos[1] = rect->ymax;
+
+ BKE_tracking_undistort_v2(tracking, pos, warped_pos);
+
+ delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
+ delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
+
+ if (a >= rect->xmax)
+ break;
+ }
+
+ for (a = rect->ymin; a <= rect->ymax + coord_delta; a += coord_delta) {
+ if (a > rect->ymax)
+ a = rect->ymax;
+
+ /* left edge */
+ pos[0] = rect->xmin;
+ pos[1] = a;
+
+ BKE_tracking_undistort_v2(tracking, pos, warped_pos);
+
+ delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
+ delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
+
+ /* right edge */
+ pos[0] = rect->xmax;
+ pos[1] = a;
+
+ BKE_tracking_undistort_v2(tracking, pos, warped_pos);
+
+ delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
+ delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
+
+ if (a >= rect->ymax)
+ break;
+ }
+}
+
/*********************** Image sampling *************************/
static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale)
@@ -1615,7 +1714,7 @@ static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int g
ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *search_ibuf,
MovieTrackingTrack *track, MovieTrackingMarker *marker,
- int use_mask, int num_samples_x, int num_samples_y,
+ int from_anchor, int use_mask, int num_samples_x, int num_samples_y,
float pos[2])
{
#ifdef WITH_LIBMV
@@ -1635,6 +1734,28 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea
get_marker_coords_for_tracking(frame_width, frame_height, marker, src_pixel_x, src_pixel_y);
+ /* from_anchor means search buffer was obtained for an anchored position,
+ * which means applying track offset rounded to pixel space (we could not
+ * store search buffer with sub-pixel precision)
+ *
+ * in this case we need to alter coordinates a bit, to compensate rounded
+ * fractional part of offset
+ */
+ if (from_anchor) {
+ int a;
+
+ for (a = 0; a < 5; a++) {
+ src_pixel_x[a] += (double) ((track->offset[0] * frame_width) - ((int) (track->offset[0] * frame_width)));
+ src_pixel_y[a] += (double) ((track->offset[1] * frame_height) - ((int) (track->offset[1] * frame_height)));
+
+ /* when offset is negative, rounding happens in opposite direction */
+ if (track->offset[0] < 0.0f)
+ src_pixel_x[a] += 1.0;
+ if (track->offset[1] < 0.0f)
+ src_pixel_y[a] += 1.0;
+ }
+ }
+
if (use_mask) {
mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker);
}
@@ -1660,13 +1781,14 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea
/* real sampling requires libmv, but areas are supposing pattern would be
* sampled if search area does exists, so we'll need to create empty
* pattern area here to prevent adding NULL-checks all over just to deal
- * with situation when lubmv is disabled
+ * with situation when libmv is disabled
*/
(void) frame_width;
(void) frame_height;
(void) search_ibuf;
(void) marker;
+ (void) from_anchor;
(void) track;
(void) use_mask;
@@ -1695,7 +1817,7 @@ ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mo
if (search_ibuf) {
pattern_ibuf = BKE_tracking_sample_pattern(ibuf->x, ibuf->y, search_ibuf, track, marker,
- FALSE, num_samples_x, num_samples_y, NULL);
+ anchored, FALSE, num_samples_x, num_samples_y, NULL);
IMB_freeImBuf(search_ibuf);
}
@@ -2578,6 +2700,8 @@ typedef struct MovieReconstructContext {
float principal_point[2];
float k1, k2, k3;
+ int width, height;
+
float reprojection_error;
TracksMap *tracks_map;
@@ -2638,11 +2762,13 @@ static void reconstruct_retrieve_libmv_intrinscis(MovieReconstructContext *conte
&k1, &k2, &k3, &width, &height);
tracking->camera.focal = focal_length;
+
tracking->camera.principal[0] = principal_x;
+ tracking->camera.principal[1] = principal_y / (double)aspy;
- tracking->camera.principal[1] = principal_y / aspy;
tracking->camera.k1 = k1;
tracking->camera.k2 = k2;
+ tracking->camera.k3 = k3;
}
static int reconstruct_retrieve_libmv_tracks(MovieReconstructContext *context, MovieTracking *tracking)
@@ -2776,10 +2902,10 @@ static int reconstruct_refine_intrinsics_get_flags(MovieTracking *tracking, Movi
flags |= LIBMV_REFINE_PRINCIPAL_POINT;
if (refine & REFINE_RADIAL_DISTORTION_K1)
- flags |= REFINE_RADIAL_DISTORTION_K1;
+ flags |= LIBMV_REFINE_RADIAL_DISTORTION_K1;
if (refine & REFINE_RADIAL_DISTORTION_K2)
- flags |= REFINE_RADIAL_DISTORTION_K2;
+ flags |= LIBMV_REFINE_RADIAL_DISTORTION_K2;
return flags;
}
@@ -2850,6 +2976,9 @@ MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieTracking *
context->principal_point[0] = camera->principal[0];
context->principal_point[1] = camera->principal[1] * aspy;
+ context->width = width;
+ context->height = height;
+
context->k1 = camera->k1;
context->k2 = camera->k2;
context->k3 = camera->k3;
@@ -2932,6 +3061,34 @@ static void reconstruct_update_solve_cb(void *customdata, double progress, const
BLI_snprintf(progressdata->stats_message, progressdata->message_size, "Solving camera | %s", message);
}
+
+static void camraIntrincicsOptionsFromContext(libmv_cameraIntrinsicsOptions *camera_intrinsics_options,
+ MovieReconstructContext *context)
+{
+ camera_intrinsics_options->focal_length = context->focal_length;
+
+ camera_intrinsics_options->principal_point_x = context->principal_point[0];
+ camera_intrinsics_options->principal_point_y = context->principal_point[1];
+
+ camera_intrinsics_options->k1 = context->k1;
+ camera_intrinsics_options->k2 = context->k2;
+ camera_intrinsics_options->k3 = context->k3;
+
+ camera_intrinsics_options->image_width = context->width;
+ camera_intrinsics_options->image_height = context->height;
+}
+
+static void reconstructionOptionsFromContext(libmv_reconstructionOptions *reconstruction_options,
+ MovieReconstructContext *context)
+{
+ reconstruction_options->keyframe1 = context->keyframe1;
+ reconstruction_options->keyframe2 = context->keyframe2;
+
+ reconstruction_options->refine_intrinsics = context->refine_flags;
+
+ reconstruction_options->success_threshold = context->success_threshold;
+ reconstruction_options->use_fallback_reconstruction = context->use_fallback_reconstruction;
+}
#endif
void BKE_tracking_reconstruction_solve(MovieReconstructContext *context, short *stop, short *do_update,
@@ -2942,32 +3099,28 @@ void BKE_tracking_reconstruction_solve(MovieReconstructContext *context, short *
ReconstructProgressData progressdata;
+ libmv_cameraIntrinsicsOptions camera_intrinsics_options;
+ libmv_reconstructionOptions reconstruction_options;
+
progressdata.stop = stop;
progressdata.do_update = do_update;
progressdata.progress = progress;
progressdata.stats_message = stats_message;
progressdata.message_size = message_size;
+ camraIntrincicsOptionsFromContext(&camera_intrinsics_options, context);
+ reconstructionOptionsFromContext(&reconstruction_options, context);
+
if (context->motion_flag & TRACKING_MOTION_MODAL) {
context->reconstruction = libmv_solveModal(context->tracks,
- context->focal_length,
- context->principal_point[0], context->principal_point[1],
- context->k1, context->k2, context->k3,
+ &camera_intrinsics_options,
+ &reconstruction_options,
reconstruct_update_solve_cb, &progressdata);
}
else {
- struct libmv_reconstructionOptions options;
-
- options.success_threshold = context->success_threshold;
- options.use_fallback_reconstruction = context->use_fallback_reconstruction;
-
context->reconstruction = libmv_solveReconstruction(context->tracks,
- context->keyframe1, context->keyframe2,
- context->refine_flags,
- context->focal_length,
- context->principal_point[0], context->principal_point[1],
- context->k1, context->k2, context->k3,
- &options,
+ &camera_intrinsics_options,
+ &reconstruction_options,
reconstruct_update_solve_cb, &progressdata);
}
@@ -3722,6 +3875,88 @@ static void tracking_dopesheet_sort(MovieTracking *tracking, int sort_method, in
}
}
+static int coverage_from_count(int count)
+{
+ if (count < 8)
+ return TRACKING_COVERAGE_BAD;
+ else if (count < 16)
+ return TRACKING_COVERAGE_ACCEPTABLE;
+ return TRACKING_COVERAGE_OK;
+}
+
+static void tracking_dopesheet_calc_coverage(MovieTracking *tracking)
+{
+ MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
+ MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
+ ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
+ MovieTrackingTrack *track;
+ int frames, start_frame = INT_MAX, end_frame = -INT_MAX;
+ int *per_frame_counter;
+ int prev_coverage, last_segment_frame;
+ int i;
+
+ /* find frame boundaries */
+ for (track = tracksbase->first; track; track = track->next) {
+ start_frame = min_ii(start_frame, track->markers[0].framenr);
+ end_frame = max_ii(end_frame, track->markers[track->markersnr - 1].framenr);
+ }
+
+ frames = end_frame - start_frame + 1;
+
+ /* this is a per-frame counter of markers (how many markers belongs to the same frame) */
+ per_frame_counter = MEM_callocN(sizeof(int) * frames, "per frame track counter");
+
+ /* find per-frame markers count */
+ for (track = tracksbase->first; track; track = track->next) {
+ int i;
+
+ for (i = 0; i < track->markersnr; i++) {
+ MovieTrackingMarker *marker = &track->markers[i];
+
+ /* TODO: perhaps we need to add check for non-single-frame track here */
+ if ((marker->flag & MARKER_DISABLED) == 0)
+ per_frame_counter[marker->framenr - start_frame]++;
+ }
+ }
+
+ /* convert markers count to coverage and detect segments with the same coverage */
+ prev_coverage = coverage_from_count(per_frame_counter[0]);
+ last_segment_frame = start_frame;
+
+ /* means only disabled tracks in the beginning, could be ignored */
+ if (!per_frame_counter[0])
+ prev_coverage = TRACKING_COVERAGE_OK;
+
+ for (i = 1; i < frames; i++) {
+ int coverage = coverage_from_count(per_frame_counter[i]);
+
+ /* means only disabled tracks in the end, could be ignored */
+ if (i == frames - 1 && !per_frame_counter[i])
+ coverage = TRACKING_COVERAGE_OK;
+
+ if (coverage != prev_coverage || i == frames - 1) {
+ MovieTrackingDopesheetCoverageSegment *coverage_segment;
+ int end_segment_frame = i - 1 + start_frame;
+
+ if (end_segment_frame == last_segment_frame)
+ end_segment_frame++;
+
+ coverage_segment = MEM_callocN(sizeof(MovieTrackingDopesheetCoverageSegment), "tracking coverage segment");
+ coverage_segment->coverage = prev_coverage;
+ coverage_segment->start_frame = last_segment_frame;
+ coverage_segment->end_frame = end_segment_frame;
+
+ BLI_addtail(&dopesheet->coverage_segments, coverage_segment);
+
+ last_segment_frame = end_segment_frame;
+ }
+
+ prev_coverage = coverage;
+ }
+
+ MEM_freeN(per_frame_counter);
+}
+
void BKE_tracking_dopesheet_tag_update(MovieTracking *tracking)
{
MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
@@ -3749,6 +3984,7 @@ void BKE_tracking_dopesheet_update(MovieTracking *tracking)
reconstruction = BKE_tracking_object_get_reconstruction(tracking, object);
+ /* channels */
for (track = tracksbase->first; track; track = track->next) {
MovieTrackingDopesheetChannel *channel;
@@ -3776,5 +4012,8 @@ void BKE_tracking_dopesheet_update(MovieTracking *tracking)
tracking_dopesheet_sort(tracking, sort_method, inverse);
+ /* frame coverage */
+ tracking_dopesheet_calc_coverage(tracking);
+
dopesheet->ok = TRUE;
}