2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2011 Blender Foundation.
19 * All rights reserved.
21 * Contributor(s): Blender Foundation,
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/blenkernel/intern/tracking.c
37 #include "MEM_guardedalloc.h"
39 #include "DNA_gpencil_types.h"
40 #include "DNA_camera_types.h"
41 #include "DNA_movieclip_types.h"
42 #include "DNA_object_types.h" /* SELECT */
43 #include "DNA_scene_types.h"
45 #include "BLI_utildefines.h"
47 #include "BLI_math_base.h"
48 #include "BLI_listbase.h"
49 #include "BLI_ghash.h"
50 #include "BLI_path_util.h"
51 #include "BLI_string.h"
52 #include "BLI_threads.h"
54 #include "BKE_global.h"
55 #include "BKE_tracking.h"
56 #include "BKE_movieclip.h"
57 #include "BKE_object.h"
58 #include "BKE_scene.h"
60 #include "IMB_imbuf_types.h"
61 #include "IMB_imbuf.h"
66 # include "libmv-capi.h"
68 struct libmv_Features;
71 typedef struct MovieDistortion {
72 struct libmv_CameraIntrinsics *intrinsics;
79 /*********************** space transformation functions *************************/
81 /* Three coordinate frames: Frame, Search, and Marker
82 * Two units: Pixels, Unified
83 * Notation: {coordinate frame}_{unit}; for example, "search_pixel" are search
84 * window relative coordinates in pixels, and "frame_unified" are unified 0..1
85 * coordinates relative to the entire frame.
87 static void unified_to_pixel(int frame_width, int frame_height,
88 const float unified_coords[2], float pixel_coords[2])
90 pixel_coords[0] = unified_coords[0] * frame_width;
91 pixel_coords[1] = unified_coords[1] * frame_height;
94 static void marker_to_frame_unified(const MovieTrackingMarker *marker, const float marker_unified_coords[2],
95 float frame_unified_coords[2])
97 frame_unified_coords[0] = marker_unified_coords[0] + marker->pos[0];
98 frame_unified_coords[1] = marker_unified_coords[1] + marker->pos[1];
101 static void marker_unified_to_frame_pixel_coordinates(int frame_width, int frame_height,
102 const MovieTrackingMarker *marker,
103 const float marker_unified_coords[2], float frame_pixel_coords[2])
105 marker_to_frame_unified(marker, marker_unified_coords, frame_pixel_coords);
106 unified_to_pixel(frame_width, frame_height, frame_pixel_coords, frame_pixel_coords);
109 static void get_search_origin_frame_pixel(int frame_width, int frame_height,
110 const MovieTrackingMarker *marker, float frame_pixel[2])
112 /* Get the lower left coordinate of the search window and snap to pixel coordinates */
113 marker_unified_to_frame_pixel_coordinates(frame_width, frame_height, marker, marker->search_min, frame_pixel);
114 frame_pixel[0] = (int)frame_pixel[0];
115 frame_pixel[1] = (int)frame_pixel[1];
119 static void pixel_to_unified(int frame_width, int frame_height, const float pixel_coords[2], float unified_coords[2])
121 unified_coords[0] = pixel_coords[0] / frame_width;
122 unified_coords[1] = pixel_coords[1] / frame_height;
125 static void marker_unified_to_search_pixel(int frame_width, int frame_height,
126 const MovieTrackingMarker *marker,
127 const float marker_unified[2], float search_pixel[2])
129 float frame_pixel[2];
130 float search_origin_frame_pixel[2];
132 marker_unified_to_frame_pixel_coordinates(frame_width, frame_height, marker, marker_unified, frame_pixel);
133 get_search_origin_frame_pixel(frame_width, frame_height, marker, search_origin_frame_pixel);
134 sub_v2_v2v2(search_pixel, frame_pixel, search_origin_frame_pixel);
137 static void search_pixel_to_marker_unified(int frame_width, int frame_height,
138 const MovieTrackingMarker *marker,
139 const float search_pixel[2], float marker_unified[2])
141 float frame_unified[2];
142 float search_origin_frame_pixel[2];
144 get_search_origin_frame_pixel(frame_width, frame_height, marker, search_origin_frame_pixel);
145 add_v2_v2v2(frame_unified, search_pixel, search_origin_frame_pixel);
146 pixel_to_unified(frame_width, frame_height, frame_unified, frame_unified);
148 /* marker pos is in frame unified */
149 sub_v2_v2v2(marker_unified, frame_unified, marker->pos);
152 /* Each marker has 5 coordinates associated with it that get warped with
153 * tracking: the four corners ("pattern_corners"), and the cernter ("pos").
154 * This function puts those 5 points into the appropriate frame for tracking
155 * (the "search" coordinate frame).
157 static void get_marker_coords_for_tracking(int frame_width, int frame_height,
158 const MovieTrackingMarker *marker,
159 double search_pixel_x[5], double search_pixel_y[5])
162 float unified_coords[2];
163 float pixel_coords[2];
165 /* Convert the corners into search space coordinates. */
166 for (i = 0; i < 4; i++) {
167 marker_unified_to_search_pixel(frame_width, frame_height, marker, marker->pattern_corners[i], pixel_coords);
168 search_pixel_x[i] = pixel_coords[0];
169 search_pixel_y[i] = pixel_coords[1];
171 /* Convert the center position (aka "pos"); this is the origin */
172 unified_coords[0] = 0.0;
173 unified_coords[1] = 0.0;
174 marker_unified_to_search_pixel(frame_width, frame_height, marker, unified_coords, pixel_coords);
176 search_pixel_x[4] = pixel_coords[0];
177 search_pixel_y[4] = pixel_coords[1];
180 /* Inverse of above. */
181 static void set_marker_coords_from_tracking(int frame_width, int frame_height, MovieTrackingMarker *marker,
182 const double search_pixel_x[5], const double search_pixel_y[5])
185 float marker_unified[2];
186 float search_pixel[2];
188 /* Convert the corners into search space coordinates. */
189 for (i = 0; i < 4; i++) {
190 search_pixel[0] = search_pixel_x[i];
191 search_pixel[1] = search_pixel_y[i];
192 search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker->pattern_corners[i]);
195 /* Convert the center position (aka "pos"); this is the origin */
196 search_pixel[0] = search_pixel_x[4];
197 search_pixel[1] = search_pixel_y[4];
198 search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker_unified);
200 /* If the tracker tracked nothing, then "marker_unified" would be zero.
201 * Otherwise, the entire patch shifted, and that delta should be applied to
202 * all the coordinates.
204 for (i = 0; i < 4; i++) {
205 marker->pattern_corners[i][0] -= marker_unified[0];
206 marker->pattern_corners[i][1] -= marker_unified[1];
209 marker->pos[0] += marker_unified[0];
210 marker->pos[1] += marker_unified[1];
214 /*********************** common functions *************************/
216 void BKE_tracking_init_settings(MovieTracking *tracking)
218 tracking->camera.sensor_width = 35.0f;
219 tracking->camera.pixel_aspect = 1.0f;
220 tracking->camera.units = CAMERA_UNITS_MM;
222 tracking->settings.default_motion_model = TRACK_MOTION_MODEL_TRANSLATION;
223 tracking->settings.default_minimum_correlation = 0.75;
224 tracking->settings.default_pattern_size = 11;
225 tracking->settings.default_search_size = 61;
226 tracking->settings.keyframe1 = 1;
227 tracking->settings.keyframe2 = 30;
228 tracking->settings.dist = 1;
229 tracking->settings.object_distance = 1;
231 tracking->stabilization.scaleinf = 1.0f;
232 tracking->stabilization.locinf = 1.0f;
233 tracking->stabilization.rotinf = 1.0f;
234 tracking->stabilization.maxscale = 2.0f;
236 BKE_tracking_new_object(tracking, "Camera");
239 void BKE_tracking_clamp_marker(MovieTrackingMarker *marker, int event)
242 float pat_min[2], pat_max[2];
244 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
246 if (event == CLAMP_PAT_DIM) {
247 for (a = 0; a < 2; a++) {
248 /* search shouldn't be resized smaller than pattern */
249 marker->search_min[a] = MIN2(pat_min[a], marker->search_min[a]);
250 marker->search_max[a] = MAX2(pat_max[a], marker->search_max[a]);
253 else if (event == CLAMP_PAT_POS) {
256 sub_v2_v2v2(dim, pat_max, pat_min);
258 for (a = 0; a < 2; a++) {
260 /* pattern shouldn't be moved outside of search */
261 if (pat_min[a] < marker->search_min[a]) {
262 for (b = 0; b < 4; b++)
263 marker->pattern_corners[b][a] += marker->search_min[a] - pat_min[a];
265 if (pat_max[a] > marker->search_max[a]) {
266 for (b = 0; b < 4; b++)
267 marker->pattern_corners[b][a] -= pat_max[a] - marker->search_max[a];
271 else if (event == CLAMP_SEARCH_DIM) {
272 for (a = 0; a < 2; a++) {
273 /* search shouldn't be resized smaller than pattern */
274 marker->search_min[a] = MIN2(pat_min[a], marker->search_min[a]);
275 marker->search_max[a] = MAX2(pat_max[a], marker->search_max[a]);
278 else if (event == CLAMP_SEARCH_POS) {
281 sub_v2_v2v2(dim, marker->search_max, marker->search_min);
283 for (a = 0; a < 2; a++) {
284 /* search shouldn't be moved inside pattern */
285 if (marker->search_min[a] > pat_min[a]) {
286 marker->search_min[a] = pat_min[a];
287 marker->search_max[a] = marker->search_min[a] + dim[a];
289 if (marker->search_max[a] < pat_max[a]) {
290 marker->search_max[a] = pat_max[a];
291 marker->search_min[a] = marker->search_max[a] - dim[a];
295 else if (event == CLAMP_SEARCH_DIM) {
297 sub_v2_v2v2(dim, pat_max, pat_min);
298 for (a = 0; a < 2; a++) {
299 marker->search_min[a] = pat_min[a];
300 marker->search_max[a] = pat_max[a];
305 void BKE_tracking_track_flag(MovieTrackingTrack *track, int area, int flag, int clear)
307 if (area == TRACK_AREA_NONE)
311 if (area & TRACK_AREA_POINT)
312 track->flag &= ~flag;
313 if (area & TRACK_AREA_PAT)
314 track->pat_flag &= ~flag;
315 if (area & TRACK_AREA_SEARCH)
316 track->search_flag &= ~flag;
319 if (area & TRACK_AREA_POINT)
321 if (area & TRACK_AREA_PAT)
322 track->pat_flag |= flag;
323 if (area & TRACK_AREA_SEARCH)
324 track->search_flag |= flag;
328 MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tracksbase, float x, float y,
329 int framenr, int width, int height)
331 MovieTrackingTrack *track;
332 MovieTrackingMarker marker;
333 MovieTrackingSettings *settings = &tracking->settings;
335 float half_pattern = (float)settings->default_pattern_size / 2.0f;
336 float half_search = (float)settings->default_search_size / 2.0f;
337 float pat[2], search[2];
339 pat[0] = half_pattern / (float)width;
340 pat[1] = half_pattern / (float)height;
342 search[0] = half_search / (float)width;
343 search[1] = half_search / (float)height;
345 track = MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track");
346 strcpy(track->name, "Track");
348 track->motion_model = settings->default_motion_model;
349 track->minimum_correlation = settings->default_minimum_correlation;
350 track->margin = settings->default_margin;
351 track->pattern_match = settings->default_pattern_match;
352 track->frames_limit = settings->default_frames_limit;
353 track->flag = settings->default_flag;
354 track->algorithm_flag = settings->default_algorithm_flag;
356 memset(&marker, 0, sizeof(marker));
359 marker.framenr = framenr;
361 marker.pattern_corners[0][0] = -pat[0];
362 marker.pattern_corners[0][1] = -pat[1];
364 marker.pattern_corners[1][0] = pat[0];
365 marker.pattern_corners[1][1] = -pat[1];
367 negate_v2_v2(marker.pattern_corners[2], marker.pattern_corners[0]);
368 negate_v2_v2(marker.pattern_corners[3], marker.pattern_corners[1]);
370 copy_v2_v2(marker.search_max, search);
371 negate_v2_v2(marker.search_min, search);
373 BKE_tracking_insert_marker(track, &marker);
375 BLI_addtail(tracksbase, track);
376 BKE_track_unique_name(tracksbase, track);
381 MovieTrackingMarker *BKE_tracking_insert_marker(MovieTrackingTrack *track, MovieTrackingMarker *marker)
383 MovieTrackingMarker *old_marker = NULL;
385 if (track->markersnr)
386 old_marker = BKE_tracking_exact_marker(track, marker->framenr);
389 *old_marker = *marker;
394 int a = track->markersnr;
397 if (track->markers[a].framenr < marker->framenr)
404 track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr);
406 track->markers = MEM_callocN(sizeof(MovieTrackingMarker), "MovieTracking markers");
408 memmove(track->markers + a + 2, track->markers + a + 1,
409 (track->markersnr - a - 2) * sizeof(MovieTrackingMarker));
410 track->markers[a + 1] = *marker;
412 track->last_marker = a + 1;
414 return &track->markers[a + 1];
418 void BKE_tracking_delete_marker(MovieTrackingTrack *track, int framenr)
422 while (a < track->markersnr) {
423 if (track->markers[a].framenr == framenr) {
424 if (track->markersnr > 1) {
425 memmove(track->markers + a, track->markers + a + 1,
426 (track->markersnr - a - 1) * sizeof(MovieTrackingMarker));
428 track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr);
431 MEM_freeN(track->markers);
432 track->markers = NULL;
433 track->markersnr = 0;
443 void BKE_tracking_marker_pattern_minmax(const MovieTrackingMarker *marker, float min[2], float max[2])
445 INIT_MINMAX2(min, max);
447 DO_MINMAX2(marker->pattern_corners[0], min, max);
448 DO_MINMAX2(marker->pattern_corners[1], min, max);
449 DO_MINMAX2(marker->pattern_corners[2], min, max);
450 DO_MINMAX2(marker->pattern_corners[3], min, max);
453 MovieTrackingMarker *BKE_tracking_get_marker(MovieTrackingTrack *track, int framenr)
455 int a = track->markersnr - 1;
457 if (!track->markersnr)
460 /* approximate pre-first framenr marker with first marker */
461 if (framenr < track->markers[0].framenr)
462 return &track->markers[0];
464 if (track->last_marker < track->markersnr)
465 a = track->last_marker;
467 if (track->markers[a].framenr <= framenr) {
468 while (a < track->markersnr && track->markers[a].framenr <= framenr) {
469 if (track->markers[a].framenr == framenr) {
470 track->last_marker = a;
472 return &track->markers[a];
477 /* if there's no marker for exact position, use nearest marker from left side */
478 return &track->markers[a - 1];
481 while (a >= 0 && track->markers[a].framenr >= framenr) {
482 if (track->markers[a].framenr == framenr) {
483 track->last_marker = a;
485 return &track->markers[a];
491 /* if there's no marker for exact position, use nearest marker from left side */
492 return &track->markers[a];
498 MovieTrackingMarker *BKE_tracking_ensure_marker(MovieTrackingTrack *track, int framenr)
500 MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr);
502 if (marker->framenr != framenr) {
503 MovieTrackingMarker marker_new;
505 marker_new = *marker;
506 marker_new.framenr = framenr;
508 BKE_tracking_insert_marker(track, &marker_new);
509 marker = BKE_tracking_get_marker(track, framenr);
515 MovieTrackingMarker *BKE_tracking_exact_marker(MovieTrackingTrack *track, int framenr)
517 MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr);
519 if (marker->framenr != framenr)
525 int BKE_tracking_has_marker(MovieTrackingTrack *track, int framenr)
527 return BKE_tracking_exact_marker(track, framenr) != 0;
530 int BKE_tracking_has_enabled_marker(MovieTrackingTrack *track, int framenr)
532 MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, framenr);
534 return marker && (marker->flag & MARKER_DISABLED) == 0;
537 void BKE_tracking_free_track(MovieTrackingTrack *track)
540 MEM_freeN(track->markers);
543 static void put_disabled_marker(MovieTrackingTrack *track, MovieTrackingMarker *ref_marker, int before, int overwrite)
545 MovieTrackingMarker marker_new;
547 marker_new = *ref_marker;
548 marker_new.flag &= ~MARKER_TRACKED;
549 marker_new.flag |= MARKER_DISABLED;
552 marker_new.framenr--;
554 marker_new.framenr++;
556 if (!BKE_tracking_has_marker(track, marker_new.framenr) || overwrite)
557 BKE_tracking_insert_marker(track, &marker_new);
560 void BKE_tracking_clear_path(MovieTrackingTrack *track, int ref_frame, int action)
564 if (action == TRACK_CLEAR_REMAINED) {
567 while (a < track->markersnr) {
568 if (track->markers[a].framenr > ref_frame) {
569 track->markersnr = a;
570 track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr);
578 if (track->markersnr)
579 put_disabled_marker(track, &track->markers[track->markersnr - 1], 0, 1);
581 else if (action == TRACK_CLEAR_UPTO) {
582 a = track->markersnr - 1;
585 if (track->markers[a].framenr <= ref_frame) {
586 memmove(track->markers, track->markers + a, (track->markersnr - a) * sizeof(MovieTrackingMarker));
588 track->markersnr = track->markersnr - a;
589 track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr);
597 if (track->markersnr)
598 put_disabled_marker(track, &track->markers[0], 1, 1);
600 else if (action == TRACK_CLEAR_ALL) {
601 MovieTrackingMarker *marker, marker_new;
603 marker = BKE_tracking_get_marker(track, ref_frame);
604 marker_new = *marker;
606 MEM_freeN(track->markers);
607 track->markers = NULL;
608 track->markersnr = 0;
610 BKE_tracking_insert_marker(track, &marker_new);
612 put_disabled_marker(track, &marker_new, 1, 1);
613 put_disabled_marker(track, &marker_new, 0, 1);
617 void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
619 int i = 0, a = 0, b = 0, tot;
620 MovieTrackingMarker *markers;
622 tot = dst_track->markersnr + src_track->markersnr;
623 markers = MEM_callocN(tot * sizeof(MovieTrackingMarker), "tmp tracking joined tracks");
625 while (a < src_track->markersnr || b < dst_track->markersnr) {
626 if (b >= dst_track->markersnr) {
627 markers[i] = src_track->markers[a++];
629 else if (a >= src_track->markersnr) {
630 markers[i] = dst_track->markers[b++];
632 else if (src_track->markers[a].framenr < dst_track->markers[b].framenr) {
633 markers[i] = src_track->markers[a++];
635 else if (src_track->markers[a].framenr > dst_track->markers[b].framenr) {
636 markers[i] = dst_track->markers[b++];
639 if ((src_track->markers[a].flag & MARKER_DISABLED) == 0) {
640 if ((dst_track->markers[b].flag & MARKER_DISABLED) == 0) {
641 /* both tracks are enabled on this frame, so find the whole segment
642 * on which tracks are intersecting and blend tracks using linear
643 * interpolation to prevent jumps
646 MovieTrackingMarker *marker_a, *marker_b;
647 int start_a = a, start_b = b, len = 0, frame = src_track->markers[a].framenr;
650 inverse = (b == 0) ||
651 (dst_track->markers[b - 1].flag & MARKER_DISABLED) ||
652 (dst_track->markers[b - 1].framenr != frame - 1);
654 /* find length of intersection */
655 while (a < src_track->markersnr && b < dst_track->markersnr) {
656 marker_a = &src_track->markers[a];
657 marker_b = &dst_track->markers[b];
659 if (marker_a->flag & MARKER_DISABLED || marker_b->flag & MARKER_DISABLED)
662 if (marker_a->framenr != frame || marker_b->framenr != frame)
674 /* linear interpolation for intersecting frames */
675 for (j = 0; j < len; j++) {
679 fac = 1.0f / (len - 1) * j;
684 marker_a = &src_track->markers[a];
685 marker_b = &dst_track->markers[b];
687 markers[i] = dst_track->markers[b];
688 interp_v2_v2v2(markers[i].pos, marker_b->pos, marker_a->pos, fac);
694 /* this values will be incremented at the end of the loop cycle */
697 else markers[i] = src_track->markers[a];
699 else markers[i] = dst_track->markers[b];
708 MEM_freeN(dst_track->markers);
710 dst_track->markers = MEM_callocN(i * sizeof(MovieTrackingMarker), "tracking joined tracks");
711 memcpy(dst_track->markers, markers, i * sizeof(MovieTrackingMarker));
713 dst_track->markersnr = i;
718 static void tracking_tracks_free(ListBase *tracks)
720 MovieTrackingTrack *track;
722 for (track = tracks->first; track; track = track->next) {
723 BKE_tracking_free_track(track);
726 BLI_freelistN(tracks);
729 static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruction)
731 if (reconstruction->cameras)
732 MEM_freeN(reconstruction->cameras);
735 static void tracking_object_free(MovieTrackingObject *object)
737 tracking_tracks_free(&object->tracks);
738 tracking_reconstruction_free(&object->reconstruction);
741 static void tracking_objects_free(ListBase *objects)
743 MovieTrackingObject *object;
745 for (object = objects->first; object; object = object->next)
746 tracking_object_free(object);
748 BLI_freelistN(objects);
751 static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet)
753 MovieTrackingDopesheetChannel *channel;
755 channel = dopesheet->channels.first;
757 if (channel->segments) {
758 MEM_freeN(channel->segments);
761 channel = channel->next;
764 BLI_freelistN(&dopesheet->channels);
766 dopesheet->channels.first = dopesheet->channels.last = NULL;
767 dopesheet->tot_channel = 0;
770 void BKE_tracking_free(MovieTracking *tracking)
772 tracking_tracks_free(&tracking->tracks);
773 tracking_reconstruction_free(&tracking->reconstruction);
774 tracking_objects_free(&tracking->objects);
776 if (tracking->stabilization.scaleibuf)
777 IMB_freeImBuf(tracking->stabilization.scaleibuf);
779 if (tracking->camera.intrinsics)
780 BKE_tracking_distortion_destroy(tracking->camera.intrinsics);
782 tracking_dopesheet_free(&tracking->dopesheet);
785 static MovieTrackingTrack *duplicate_track(MovieTrackingTrack *track)
787 MovieTrackingTrack *new_track;
789 new_track = MEM_callocN(sizeof(MovieTrackingTrack), "tracksMapMerge new_track");
792 new_track->next = new_track->prev = NULL;
794 new_track->markers = MEM_dupallocN(new_track->markers);
799 /*********************** clipboard *************************/
801 void BKE_tracking_free_clipboard(void)
803 MovieTrackingTrack *track = tracking_clipboard.tracks.first, *next_track;
806 next_track = track->next;
808 BKE_tracking_free_track(track);
815 void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingObject *object)
817 ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object);
818 MovieTrackingTrack *track = tracksbase->first;
820 BKE_tracking_free_clipboard();
823 if (TRACK_SELECTED(track) && (track->flag & TRACK_HIDDEN) == 0) {
824 MovieTrackingTrack *new_track = duplicate_track(track);
826 BLI_addtail(&tracking_clipboard.tracks, new_track);
833 int BKE_tracking_clipboard_has_tracks(void)
835 return tracking_clipboard.tracks.first != NULL;
838 void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingObject *object)
840 ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object);
841 MovieTrackingTrack *track = tracking_clipboard.tracks.first;
844 MovieTrackingTrack *new_track = duplicate_track(track);
846 BLI_addtail(tracksbase, new_track);
847 BKE_track_unique_name(tracksbase, new_track);
853 /*********************** tracks map *************************/
855 typedef struct TracksMap {
856 char object_name[MAX_NAME];
863 MovieTrackingTrack *tracks;
870 static TracksMap *tracks_map_new(const char *object_name, int is_camera, int num_tracks, int customdata_size)
872 TracksMap *map = MEM_callocN(sizeof(TracksMap), "TrackingsMap");
874 BLI_strncpy(map->object_name, object_name, sizeof(map->object_name));
875 map->is_camera = is_camera;
877 map->num_tracks = num_tracks;
878 map->customdata_size = customdata_size;
880 map->tracks = MEM_callocN(sizeof(MovieTrackingTrack) * num_tracks, "TrackingsMap tracks");
883 map->customdata = MEM_callocN(customdata_size * num_tracks, "TracksMap customdata");
885 map->hash = BLI_ghash_ptr_new("TracksMap hash");
890 static int tracks_map_size(TracksMap *map)
892 return map->num_tracks;
895 static void tracks_map_get(TracksMap *map, int index, MovieTrackingTrack **track, void **customdata)
897 *track = &map->tracks[index];
900 *customdata = &map->customdata[index * map->customdata_size];
903 static void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *customdata)
905 MovieTrackingTrack new_track = *track;
907 new_track.markers = MEM_dupallocN(new_track.markers);
909 map->tracks[map->ptr] = new_track;
912 memcpy(&map->customdata[map->ptr * map->customdata_size], customdata, map->customdata_size);
914 BLI_ghash_insert(map->hash, &map->tracks[map->ptr], track);
919 static void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
921 MovieTrackingTrack *track;
922 MovieTrackingTrack *act_track = BKE_tracking_active_track(tracking);
923 MovieTrackingTrack *rot_track = tracking->stabilization.rot_track;
924 ListBase tracks = {NULL, NULL}, new_tracks = {NULL, NULL};
925 ListBase *old_tracks;
928 if (map->is_camera) {
929 old_tracks = &tracking->tracks;
932 MovieTrackingObject *object = BKE_tracking_named_object(tracking, map->object_name);
935 /* object was deleted by user, create new one */
936 object = BKE_tracking_new_object(tracking, map->object_name);
939 old_tracks = &object->tracks;
942 /* duplicate currently operating tracks to temporary list.
943 * this is needed to keep names in unique state and it's faster to change names
944 * of currently operating tracks (if needed)
946 for (a = 0; a < map->num_tracks; a++) {
947 int replace_sel = 0, replace_rot = 0;
948 MovieTrackingTrack *new_track, *old;
950 track = &map->tracks[a];
952 /* find original of operating track in list of previously displayed tracks */
953 old = BLI_ghash_lookup(map->hash, track);
955 MovieTrackingTrack *cur = old_tracks->first;
964 /* original track was found, re-use flags and remove this track */
966 if (cur == act_track)
968 if (cur == rot_track)
971 track->flag = cur->flag;
972 track->pat_flag = cur->pat_flag;
973 track->search_flag = cur->search_flag;
975 BKE_tracking_free_track(cur);
976 BLI_freelinkN(old_tracks, cur);
980 new_track = duplicate_track(track);
982 BLI_ghash_remove(map->hash, track, NULL, NULL); /* XXX: are we actually need this */
983 BLI_ghash_insert(map->hash, track, new_track);
985 if (replace_sel) /* update current selection in clip */
986 tracking->act_track = new_track;
988 if (replace_rot) /* update track used for rotation stabilization */
989 tracking->stabilization.rot_track = new_track;
991 BLI_addtail(&tracks, new_track);
994 /* move all tracks, which aren't operating */
995 track = old_tracks->first;
997 MovieTrackingTrack *next = track->next;
999 track->next = track->prev = NULL;
1000 BLI_addtail(&new_tracks, track);
1005 /* now move all tracks which are currently operating and keep their names unique */
1006 track = tracks.first;
1008 MovieTrackingTrack *next = track->next;
1010 BLI_remlink(&tracks, track);
1012 track->next = track->prev = NULL;
1013 BLI_addtail(&new_tracks, track);
1015 BLI_uniquename(&new_tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
1020 *old_tracks = new_tracks;
1023 static void tracks_map_free(TracksMap *map, void (*customdata_free)(void *customdata))
1027 BLI_ghash_free(map->hash, NULL, NULL);
1029 for (i = 0; i < map->num_tracks; i++) {
1030 if (map->customdata && customdata_free)
1031 customdata_free(&map->customdata[i * map->customdata_size]);
1033 BKE_tracking_free_track(&map->tracks[i]);
1036 if (map->customdata)
1037 MEM_freeN(map->customdata);
1039 MEM_freeN(map->tracks);
1043 /*********************** tracking *************************/
1045 typedef struct TrackContext {
1047 /* the reference marker and cutout search area */
1048 MovieTrackingMarker marker;
1050 /* keyframed patch. This is the search area */
1052 int search_area_height;
1053 int search_area_width;
1062 typedef struct MovieTrackingContext {
1067 int first_time, frames;
1069 MovieTrackingSettings settings;
1070 TracksMap *tracks_map;
1072 short backwards, sequence;
1074 } MovieTrackingContext;
1076 MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, short backwards, short sequence)
1078 MovieTrackingContext *context = MEM_callocN(sizeof(MovieTrackingContext), "trackingContext");
1079 MovieTracking *tracking = &clip->tracking;
1080 MovieTrackingSettings *settings = &tracking->settings;
1081 ListBase *tracksbase = BKE_tracking_get_tracks(tracking);
1082 MovieTrackingTrack *track;
1083 MovieTrackingObject *object = BKE_tracking_active_object(tracking);
1086 context->settings = *settings;
1087 context->backwards = backwards;
1088 context->sync_frame = user->framenr;
1089 context->first_time = TRUE;
1090 context->sequence = sequence;
1093 track = tracksbase->first;
1095 if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) {
1096 int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
1097 MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr);
1099 if ((marker->flag & MARKER_DISABLED) == 0)
1103 track = track->next;
1109 context->tracks_map = tracks_map_new(object->name, object->flag & TRACKING_OBJECT_CAMERA,
1110 num_tracks, sizeof(TrackContext));
1112 BKE_movieclip_get_size(clip, user, &width, &height);
1114 /* create tracking data */
1115 track = tracksbase->first;
1117 if (TRACK_SELECTED(track) && (track->flag & (TRACK_HIDDEN | TRACK_LOCKED)) == 0) {
1118 int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
1119 MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr);
1121 if ((marker->flag & MARKER_DISABLED) == 0) {
1122 TrackContext track_context;
1123 memset(&track_context, 0, sizeof(TrackContext));
1124 tracks_map_insert(context->tracks_map, track, &track_context);
1128 track = track->next;
1132 context->clip = clip;
1134 /* store needed clip flags passing to get_buffer functions
1135 * - MCLIP_USE_PROXY is needed to because timecode affects on movie clip
1136 * only in case Proxy/Timecode flag is set, so store this flag to use
1137 * timecodes properly but reset render size to SIZE_FULL so correct resolution
1138 * would be used for images
1139 * - MCLIP_USE_PROXY_CUSTOM_DIR is needed because proxy/timecode files might
1140 * be stored in a different location
1141 * ignore all the rest possible flags for now
1143 context->clip_flag = clip->flag & MCLIP_TIMECODE_FLAGS;
1145 context->user = *user;
1146 context->user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
1147 context->user.render_flag = 0;
1150 BLI_begin_threaded_malloc();
1155 static void track_context_free(void *customdata)
1157 TrackContext *track_context = (TrackContext *)customdata;
1160 if (track_context->search_area)
1161 MEM_freeN(track_context->search_area);
1163 if (track_context->mask)
1164 MEM_freeN(track_context->mask);
1167 (void)track_context;
1171 void BKE_tracking_context_free(MovieTrackingContext *context)
1173 if (!context->sequence)
1174 BLI_end_threaded_malloc();
1176 tracks_map_free(context->tracks_map, track_context_free);
1181 /* zap channels from the imbuf that are disabled by the user. this can lead to
1182 * better tracks sometimes. however, instead of simply zeroing the channels
1183 * out, do a partial grayscale conversion so the display is better.
1185 void BKE_tracking_disable_imbuf_channels(ImBuf *ibuf, int disable_red, int disable_green, int disable_blue,
1191 if (!disable_red && !disable_green && !disable_blue && !grayscale)
1194 /* If only some components are selected, it's important to rescale the result
1195 * appropriately so that e.g. if only blue is selected, it's not zeroed out.
1197 scale = (disable_red ? 0.0f : 0.2126f) +
1198 (disable_green ? 0.0f : 0.7152f) +
1199 (disable_blue ? 0.0f : 0.0722f);
1201 for (y = 0; y < ibuf->y; y++) {
1202 for (x = 0; x < ibuf->x; x++) {
1203 int pixel = ibuf->x * y + x;
1205 if (ibuf->rect_float) {
1206 float *rrgbf = ibuf->rect_float + pixel * 4;
1207 float r = disable_red ? 0.0f : rrgbf[0];
1208 float g = disable_green ? 0.0f : rrgbf[1];
1209 float b = disable_blue ? 0.0f : rrgbf[2];
1212 float gray = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale;
1214 rrgbf[0] = rrgbf[1] = rrgbf[2] = gray;
1223 char *rrgb = (char *)ibuf->rect + pixel * 4;
1224 char r = disable_red ? 0 : rrgb[0];
1225 char g = disable_green ? 0 : rrgb[1];
1226 char b = disable_blue ? 0 : rrgb[2];
1229 float gray = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale;
1231 rrgb[0] = rrgb[1] = rrgb[2] = gray;
1242 if (ibuf->rect_float)
1243 ibuf->userflags |= IB_RECT_INVALID;
1246 static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale)
1248 BKE_tracking_disable_imbuf_channels(ibuf, track->flag & TRACK_DISABLE_RED,
1249 track->flag & TRACK_DISABLE_GREEN, track->flag & TRACK_DISABLE_BLUE, grayscale);
1252 ImBuf *BKE_tracking_sample_pattern_imbuf(int frame_width, int frame_height, ImBuf *search_ibuf,
1253 MovieTrackingTrack *track, MovieTrackingMarker *marker,
1254 int use_mask, int num_samples_x, int num_samples_y,
1258 ImBuf *pattern_ibuf;
1259 double src_pixel_x[5], src_pixel_y[5];
1260 double warped_position_x, warped_position_y;
1263 pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat);
1264 pattern_ibuf->profile = IB_PROFILE_LINEAR_RGB;
1266 if (!search_ibuf->rect_float) {
1267 IMB_float_from_rect(search_ibuf);
1270 get_marker_coords_for_tracking(frame_width, frame_height, marker, src_pixel_x, src_pixel_y);
1273 mask = BKE_tracking_track_mask_get(frame_width, frame_height, track, marker);
1276 libmv_samplePlanarPatch(search_ibuf->rect_float, search_ibuf->x, search_ibuf->y, 4,
1277 src_pixel_x, src_pixel_y, num_samples_x,
1278 num_samples_y, mask, pattern_ibuf->rect_float,
1279 &warped_position_x, &warped_position_y);
1282 pos[0] = warped_position_x;
1283 pos[1] = warped_position_y;
1290 return pattern_ibuf;
1292 ImBuf *pattern_ibuf;
1294 /* real sampling requires libmv, but areas are supposing pattern would be
1295 * sampled if search area does exists, so we'll need to create empty
1296 * pattern area here to prevent adding NULL-checks all over just to deal
1297 * with situation when lubmv is disabled
1301 (void) frame_height;
1307 pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat);
1309 pos[0] = num_samples_x / 2.0f;
1310 pos[1] = num_samples_y / 2.0f;
1312 return pattern_ibuf;
1316 ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1317 int anchored, int disable_channels)
1319 ImBuf *pattern_ibuf, *search_ibuf;
1320 float pat_min[2], pat_max[2];
1321 int num_samples_x, num_samples_y;
1323 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
1325 num_samples_x = (pat_max[0] - pat_min[0]) * ibuf->x;
1326 num_samples_y = (pat_max[1] - pat_min[1]) * ibuf->y;
1328 search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, anchored, disable_channels);
1330 pattern_ibuf = BKE_tracking_sample_pattern_imbuf(ibuf->x, ibuf->y, search_ibuf, track, marker,
1331 FALSE, num_samples_x, num_samples_y, NULL);
1333 IMB_freeImBuf(search_ibuf);
1335 return pattern_ibuf;
1338 ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1339 int anchored, int disable_channels)
1343 float search_origin[2];
1345 get_search_origin_frame_pixel(ibuf->x, ibuf->y, marker, search_origin);
1347 x = search_origin[0];
1348 y = search_origin[1];
1351 x += track->offset[0] * ibuf->x;
1352 y += track->offset[1] * ibuf->y;
1355 w = (marker->search_max[0] - marker->search_min[0]) * ibuf->x;
1356 h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y;
1358 searchibuf = IMB_allocImBuf(w, h, 32, ibuf->rect_float ? IB_rectfloat : IB_rect);
1359 searchibuf->profile = ibuf->profile;
1361 IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h);
1363 if (disable_channels) {
1364 if ((track->flag & TRACK_PREVIEW_GRAYSCALE) ||
1365 (track->flag & TRACK_DISABLE_RED) ||
1366 (track->flag & TRACK_DISABLE_GREEN) ||
1367 (track->flag & TRACK_DISABLE_BLUE))
1369 disable_imbuf_channels(searchibuf, track, TRUE);
1376 static bGPDlayer *track_mask_gpencil_layer_get(MovieTrackingTrack *track)
1383 layer = track->gpd->layers.first;
1386 if (layer->flag & GP_LAYER_ACTIVE) {
1387 bGPDframe *frame = layer->frames.first;
1391 if (frame->strokes.first) {
1395 frame = frame->next;
1402 layer = layer->next;
1408 static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height,
1409 MovieTrackingMarker *marker, bGPDlayer *layer,
1410 float *mask, int mask_width, int mask_height)
1412 bGPDframe *frame = layer->frames.first;
1415 bGPDstroke *stroke = frame->strokes.first;
1418 bGPDspoint *stroke_points = stroke->points;
1419 float *mask_points, *fp;
1422 if (stroke->flag & GP_STROKE_2DSPACE) {
1423 fp = mask_points = MEM_callocN(2 * stroke->totpoints * sizeof(float),
1424 "track mask rasterization points");
1426 for (i = 0; i < stroke->totpoints; i++, fp += 2) {
1427 fp[0] = (stroke_points[i].x - marker->search_min[0]) * frame_width / mask_width;
1428 fp[1] = (stroke_points[i].y - marker->search_min[1]) * frame_height / mask_height;
1431 PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, mask_width, mask_height, FALSE /* XXX- TODO: make on/off for AA*/);
1433 MEM_freeN(mask_points);
1436 stroke = stroke->next;
1439 frame = frame->next;
1443 float *BKE_tracking_track_mask_get(int frame_width, int frame_height,
1444 MovieTrackingTrack *track, MovieTrackingMarker *marker)
1447 bGPDlayer *layer = track_mask_gpencil_layer_get(track);
1448 int mask_width, mask_height;
1450 mask_width = (marker->search_max[0] - marker->search_min[0]) * frame_width;
1451 mask_height = (marker->search_max[1] - marker->search_min[1]) * frame_height;
1454 mask = MEM_callocN(mask_width * mask_height * sizeof(float), "track mask");
1456 track_mask_gpencil_layer_rasterize(frame_width, frame_height, marker, layer,
1457 mask, mask_width, mask_height);
1465 /* Convert from float and byte RGBA to grayscale. Supports different coefficients for RGB. */
1466 static void float_rgba_to_gray(const float *rgba, float *gray, int num_pixels,
1467 float weight_red, float weight_green, float weight_blue)
1471 for (i = 0; i < num_pixels; i++) {
1472 const float *pixel = rgba + 4 * i;
1474 gray[i] = weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2];
1478 static void uint8_rgba_to_float_gray(const unsigned char *rgba, float *gray, int num_pixels,
1479 float weight_red, float weight_green, float weight_blue)
1483 for (i = 0; i < num_pixels; i++) {
1484 const unsigned char *pixel = rgba + i * 4;
1486 *gray++ = (weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]) / 255.0f;
1490 static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1491 int *width_r, int *height_r)
1497 searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, FALSE, TRUE);
1499 width = searchibuf->x;
1500 height = searchibuf->y;
1502 *width_r = searchibuf->x;
1503 *height_r = searchibuf->y;
1505 gray_pixels = MEM_callocN(width * height * sizeof(float), "tracking floatBuf");
1507 if (searchibuf->rect_float) {
1508 float_rgba_to_gray(searchibuf->rect_float, gray_pixels, width * height,
1509 0.2126f, 0.7152f, 0.0722f);
1512 uint8_rgba_to_float_gray((unsigned char *)searchibuf->rect, gray_pixels, width * height,
1513 0.2126f, 0.7152f, 0.0722f);
1516 IMB_freeImBuf(searchibuf);
1521 static unsigned char *get_ucharbuf(ImBuf *ibuf)
1524 unsigned char *pixels, *cp;
1526 cp = pixels = MEM_callocN(ibuf->x * ibuf->y * sizeof(unsigned char), "tracking ucharBuf");
1527 for (y = 0; y < ibuf->y; y++) {
1528 for (x = 0; x < ibuf->x; x++) {
1529 int pixel = ibuf->x * y + x;
1531 if (ibuf->rect_float) {
1532 const float *rrgbf = ibuf->rect_float + pixel * 4;
1533 const float grey_f = 0.2126f * rrgbf[0] + 0.7152f * rrgbf[1] + 0.0722f * rrgbf[2];
1535 *cp = FTOCHAR(grey_f);
1538 const unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4;
1540 *cp = 0.2126f * rrgb[0] + 0.7152f * rrgb[1] + 0.0722f * rrgb[2];
1550 static ImBuf *get_frame_ibuf(MovieTrackingContext *context, int framenr)
1553 MovieClipUser user = context->user;
1555 user.framenr = BKE_movieclip_remap_clip_to_scene_frame(context->clip, framenr);
1557 ibuf = BKE_movieclip_get_ibuf_flag(context->clip, &user, context->clip_flag, MOVIECLIP_CACHE_SKIP);
1562 static ImBuf *get_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track,
1563 MovieTrackingMarker *marker, MovieTrackingMarker **marker_keyed)
1565 int framenr = marker->framenr;
1566 int a = marker - track->markers;
1568 *marker_keyed = marker;
1570 while (a >= 0 && a < track->markersnr) {
1571 int next = (context->backwards) ? a + 1 : a - 1;
1572 int is_keyframed = FALSE;
1573 MovieTrackingMarker *cur_marker = &track->markers[a];
1574 MovieTrackingMarker *next_marker = NULL;
1576 if (next >= 0 && next < track->markersnr)
1577 next_marker = &track->markers[next];
1579 /* if next mrker is disabled, stop searching keyframe and use current frame as keyframe */
1580 if (next_marker && next_marker->flag & MARKER_DISABLED)
1581 is_keyframed = TRUE;
1583 is_keyframed |= (cur_marker->flag & MARKER_TRACKED) == 0;
1586 framenr = cur_marker->framenr;
1587 *marker_keyed = cur_marker;
1595 return get_frame_ibuf(context, framenr);
1598 static ImBuf *get_adjust_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1599 int curfra, MovieTrackingMarker **marker_keyed)
1603 if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
1604 ibuf = get_keyframed_ibuf(context, track, marker, marker_keyed);
1607 ibuf = get_frame_ibuf(context, curfra);
1609 /* use current marker as keyframed position */
1610 *marker_keyed = marker;
1616 static void marker_search_scale_after_tracking(const MovieTrackingMarker *old_marker, MovieTrackingMarker *new_marker)
1618 float old_pat_min[2], old_pat_max[2];
1619 float new_pat_min[2], new_pat_max[2];
1620 float scale_x, scale_y;
1622 BKE_tracking_marker_pattern_minmax(old_marker, old_pat_min, old_pat_max);
1623 BKE_tracking_marker_pattern_minmax(new_marker, new_pat_min, new_pat_max);
1625 scale_x = (new_pat_max[0] - new_pat_min[0]) / (old_pat_max[0] - old_pat_min[0]);
1626 scale_y = (new_pat_max[1] - new_pat_min[1]) / (old_pat_max[1] - old_pat_min[1]);
1628 new_marker->search_min[0] *= scale_x;
1629 new_marker->search_min[1] *= scale_y;
1631 new_marker->search_max[0] *= scale_x;
1632 new_marker->search_max[1] *= scale_y;
1637 void BKE_tracking_sync(MovieTrackingContext *context)
1639 MovieTracking *tracking = &context->clip->tracking;
1642 tracks_map_merge(context->tracks_map, tracking);
1644 if (context->backwards)
1645 newframe = context->user.framenr + 1;
1647 newframe = context->user.framenr - 1;
1649 context->sync_frame = newframe;
1651 tracking->dopesheet.ok = FALSE;
1654 void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context)
1656 user->framenr = context->sync_frame;
1659 int BKE_tracking_next(MovieTrackingContext *context)
1661 ImBuf *destination_ibuf;
1662 int curfra = BKE_movieclip_remap_scene_to_clip_frame(context->clip, context->user.framenr);
1663 int a, ok = FALSE, map_size;
1665 int frame_width, frame_height;
1667 map_size = tracks_map_size(context->tracks_map);
1669 /* nothing to track, avoid unneeded frames reading to save time and memory */
1673 if (context->backwards)
1674 context->user.framenr--;
1676 context->user.framenr++;
1678 destination_ibuf = BKE_movieclip_get_ibuf_flag(context->clip, &context->user,
1679 context->clip_flag, MOVIECLIP_CACHE_SKIP);
1680 if (!destination_ibuf)
1683 frame_width = destination_ibuf->x;
1684 frame_height = destination_ibuf->y;
1686 //#pragma omp parallel for private(a) shared(destination_ibuf, ok) if (map_size>1)
1687 for (a = 0; a < map_size; a++) {
1688 TrackContext *track_context = NULL;
1689 MovieTrackingTrack *track;
1690 MovieTrackingMarker *marker;
1692 tracks_map_get(context->tracks_map, a, &track, (void **)&track_context);
1694 marker = BKE_tracking_exact_marker(track, curfra);
1696 if (marker && (marker->flag & MARKER_DISABLED) == 0) {
1698 int width, height, tracked = 0, need_readjust = 0;
1699 float margin[2], dim[2], pat_min[2], pat_max[2];
1700 MovieTrackingMarker marker_new, *marker_keyed;
1701 int onbound = FALSE, nextfra;
1702 double dst_pixel_x[5], dst_pixel_y[5];
1704 if (track->pattern_match == TRACK_MATCH_KEYFRAME)
1705 need_readjust = context->first_time;
1707 need_readjust = TRUE;
1709 if (context->backwards)
1710 nextfra = curfra - 1;
1712 nextfra = curfra + 1;
1714 /* margin from frame boundaries */
1715 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
1716 sub_v2_v2v2(dim, pat_max, pat_min);
1717 margin[0] = margin[1] = MAX2(dim[0], dim[1]) / 2.0f;
1719 margin[0] = MAX2(margin[0], (float)track->margin / destination_ibuf->x);
1720 margin[1] = MAX2(margin[1], (float)track->margin / destination_ibuf->y);
1722 /* do not track markers which are too close to boundary */
1723 if (marker->pos[0] < margin[0] || marker->pos[0] > 1.0f - margin[0] ||
1724 marker->pos[1] < margin[1] || marker->pos[1] > 1.0f - margin[1])
1729 /* to convert to the x/y split array format for libmv. */
1730 double src_pixel_x[5];
1731 double src_pixel_y[5];
1733 /* settings for the tracker */
1734 struct libmv_trackRegionOptions options = {0};
1735 struct libmv_trackRegionResult result;
1739 if (need_readjust) {
1740 ImBuf *reference_ibuf = NULL;
1741 /* calculate patch for keyframed position */
1742 reference_ibuf = get_adjust_ibuf(context, track, marker, curfra, &marker_keyed);
1743 track_context->marker = *marker_keyed;
1745 if (track_context->search_area)
1746 MEM_freeN(track_context->search_area);
1748 track_context->search_area = get_search_floatbuf(reference_ibuf, track,
1749 marker_keyed, &width, &height);
1750 track_context->search_area_height = height;
1751 track_context->search_area_width = width;
1753 IMB_freeImBuf(reference_ibuf);
1755 if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0) {
1756 if (track_context->mask)
1757 MEM_freeN(track_context->mask);
1759 track_context->mask = BKE_tracking_track_mask_get(frame_width, frame_height,
1764 /* for now track to the same search area dimension as marker has got for current frame
1765 * will make all tracked markers in currently tracked segment have the same search area
1766 * size, but it's quite close to what is actually needed
1768 patch_new = get_search_floatbuf(destination_ibuf, track, marker, &width, &height);
1770 /* Configure the tracker */
1771 options.motion_model = track->motion_model;
1774 ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_BRUTE) != 0);
1776 options.use_normalization =
1777 ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_NORMALIZATION) != 0);
1779 options.num_iterations = 50;
1780 options.minimum_correlation = track->minimum_correlation;
1781 options.sigma = 0.9;
1783 if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0)
1784 options.image1_mask = track_context->mask;
1786 /* Convert the marker corners and center into pixel coordinates in the search/destination images. */
1787 get_marker_coords_for_tracking(frame_width, frame_height, &track_context->marker, src_pixel_x, src_pixel_y);
1788 get_marker_coords_for_tracking(frame_width, frame_height, marker, dst_pixel_x, dst_pixel_y);
1790 /* Run the tracker! */
1791 tracked = libmv_trackRegion(&options,
1792 track_context->search_area,
1793 track_context->search_area_width,
1794 track_context->search_area_height,
1795 patch_new, width, height,
1796 src_pixel_x, src_pixel_y,
1798 dst_pixel_x, dst_pixel_y);
1799 MEM_freeN(patch_new);
1802 if (tracked && !onbound) {
1803 memset(&marker_new, 0, sizeof(marker_new));
1804 marker_new = *marker;
1805 set_marker_coords_from_tracking(frame_width, frame_height, &marker_new, dst_pixel_x, dst_pixel_y);
1806 marker_new.flag |= MARKER_TRACKED;
1807 marker_new.framenr = nextfra;
1809 marker_search_scale_after_tracking(marker, &marker_new);
1811 //#pragma omp critical
1813 if (context->first_time) {
1814 /* check if there's no keyframe/tracked markers before tracking marker.
1815 * if so -- create disabled marker before currently tracking "segment"
1818 put_disabled_marker(track, &marker_new, !context->backwards, 0);
1821 /* insert currently tracked marker */
1822 BKE_tracking_insert_marker(track, &marker_new);
1824 /* make currently tracked segment be finished with disabled marker */
1825 put_disabled_marker(track, &marker_new, context->backwards, 0);
1829 marker_new = *marker;
1831 marker_new.framenr = nextfra;
1832 marker_new.flag |= MARKER_DISABLED;
1834 //#pragma omp critical
1836 BKE_tracking_insert_marker(track, &marker_new);
1848 IMB_freeImBuf(destination_ibuf);
1850 context->first_time = FALSE;
1856 /*********************** camera solving *************************/
1858 typedef struct MovieReconstructContext {
1860 struct libmv_Tracks *tracks;
1861 int keyframe1, keyframe2;
1864 struct libmv_Reconstruction *reconstruction;
1866 char object_name[MAX_NAME];
1871 float principal_point[2];
1874 float reprojection_error;
1876 TracksMap *tracks_map;
1879 } MovieReconstructContext;
1881 typedef struct ReconstructProgressData {
1885 char *stats_message;
1887 } ReconstructProgressData;
1890 static struct libmv_Tracks *create_libmv_tracks(ListBase *tracksbase, int width, int height)
1893 MovieTrackingTrack *track;
1894 struct libmv_Tracks *tracks = libmv_tracksNew();
1896 track = tracksbase->first;
1900 for (a = 0; a < track->markersnr; a++) {
1901 MovieTrackingMarker *marker = &track->markers[a];
1903 if ((marker->flag & MARKER_DISABLED) == 0) {
1904 libmv_tracksInsert(tracks, marker->framenr, tracknr,
1905 marker->pos[0] * width, marker->pos[1] * height);
1909 track = track->next;
1916 static void retrieve_libmv_reconstruct_intrinscis(MovieReconstructContext *context, MovieTracking *tracking)
1918 struct libmv_Reconstruction *libmv_reconstruction = context->reconstruction;
1919 struct libmv_CameraIntrinsics *libmv_intrinsics = libmv_ReconstructionExtractIntrinsics(libmv_reconstruction);
1921 float aspy = 1.0f / tracking->camera.pixel_aspect;
1923 double focal_length, principal_x, principal_y, k1, k2, k3;
1926 libmv_CameraIntrinsicsExtract(libmv_intrinsics, &focal_length, &principal_x, &principal_y,
1927 &k1, &k2, &k3, &width, &height);
1929 tracking->camera.focal = focal_length;
1930 tracking->camera.principal[0] = principal_x;
1932 tracking->camera.principal[1] = principal_y / aspy;
1933 tracking->camera.k1 = k1;
1934 tracking->camera.k2 = k2;
1937 static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, MovieTracking *tracking)
1939 struct libmv_Reconstruction *libmv_reconstruction = context->reconstruction;
1940 MovieTrackingReconstruction *reconstruction = NULL;
1941 MovieReconstructedCamera *reconstructed;
1942 MovieTrackingTrack *track;
1943 ListBase *tracksbase = NULL;
1944 int ok = TRUE, tracknr = 0, a, origin_set = FALSE;
1945 int sfra = context->sfra, efra = context->efra;
1948 if (context->is_camera) {
1949 tracksbase = &tracking->tracks;
1950 reconstruction = &tracking->reconstruction;
1953 MovieTrackingObject *object = BKE_tracking_named_object(tracking, context->object_name);
1955 tracksbase = &object->tracks;
1956 reconstruction = &object->reconstruction;
1961 track = tracksbase->first;
1965 if (libmv_reporojectionPointForTrack(libmv_reconstruction, tracknr, pos)) {
1966 track->bundle_pos[0] = pos[0];
1967 track->bundle_pos[1] = pos[1];
1968 track->bundle_pos[2] = pos[2];
1970 track->flag |= TRACK_HAS_BUNDLE;
1971 track->error = libmv_reporojectionErrorForTrack(libmv_reconstruction, tracknr);
1974 track->flag &= ~TRACK_HAS_BUNDLE;
1977 printf("No bundle for track #%d '%s'\n", tracknr, track->name);
1980 track = track->next;
1984 if (reconstruction->cameras)
1985 MEM_freeN(reconstruction->cameras);
1987 reconstruction->camnr = 0;
1988 reconstruction->cameras = NULL;
1989 reconstructed = MEM_callocN((efra - sfra + 1) * sizeof(MovieReconstructedCamera),
1990 "temp reconstructed camera");
1992 for (a = sfra; a <= efra; a++) {
1995 if (libmv_reporojectionCameraForImage(libmv_reconstruction, a, matd)) {
1998 float error = libmv_reporojectionErrorForImage(libmv_reconstruction, a);
2000 for (i = 0; i < 4; i++)
2001 for (j = 0; j < 4; j++)
2002 mat[i][j] = matd[i][j];
2005 copy_m4_m4(imat, mat);
2011 mult_m4_m4m4(mat, imat, mat);
2013 copy_m4_m4(reconstructed[reconstruction->camnr].mat, mat);
2014 reconstructed[reconstruction->camnr].framenr = a;
2015 reconstructed[reconstruction->camnr].error = error;
2016 reconstruction->camnr++;
2020 printf("No camera for frame %d\n", a);
2024 if (reconstruction->camnr) {
2025 int size = reconstruction->camnr * sizeof(MovieReconstructedCamera);
2026 reconstruction->cameras = MEM_callocN(size, "reconstructed camera");
2027 memcpy(reconstruction->cameras, reconstructed, size);
2031 track = tracksbase->first;
2033 if (track->flag & TRACK_HAS_BUNDLE)
2034 mul_v3_m4v3(track->bundle_pos, imat, track->bundle_pos);
2036 track = track->next;
2040 MEM_freeN(reconstructed);
2045 static int retrieve_libmv_reconstruct(MovieReconstructContext *context, MovieTracking *tracking)
2047 /* take the intrinscis back from libmv */
2048 retrieve_libmv_reconstruct_intrinscis(context, tracking);
2050 return retrieve_libmv_reconstruct_tracks(context, tracking);
2053 static int get_refine_intrinsics_flags(MovieTracking *tracking, MovieTrackingObject *object)
2055 int refine = tracking->settings.refine_camera_intrinsics;
2058 if ((object->flag & TRACKING_OBJECT_CAMERA) == 0)
2061 if (refine & REFINE_FOCAL_LENGTH)
2062 flags |= LIBMV_REFINE_FOCAL_LENGTH;
2064 if (refine & REFINE_PRINCIPAL_POINT)
2065 flags |= LIBMV_REFINE_PRINCIPAL_POINT;
2067 if (refine & REFINE_RADIAL_DISTORTION_K1)
2068 flags |= REFINE_RADIAL_DISTORTION_K1;
2070 if (refine & REFINE_RADIAL_DISTORTION_K2)
2071 flags |= REFINE_RADIAL_DISTORTION_K2;
2076 static int count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tracksbase)
2079 int frame1 = tracking->settings.keyframe1, frame2 = tracking->settings.keyframe2;
2080 MovieTrackingTrack *track;
2082 track = tracksbase->first;
2084 if (BKE_tracking_has_enabled_marker(track, frame1))
2085 if (BKE_tracking_has_enabled_marker(track, frame2))
2088 track = track->next;
2095 int BKE_tracking_can_reconstruct(MovieTracking *tracking, MovieTrackingObject *object, char *error_msg, int error_size)
2098 ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object);
2100 if (tracking->settings.motion_flag & TRACKING_MOTION_MODAL) {
2101 /* TODO: check for number of tracks? */
2104 else if (count_tracks_on_both_keyframes(tracking, tracksbase) < 8) {
2105 BLI_strncpy(error_msg, "At least 8 common tracks on both of keyframes are needed for reconstruction",
2113 BLI_strncpy(error_msg, "Blender is compiled without motion tracking library", error_size);
2122 MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieTracking *tracking, MovieTrackingObject *object,
2123 int keyframe1, int keyframe2, int width, int height)
2125 MovieReconstructContext *context = MEM_callocN(sizeof(MovieReconstructContext), "MovieReconstructContext data");
2126 MovieTrackingCamera *camera = &tracking->camera;
2127 ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object);
2128 float aspy = 1.0f / tracking->camera.pixel_aspect;
2129 int num_tracks = BLI_countlist(tracksbase);
2130 int sfra = INT_MAX, efra = INT_MIN;
2131 MovieTrackingTrack *track;
2133 BLI_strncpy(context->object_name, object->name, sizeof(context->object_name));
2134 context->is_camera = object->flag & TRACKING_OBJECT_CAMERA;
2135 context->motion_flag = tracking->settings.motion_flag;
2137 context->tracks_map = tracks_map_new(context->object_name, context->is_camera, num_tracks, 0);
2139 track = tracksbase->first;
2141 int first = 0, last = track->markersnr - 1;
2142 MovieTrackingMarker *first_marker = &track->markers[0];
2143 MovieTrackingMarker *last_marker = &track->markers[track->markersnr - 1];
2145 /* find first not-disabled marker */
2146 while (first <= track->markersnr - 1 && first_marker->flag & MARKER_DISABLED) {
2151 /* find last not-disabled marker */
2152 while (last >= 0 && last_marker->flag & MARKER_DISABLED) {
2157 if (first < track->markersnr - 1)
2158 sfra = MIN2(sfra, first_marker->framenr);
2161 efra = MAX2(efra, last_marker->framenr);
2163 tracks_map_insert(context->tracks_map, track, NULL);
2165 track = track->next;
2168 context->sfra = sfra;
2169 context->efra = efra;
2172 context->tracks = create_libmv_tracks(tracksbase, width, height * aspy);
2173 context->keyframe1 = keyframe1;
2174 context->keyframe2 = keyframe2;
2175 context->refine_flags = get_refine_intrinsics_flags(tracking, object);
2183 context->focal_length = camera->focal;
2184 context->principal_point[0] = camera->principal[0];
2185 context->principal_point[1] = camera->principal[1] * aspy;
2187 context->k1 = camera->k1;
2188 context->k2 = camera->k2;
2189 context->k3 = camera->k3;
2194 void BKE_tracking_reconstruction_context_free(MovieReconstructContext *context)
2197 if (context->reconstruction)
2198 libmv_destroyReconstruction(context->reconstruction);
2200 libmv_tracksDestroy(context->tracks);
2203 tracks_map_free(context->tracks_map, NULL);
2209 static void solve_reconstruction_update_cb(void *customdata, double progress, const char *message)
2211 ReconstructProgressData *progressdata = customdata;
2213 if (progressdata->progress) {
2214 *progressdata->progress = progress;
2215 *progressdata->do_update = TRUE;
2218 BLI_snprintf(progressdata->stats_message, progressdata->message_size, "Solving camera | %s", message);
2223 static int solve_reconstruction_testbreak_cb(void *customdata)
2225 ReconstructProgressData *progressdata = customdata;
2227 if (progressdata->stop && *progressdata->stop)
2234 void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short *stop, short *do_update,
2235 float *progress, char *stats_message, int message_size)
2240 ReconstructProgressData progressdata;
2242 progressdata.stop = stop;
2243 progressdata.do_update = do_update;
2244 progressdata.progress = progress;
2245 progressdata.stats_message = stats_message;
2246 progressdata.message_size = message_size;
2248 if (context->motion_flag & TRACKING_MOTION_MODAL) {
2249 context->reconstruction = libmv_solveModal(context->tracks,
2250 context->focal_length,
2251 context->principal_point[0], context->principal_point[1],
2252 context->k1, context->k2, context->k3,
2253 solve_reconstruction_update_cb, &progressdata);
2256 context->reconstruction = libmv_solveReconstruction(context->tracks,
2257 context->keyframe1, context->keyframe2,
2258 context->refine_flags,
2259 context->focal_length,
2260 context->principal_point[0], context->principal_point[1],
2261 context->k1, context->k2, context->k3,
2262 solve_reconstruction_update_cb, &progressdata);
2265 error = libmv_reprojectionError(context->reconstruction);
2267 context->reprojection_error = error;
2273 (void) stats_message;
2274 (void) message_size;
2278 int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTracking *tracking)
2280 MovieTrackingReconstruction *reconstruction;
2282 tracks_map_merge(context->tracks_map, tracking);
2284 if (context->is_camera) {
2285 reconstruction = &tracking->reconstruction;
2288 MovieTrackingObject *object;
2290 object = BKE_tracking_named_object(tracking, context->object_name);
2291 reconstruction = &object->reconstruction;
2294 reconstruction->error = context->reprojection_error;
2295 reconstruction->flag |= TRACKING_RECONSTRUCTED;
2298 if (!retrieve_libmv_reconstruct(context, tracking))
2305 void BKE_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track)
2307 BLI_uniquename(tracksbase, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
2310 MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, MovieTrackingObject *object, const char *name)
2312 ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object);
2313 MovieTrackingTrack *track = tracksbase->first;
2316 if (!strcmp(track->name, name))
2319 track = track->next;
2325 static int reconstruction_camera_index(MovieTrackingReconstruction *reconstruction, int framenr, int nearest)
2327 MovieReconstructedCamera *cameras = reconstruction->cameras;
2330 if (!reconstruction->camnr)
2333 if (framenr < cameras[0].framenr) {
2340 if (framenr > cameras[reconstruction->camnr - 1].framenr) {
2342 return reconstruction->camnr - 1;
2347 if (reconstruction->last_camera < reconstruction->camnr)
2348 a = reconstruction->last_camera;
2350 if (cameras[a].framenr >= framenr)
2353 while (a >= 0 && a < reconstruction->camnr) {
2354 int cfra = cameras[a].framenr;
2356 /* check if needed framenr was "skipped" -- no data for requested frame */
2358 if (d > 0 && cfra > framenr) {
2359 /* interpolate with previous position */
2366 if (d < 0 && cfra < framenr) {
2367 /* interpolate with next position */
2374 if (cfra == framenr) {
2375 reconstruction->last_camera = a;
2386 static void scale_reconstructed_camera(MovieTrackingObject *object, float mat[4][4])
2388 if ((object->flag & TRACKING_OBJECT_CAMERA) == 0) {
2391 scale_m4_fl(smat, 1.0f / object->scale);
2392 mult_m4_m4m4(mat, mat, smat);
2396 MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking,
2397 MovieTrackingObject *object, int framenr)
2399 MovieTrackingReconstruction *reconstruction;
2402 reconstruction = BKE_tracking_object_reconstruction(tracking, object);
2403 a = reconstruction_camera_index(reconstruction, framenr, FALSE);
2408 return &reconstruction->cameras[a];
2411 void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, MovieTrackingObject *object,
2412 int framenr, float mat[4][4])
2414 MovieTrackingReconstruction *reconstruction;
2415 MovieReconstructedCamera *cameras;
2418 reconstruction = BKE_tracking_object_reconstruction(tracking, object);
2419 cameras = reconstruction->cameras;
2420 a = reconstruction_camera_index(reconstruction, framenr, 1);
2428 if (cameras[a].framenr != framenr && a > 0 && a < reconstruction->camnr - 1) {
2429 float t = ((float)framenr - cameras[a].framenr) / (cameras[a + 1].framenr - cameras[a].framenr);
2431 blend_m4_m4m4(mat, cameras[a].mat, cameras[a + 1].mat, t);
2434 copy_m4_m4(mat, cameras[a].mat);
2437 scale_reconstructed_camera(object, mat);
2440 void BKE_get_tracking_mat(Scene *scene, Object *ob, float mat[4][4])
2446 ob = BKE_scene_camera_find(scene);
2450 BKE_object_where_is_calc_mat4(scene, ob, mat);
2455 void BKE_tracking_camera_shift(MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty)
2457 /* indeed in both of cases it should be winx -- it's just how camera shift works for blender's camera */
2458 *shiftx = (0.5f * winx - tracking->camera.principal[0]) / winx;
2459 *shifty = (0.5f * winy - tracking->camera.principal[1]) / winx;
2462 void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camera *camera, int width, int height)
2464 float focal = tracking->camera.focal;
2466 camera->sensor_x = tracking->camera.sensor_width;
2467 camera->sensor_fit = CAMERA_SENSOR_FIT_AUTO;
2468 camera->lens = focal * camera->sensor_x / width;
2470 scene->r.xsch = width * tracking->camera.pixel_aspect;
2471 scene->r.ysch = height;
2473 scene->r.xasp = 1.0f;
2474 scene->r.yasp = 1.0f;
2476 BKE_tracking_camera_shift(tracking, width, height, &camera->shiftx, &camera->shifty);
2479 void BKE_tracking_projection_matrix(MovieTracking *tracking, MovieTrackingObject *object,
2480 int framenr, int winx, int winy, float mat[4][4])
2482 MovieReconstructedCamera *camera;
2483 float lens = tracking->camera.focal * tracking->camera.sensor_width / (float)winx;
2484 float viewfac, pixsize, left, right, bottom, top, clipsta, clipend;
2486 float ycor = 1.0f / tracking->camera.pixel_aspect;
2487 float shiftx, shifty, winside = MAX2(winx, winy);
2489 BKE_tracking_camera_shift(tracking, winx, winy, &shiftx, &shifty);
2495 viewfac = (lens * winx) / tracking->camera.sensor_width;
2497 viewfac = (ycor * lens * winy) / tracking->camera.sensor_width;
2499 pixsize = clipsta / viewfac;
2501 left = -0.5f * (float)winx + shiftx * winside;
2502 bottom = -0.5f * (ycor) * (float)winy + shifty * winside;
2503 right = 0.5f * (float)winx + shiftx * winside;
2504 top = 0.5f * (ycor) * (float)winy + shifty * winside;
2511 perspective_m4(winmat, left, right, bottom, top, clipsta, clipend);
2513 camera = BKE_tracking_get_reconstructed_camera(tracking, object, framenr);
2518 invert_m4_m4(imat, camera->mat);
2519 mult_m4_m4m4(mat, winmat, imat);
2521 else copy_m4_m4(mat, winmat);
2524 ListBase *BKE_tracking_get_tracks(MovieTracking *tracking)
2526 MovieTrackingObject *object = BKE_tracking_active_object(tracking);
2528 if (object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) {
2529 return &object->tracks;
2532 return &tracking->tracks;
2535 MovieTrackingTrack *BKE_tracking_active_track(MovieTracking *tracking)
2537 ListBase *tracksbase;
2539 if (!tracking->act_track)
2542 tracksbase = BKE_tracking_get_tracks(tracking);
2544 /* check that active track is in current tracks list */
2545 if (BLI_findindex(tracksbase, tracking->act_track) >= 0)
2546 return tracking->act_track;
2551 MovieTrackingObject *BKE_tracking_active_object(MovieTracking *tracking)
2553 return BLI_findlink(&tracking->objects, tracking->objectnr);
2556 MovieTrackingObject *BKE_tracking_get_camera_object(MovieTracking *tracking)
2558 MovieTrackingObject *object = tracking->objects.first;
2561 if (object->flag & TRACKING_OBJECT_CAMERA)
2564 object = object->next;
2570 ListBase *BKE_tracking_object_tracks(MovieTracking *tracking, MovieTrackingObject *object)
2572 if (object->flag & TRACKING_OBJECT_CAMERA) {
2573 return &tracking->tracks;
2576 return &object->tracks;
2579 MovieTrackingReconstruction *BKE_tracking_object_reconstruction(MovieTracking *tracking, MovieTrackingObject *object)
2581 if (object->flag & TRACKING_OBJECT_CAMERA) {
2582 return &tracking->reconstruction;
2585 return &object->reconstruction;
2588 MovieTrackingReconstruction *BKE_tracking_get_reconstruction(MovieTracking *tracking)
2590 MovieTrackingObject *object = BKE_tracking_active_object(tracking);
2592 return BKE_tracking_object_reconstruction(tracking, object);
2595 void BKE_tracking_apply_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
2597 MovieTrackingCamera *camera = &tracking->camera;
2601 float aspy = 1.0f / tracking->camera.pixel_aspect;
2603 /* normalize coords */
2604 x = (co[0] - camera->principal[0]) / camera->focal;
2605 y = (co[1] - camera->principal[1] * aspy) / camera->focal;
2607 libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
2608 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
2610 /* result is in image coords already */
2620 void BKE_tracking_invert_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
2622 MovieTrackingCamera *camera = &tracking->camera;
2625 double x = co[0], y = co[1];
2626 float aspy = 1.0f / tracking->camera.pixel_aspect;
2628 libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
2629 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
2631 nco[0] = x * camera->focal + camera->principal[0];
2632 nco[1] = y * camera->focal + camera->principal[1] * aspy;
2641 static int point_in_stroke(bGPDstroke *stroke, float x, float y)
2645 bGPDspoint *points = stroke->points;
2647 prev = stroke->totpoints - 1;
2649 for (i = 0; i < stroke->totpoints; i++) {
2650 if ((points[i].y < y && points[prev].y >= y) || (points[prev].y < y && points[i].y >= y)) {
2651 float fac = (y - points[i].y) / (points[prev].y - points[i].y);
2653 if (points[i].x + fac * (points[prev].x - points[i].x) < x)
2663 static int point_in_layer(bGPDlayer *layer, float x, float y)
2665 bGPDframe *frame = layer->frames.first;
2668 bGPDstroke *stroke = frame->strokes.first;
2671 if (point_in_stroke(stroke, x, y))
2674 stroke = stroke->next;
2676 frame = frame->next;
2682 static void retrieve_libmv_features(MovieTracking *tracking, ListBase *tracksbase,
2683 struct libmv_Features *features, int framenr, int width, int height,
2684 bGPDlayer *layer, int place_outside_layer)
2688 a = libmv_countFeatures(features);
2690 MovieTrackingTrack *track;
2691 double x, y, size, score;
2695 libmv_getFeature(features, a, &x, &y, &score, &size);
2701 ok = point_in_layer(layer, xu, yu) != place_outside_layer;
2704 track = BKE_tracking_add_track(tracking, tracksbase, xu, yu, framenr, width, height);
2705 track->flag |= SELECT;
2706 track->pat_flag |= SELECT;
2707 track->search_flag |= SELECT;
2713 void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImBuf *ibuf,
2714 int framenr, int margin, int min_trackness, int min_distance, bGPDlayer *layer,
2715 int place_outside_layer)
2718 struct libmv_Features *features;
2719 unsigned char *pixels = get_ucharbuf(ibuf);
2721 features = libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x,
2722 margin, min_trackness, min_distance);
2726 retrieve_libmv_features(tracking, tracksbase, features, framenr,
2727 ibuf->x, ibuf->y, layer, place_outside_layer);
2729 libmv_destroyFeatures(features);
2736 (void) min_trackness;
2737 (void) min_distance;
2739 (void) place_outside_layer;
2743 MovieTrackingTrack *BKE_tracking_indexed_track(MovieTracking *tracking, int tracknr, ListBase **tracksbase_r)
2745 MovieTrackingObject *object;
2748 object = tracking->objects.first;
2750 ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object);
2751 MovieTrackingTrack *track = tracksbase->first;
2754 if (track->flag & TRACK_HAS_BUNDLE) {
2755 if (cur == tracknr) {
2756 *tracksbase_r = tracksbase;
2763 track = track->next;
2766 object = object->next;
2769 *tracksbase_r = NULL;
2774 static int stabilization_median_point(MovieTracking *tracking, int framenr, float median[2])
2777 float min[2], max[2];
2778 MovieTrackingTrack *track;
2780 INIT_MINMAX2(min, max);
2782 track = tracking->tracks.first;
2784 if (track->flag & TRACK_USE_2D_STAB) {
2785 MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr);
2787 DO_MINMAX2(marker->pos, min, max);
2792 track = track->next;
2795 median[0] = (max[0] + min[0]) / 2.0f;
2796 median[1] = (max[1] + min[1]) / 2.0f;
2801 static void calculate_stabdata(MovieTracking *tracking, int framenr, float width, float height,
2802 float firstmedian[2], float median[2], float loc[2], float *scale, float *angle)
2804 MovieTrackingStabilization *stab = &tracking->stabilization;
2806 *scale = (stab->scale - 1.0f) * stab->scaleinf + 1.0f;
2809 loc[0] = (firstmedian[0] - median[0]) * width * (*scale);
2810 loc[1] = (firstmedian[1] - median[1]) * height * (*scale);
2812 mul_v2_fl(loc, stab->locinf);
2814 if ((stab->flag & TRACKING_STABILIZE_ROTATION) && stab->rot_track && stab->rotinf) {
2815 MovieTrackingMarker *marker;
2817 float x0 = (float)width / 2.0f, y0 = (float)height / 2.0f;
2818 float x = median[0] * width, y = median[1] * height;
2820 marker = BKE_tracking_get_marker(stab->rot_track, 1);
2821 sub_v2_v2v2(a, marker->pos, firstmedian);
2825 marker = BKE_tracking_get_marker(stab->rot_track, framenr);
2826 sub_v2_v2v2(b, marker->pos, median);
2830 *angle = -atan2(a[0] * b[1] - a[1] * b[0], a[0] * b[0] + a[1] * b[1]);
2831 *angle *= stab->rotinf;
2833 /* convert to rotation around image center */
2834 loc[0] -= (x0 + (x - x0) * cosf(*angle) - (y - y0) * sinf(*angle) - x) * (*scale);
2835 loc[1] -= (y0 + (x - x0) * sinf(*angle) + (y - y0) * cosf(*angle) - y) * (*scale);
2839 static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, int height)
2841 float firstmedian[2];
2842 MovieTrackingStabilization *stab = &tracking->stabilization;
2843 float aspect = tracking->camera.pixel_aspect;
2848 if (stabilization_median_point(tracking, 1, firstmedian)) {
2849 int sfra = INT_MAX, efra = INT_MIN, cfra;
2851 MovieTrackingTrack *track;
2855 track = tracking->tracks.first;
2857 if (track->flag & TRACK_USE_2D_STAB ||
2858 ((stab->flag & TRACKING_STABILIZE_ROTATION) && track == stab->rot_track))
2860 sfra = MIN2(sfra, track->markers[0].framenr);
2861 efra = MAX2(efra, track->markers[track->markersnr - 1].framenr);
2864 track = track->next;
2867 for (cfra = sfra; cfra <= efra; cfra++) {
2869 float loc[2], angle, tmp_scale;
2872 float points[4][2] = {{0.0f, 0.0f}, {0.0f, height}, {width, height}, {width, 0.0f}};
2875 stabilization_median_point(tracking, cfra, median);
2877 calculate_stabdata(tracking, cfra, width, height, firstmedian, median, loc, &tmp_scale, &angle);
2879 BKE_tracking_stabdata_to_mat4(width, height, aspect, loc, 1.0f, angle, mat);
2884 for (i = 0; i < 4; i++) {
2886 float a[3] = {0.0f, 0.0f, 0.0f}, b[3] = {0.0f, 0.0f, 0.0f};
2888 copy_v3_v3(a, points[i]);
2889 copy_v3_v3(b, points[(i + 1) % 4]);
2894 for (j = 0; j < 4; j++) {
2895 float point[3] = {points[j][0], points[j][1], 0.0f};
2898 sub_v3_v3v3(v1, b, a);
2899 sub_v3_v3v3(v2, point, a);
2901 if (cross_v2v2(v1, v2) >= 0.0f) {
2902 const float rotDx[4][2] = {{1.0f, 0.0f}, {0.0f, -1.0f}, {-1.0f, 0.0f}, {0.0f, 1.0f}};
2903 const float rotDy[4][2] = {{0.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, -1.0f}, {-1.0f, 0.0f}};
2905 float dx = loc[0] * rotDx[j][0] + loc[1] * rotDx[j][1],
2906 dy = loc[0] * rotDy[j][0] + loc[1] * rotDy[j][1];
2908 float w, h, E, F, G, H, I, J, K, S;
2911 w = (float)height / 2.0f;
2912 h = (float)width / 2.0f;
2915 w = (float)width / 2.0f;
2916 h = (float)height / 2.0f;
2919 E = -w * co + h * si;
2920 F = -h * co - w * si;
2922 if ((i % 2) == (j % 2)) {
2923 G = -w * co - h * si;
2924 H = h * co - w * si;
2927 G = w * co + h * si;
2928 H = -h * co + w * si;
2935 S = (-w * I - h * J) / (dx * I + dy * J + K);
2937 scale = MAX2(scale, S);
2943 stab->scale = scale;
2945 if (stab->maxscale > 0.0f)
2946 stab->scale = MIN2(stab->scale, stab->maxscale);
2957 static ImBuf *stabilize_alloc_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill)
2961 if (cacheibuf && (cacheibuf->x != srcibuf->x || cacheibuf->y != srcibuf->y)) {
2962 IMB_freeImBuf(cacheibuf);
2968 if (srcibuf->rect_float)
2969 flags |= IB_rectfloat;
2973 float col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2975 IMB_rectfill(cacheibuf, col);
2979 cacheibuf = IMB_allocImBuf(srcibuf->x, srcibuf->y, srcibuf->planes, flags);
2980 cacheibuf->profile = srcibuf->profile;
2986 void BKE_tracking_stabilization_data(MovieTracking *tracking, int framenr, int width, int height,
2987 float loc[2], float *scale, float *angle)
2989 float firstmedian[2], median[2];
2990 MovieTrackingStabilization *stab = &tracking->stabilization;
2992 if ((stab->flag & TRACKING_2D_STABILIZATION) == 0) {
3000 if (stabilization_median_point(tracking, 1, firstmedian)) {
3001 stabilization_median_point(tracking, framenr, median);
3003 if ((stab->flag & TRACKING_AUTOSCALE) == 0)
3007 if (stab->flag & TRACKING_AUTOSCALE)
3008 stabilization_auto_scale_factor(tracking, width, height);
3010 calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle);
3015 calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle);
3025 ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf,
3026 float loc[2], float *scale, float *angle)
3028 float tloc[2], tscale, tangle;
3029 MovieTrackingStabilization *stab = &tracking->stabilization;
3031 float width = ibuf->x, height = ibuf->y;
3032 float aspect = tracking->camera.pixel_aspect;
3035 copy_v2_v2(tloc, loc);
3040 if ((stab->flag & TRACKING_2D_STABILIZATION) == 0) {
3050 BKE_tracking_stabilization_data(tracking, framenr, width, height, tloc, &tscale, &tangle);
3052 tmpibuf = stabilize_alloc_ibuf(NULL, ibuf, TRUE);
3054 /* scale would be handled by matrix transformation when angle is non-zero */
3055 if (tscale != 1.0f && tangle == 0.0f) {
3058 stabilization_auto_scale_factor(tracking, width, height);
3060 scaleibuf = stabilize_alloc_ibuf(stab->scaleibuf, ibuf, 0);
3061 stab->scaleibuf = scaleibuf;
3063 IMB_rectcpy(scaleibuf, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y);
3064 IMB_scalefastImBuf(scaleibuf, ibuf->x * tscale, ibuf->y * tscale);
3069 if (tangle == 0.0f) {
3070 /* if angle is zero, then it's much faster to use rect copy
3071 * but could be issues with subpixel precisions
3073 IMB_rectcpy(tmpibuf, ibuf,
3074 tloc[0] - (tscale - 1.0f) * width / 2.0f,
3075 tloc[1] - (tscale - 1.0f) * height / 2.0f,
3076 0, 0, ibuf->x, ibuf->y);
3080 int i, j, filter = tracking->stabilization.filter;
3081 void (*interpolation)(struct ImBuf *, struct ImBuf *, float, float, int, int) = NULL;
3083 BKE_tracking_stabdata_to_mat4(ibuf->x, ibuf->y, aspect, tloc, tscale, tangle, mat);
3086 if (filter == TRACKING_FILTER_NEAREAST)
3087 interpolation = neareast_interpolation;
3088 else if (filter == TRACKING_FILTER_BILINEAR)
3089 interpolation = bilinear_interpolation;
3090 else if (filter == TRACKING_FILTER_BICUBIC)
3091 interpolation = bicubic_interpolation;
3093 /* fallback to default interpolation method */
3094 interpolation = neareast_interpolation;
3096 for (j = 0; j < tmpibuf->y; j++) {
3097 for (i = 0; i < tmpibuf->x; i++) {
3098 float vec[3] = {i, j, 0};
3100 mul_v3_m4v3(vec, mat, vec);
3102 interpolation(ibuf, tmpibuf, vec[0], vec[1], i, j);
3107 tmpibuf->userflags |= IB_MIPMAP_INVALID;
3109 if (tmpibuf->rect_float)
3110 tmpibuf->userflags |= IB_RECT_INVALID;
3113 copy_v2_v2(loc, tloc);
3124 void BKE_tracking_stabdata_to_mat4(int width, int height, float aspect,
3125 float loc[2], float scale, float angle, float mat[4][4])
3127 float lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4], amat[4][4], iamat[4][4];
3128 float svec[3] = {scale, scale, scale};
3136 /* aspect ratio correction matrix */
3137 amat[0][0] = 1.0f / aspect;
3138 invert_m4_m4(iamat, amat);
3140 /* image center as rotation center */
3141 cmat[3][0] = (float)width / 2.0f;
3142 cmat[3][1] = (float)height / 2.0f;
3143 invert_m4_m4(icmat, cmat);
3145 size_to_mat4(smat, svec); /* scale matrix */
3146 add_v2_v2(lmat[3], loc); /* translation matrix */
3147 rotate_m4(rmat, 'Z', angle); /* rotation matrix */
3149 /* compose transformation matrix */
3150 mul_serie_m4(mat, lmat, cmat, amat, rmat, iamat, smat, icmat, NULL);
3153 MovieDistortion *BKE_tracking_distortion_create(void)
3155 MovieDistortion *distortion;
3157 distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
3162 MovieDistortion *BKE_tracking_distortion_copy(MovieDistortion *distortion)
3164 MovieDistortion *new_distortion;
3166 new_distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
3169 new_distortion->intrinsics = libmv_CameraIntrinsicsCopy(distortion->intrinsics);
3174 return new_distortion;
3177 void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking, int width, int height)
3179 MovieTrackingCamera *camera = &tracking->camera;
3180 float aspy = 1.0f / tracking->camera.pixel_aspect;
3183 if (!distortion->intrinsics) {
3184 distortion->intrinsics = libmv_CameraIntrinsicsNew(camera->focal,
3185 camera->principal[0], camera->principal[1] * aspy,
3186 camera->k1, camera->k2, camera->k3, width, height * aspy);
3189 libmv_CameraIntrinsicsUpdate(distortion->intrinsics, camera->focal,
3190 camera->principal[0], camera->principal[1] * aspy,
3191 camera->k1, camera->k2, camera->k3, width, height * aspy);
3202 ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *tracking,
3203 ImBuf *ibuf, int width, int height, float overscan, int undistort)
3207 BKE_tracking_distortion_update(distortion, tracking, width, height);
3209 resibuf = IMB_dupImBuf(ibuf);
3211 if (ibuf->rect_float) {
3214 libmv_CameraIntrinsicsUndistortFloat(distortion->intrinsics,
3215 ibuf->rect_float, resibuf->rect_float,
3216 ibuf->x, ibuf->y, overscan, ibuf->channels);
3219 libmv_CameraIntrinsicsDistortFloat(distortion->intrinsics,
3220 ibuf->rect_float, resibuf->rect_float,
3221 ibuf->x, ibuf->y, overscan, ibuf->channels);
3225 resibuf->userflags |= IB_RECT_INVALID;
3230 libmv_CameraIntrinsicsUndistortByte(distortion->intrinsics,
3231 (unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect,
3232 ibuf->x, ibuf->y, overscan, ibuf->channels);
3235 libmv_CameraIntrinsicsDistortByte(distortion->intrinsics,
3236 (unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect,
3237 ibuf->x, ibuf->y, overscan, ibuf->channels);