4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2011 Blender Foundation.
21 * All rights reserved.
23 * Contributor(s): Blender Foundation,
26 * ***** END GPL LICENSE BLOCK *****
29 /** \file blender/blenkernel/intern/tracking.c
38 #include "MEM_guardedalloc.h"
40 #include "DNA_movieclip_types.h"
41 #include "DNA_object_types.h" /* SELECT */
42 #include "DNA_scene_types.h"
44 #include "BLI_utildefines.h"
46 #include "BLI_listbase.h"
47 #include "BLI_ghash.h"
49 #include "BKE_global.h"
50 #include "BKE_tracking.h"
51 #include "BKE_movieclip.h"
52 #include "BKE_object.h"
53 #include "BKE_scene.h"
55 #include "IMB_imbuf_types.h"
56 #include "IMB_imbuf.h"
59 #include "libmv-capi.h"
62 /*********************** common functions *************************/
64 void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event)
70 if(track->pat_min[a]>track->pat_max[a])
71 SWAP(float, track->pat_min[a], track->pat_max[a]);
73 if(track->search_min[a]>track->search_max[a])
74 SWAP(float, track->search_min[a], track->search_max[a]);
77 if(event==CLAMP_PAT_DIM) {
79 /* pattern shouldn't be resized bigger than search */
80 track->pat_min[a]= MAX2(track->pat_min[a], track->search_min[a]);
81 track->pat_max[a]= MIN2(track->pat_max[a], track->search_max[a]);
84 else if(event==CLAMP_PAT_POS) {
86 sub_v2_v2v2(dim, track->pat_max, track->pat_min);
89 /* pattern shouldn't be moved outside of search */
90 if(track->pat_min[a] < track->search_min[a]) {
91 track->pat_min[a]= track->search_min[a];
92 track->pat_max[a]= track->pat_min[a]+dim[a];
94 if(track->pat_max[a] > track->search_max[a]) {
95 track->pat_max[a]= track->search_max[a];
96 track->pat_min[a]= track->pat_max[a]-dim[a];
100 else if(event==CLAMP_SEARCH_DIM) {
101 for(a= 0; a<2; a++) {
102 /* search shouldn't be resized smaller than pattern */
103 track->search_min[a]= MIN2(track->pat_min[a], track->search_min[a]);
104 track->search_max[a]= MAX2(track->pat_max[a], track->search_max[a]);
107 else if(event==CLAMP_SEARCH_POS) {
109 sub_v2_v2v2(dim, track->search_max, track->search_min);
111 for(a= 0; a<2; a++) {
112 /* search shouldn't be moved inside pattern */
113 if(track->search_min[a] > track->pat_min[a]) {
114 track->search_min[a]= track->pat_min[a];
115 track->search_max[a]= track->search_min[a]+dim[a];
117 if(track->search_max[a] < track->pat_max[a]) {
118 track->search_max[a]= track->pat_max[a];
119 track->search_min[a]= track->search_max[a]-dim[a];
124 /* marker's center should be in center of pattern */
125 if(event==CLAMP_PAT_DIM || event==CLAMP_PAT_POS) {
127 sub_v2_v2v2(dim, track->pat_max, track->pat_min);
129 for(a= 0; a<2; a++) {
130 track->pat_min[a]= -dim[a]/2.f;
131 track->pat_max[a]= dim[a]/2.f;
136 void BKE_tracking_track_flag(MovieTrackingTrack *track, int area, int flag, int clear)
138 if(area==TRACK_AREA_NONE)
142 if(area&TRACK_AREA_POINT) track->flag&= ~flag;
143 if(area&TRACK_AREA_PAT) track->pat_flag&= ~flag;
144 if(area&TRACK_AREA_SEARCH) track->search_flag&= ~flag;
146 if(area&TRACK_AREA_POINT) track->flag|= flag;
147 if(area&TRACK_AREA_PAT) track->pat_flag|= flag;
148 if(area&TRACK_AREA_SEARCH) track->search_flag|= flag;
152 MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, float x, float y,
153 int framenr, int width, int height)
155 MovieTrackingTrack *track;
156 MovieTrackingMarker marker;
157 float pat[2]= {5.5f, 5.5f}, search[2]= {80.5f, 80.5f}; /* TODO: move to default setting? */
159 /* XXX: not very nice to have such check here, but it will prevent
160 complaints about bad default settings for new markers */
161 if(tracking->settings.tracker==TRACKER_SAD) {
169 pat[0] /= (float)width;
170 pat[1] /= (float)height;
172 search[0] /= (float)width;
173 search[1] /= (float)height;
175 track= MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track");
176 strcpy(track->name, "Track");
178 memset(&marker, 0, sizeof(marker));
181 marker.framenr= framenr;
183 copy_v2_v2(track->pat_max, pat);
184 negate_v2_v2(track->pat_min, pat);
186 copy_v2_v2(track->search_max, search);
187 negate_v2_v2(track->search_min, search);
189 BKE_tracking_insert_marker(track, &marker);
191 BLI_addtail(&tracking->tracks, track);
192 BKE_track_unique_name(tracking, track);
197 void BKE_tracking_insert_marker(MovieTrackingTrack *track, MovieTrackingMarker *marker)
199 MovieTrackingMarker *old_marker= BKE_tracking_get_marker(track, marker->framenr);
201 if(old_marker && old_marker->framenr==marker->framenr) {
202 *old_marker= *marker;
204 int a= track->markersnr;
207 if(track->markers[a].framenr<marker->framenr)
213 if(track->markers) track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
214 else track->markers= MEM_callocN(sizeof(MovieTrackingMarker), "MovieTracking markers");
216 memmove(track->markers+a+2, track->markers+a+1, (track->markersnr-a-2)*sizeof(MovieTrackingMarker));
217 track->markers[a+1]= *marker;
219 track->last_marker= a+1;
223 void BKE_tracking_delete_marker(MovieTrackingTrack *track, int framenr)
227 while(a<track->markersnr) {
228 if(track->markers[a].framenr==framenr) {
229 if(track->markersnr>1) {
230 memmove(track->markers+a, track->markers+a+1, (track->markersnr-a-1)*sizeof(MovieTrackingMarker));
232 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
234 MEM_freeN(track->markers);
235 track->markers= NULL;
246 MovieTrackingMarker *BKE_tracking_get_marker(MovieTrackingTrack *track, int framenr)
248 int a= track->markersnr-1;
250 if(!track->markersnr)
253 /* approximate pre-first framenr marker with first marker */
254 if(framenr<track->markers[0].framenr)
255 return &track->markers[0];
257 if(track->last_marker<track->markersnr)
258 a= track->last_marker;
260 if(track->markers[a].framenr<=framenr) {
261 while(a<track->markersnr && track->markers[a].framenr<=framenr) {
262 if(track->markers[a].framenr==framenr) {
263 track->last_marker= a;
264 return &track->markers[a];
269 /* if there's no marker for exact position, use nearest marker from left side */
270 return &track->markers[a-1];
272 while(a>=0 && track->markers[a].framenr>=framenr) {
273 if(track->markers[a].framenr==framenr) {
274 track->last_marker= a;
275 return &track->markers[a];
281 /* if there's no marker for exact position, use nearest marker from left side */
282 return &track->markers[a];
288 MovieTrackingMarker *BKE_tracking_ensure_marker(MovieTrackingTrack *track, int framenr)
290 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
292 if(marker && marker->framenr!=framenr) {
293 MovieTrackingMarker marker_new;
296 marker_new.framenr= framenr;
298 BKE_tracking_insert_marker(track, &marker_new);
299 marker= BKE_tracking_get_marker(track, framenr);
305 MovieTrackingMarker *BKE_tracking_exact_marker(MovieTrackingTrack *track, int framenr)
307 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
309 if(marker && marker->framenr!=framenr)
315 int BKE_tracking_has_marker(MovieTrackingTrack *track, int framenr)
317 return BKE_tracking_exact_marker(track, framenr) != 0;
320 void BKE_tracking_free_track(MovieTrackingTrack *track)
322 if(track->markers) MEM_freeN(track->markers);
325 MovieTrackingTrack *BKE_tracking_copy_track(MovieTrackingTrack *track)
327 MovieTrackingTrack *new_track= MEM_dupallocN(track);
329 new_track->next= new_track->prev= NULL;
331 if(new_track->markers)
332 new_track->markers= MEM_dupallocN(new_track->markers);
337 void BKE_tracking_clear_path(MovieTrackingTrack *track, int ref_frame, int action)
341 if(action==TRACK_CLEAR_REMAINED) {
343 while(a<track->markersnr) {
344 if(track->markers[a].framenr>ref_frame) {
346 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
353 } else if(action==TRACK_CLEAR_UPTO) {
354 a= track->markersnr-1;
356 if(track->markers[a].framenr<=ref_frame) {
357 memmove(track->markers, track->markers+a, (track->markersnr-a)*sizeof(MovieTrackingMarker));
359 track->markersnr= track->markersnr-a;
360 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
367 } else if(action==TRACK_CLEAR_ALL) {
368 MovieTrackingMarker *marker, marker_new;
370 marker= BKE_tracking_get_marker(track, ref_frame);
374 MEM_freeN(track->markers);
375 track->markers= NULL;
379 BKE_tracking_insert_marker(track, &marker_new);
383 int BKE_tracking_test_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
385 int i, a= 0, b= 0, tot= dst_track->markersnr+src_track->markersnr;
388 for(i= 0; i<tot; i++) {
389 if(a>=src_track->markersnr) {
393 else if(b>=dst_track->markersnr) {
397 else if(src_track->markers[a].framenr<dst_track->markers[b].framenr) {
400 } else if(src_track->markers[a].framenr>dst_track->markers[b].framenr) {
404 if((src_track->markers[a].flag&MARKER_DISABLED)==0 && (dst_track->markers[b].flag&MARKER_DISABLED)==0)
416 void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
418 int i, a= 0, b= 0, tot;
419 MovieTrackingMarker *markers;
421 tot= BKE_tracking_test_join_tracks(dst_track, src_track);
423 markers= MEM_callocN(tot*sizeof(MovieTrackingMarker), "tracking joined tracks");
425 for(i= 0; i<tot; i++) {
426 if(b>=dst_track->markersnr) {
427 markers[i]= src_track->markers[a++];
429 else if(a>=src_track->markersnr) {
430 markers[i]= dst_track->markers[b++];
432 else if(src_track->markers[a].framenr<dst_track->markers[b].framenr) {
433 markers[i]= src_track->markers[a++];
434 } else if(src_track->markers[a].framenr>dst_track->markers[b].framenr) {
435 markers[i]= dst_track->markers[b++];
437 if((src_track->markers[a].flag&MARKER_DISABLED)) markers[i]= dst_track->markers[b];
438 else markers[i]= src_track->markers[a++];
445 MEM_freeN(dst_track->markers);
447 dst_track->markers= markers;
448 dst_track->markersnr= tot;
451 void BKE_tracking_free(MovieTracking *tracking)
453 MovieTrackingTrack *track;
455 for(track= tracking->tracks.first; track; track= track->next) {
456 BKE_tracking_free_track(track);
459 BLI_freelistN(&tracking->tracks);
461 if(tracking->reconstruction.cameras)
462 MEM_freeN(tracking->reconstruction.cameras);
464 if(tracking->stabilization.scaleibuf)
465 IMB_freeImBuf(tracking->stabilization.scaleibuf);
468 /*********************** tracking *************************/
470 typedef struct TrackContext {
471 MovieTrackingTrack *track;
474 /* ** KLT tracker ** */
475 struct libmv_RegionTracker *region_tracker;
476 float *patch; /* keyframed patch */
478 /* ** SAD tracker ** */
479 int patsize; /* size of pattern (currently only 16x16 due to libmv side) */
480 unsigned char *pattern; /* keyframed pattern */
481 unsigned char *warped; /* warped version of reference */
485 typedef struct MovieTrackingContext {
489 int first_time, frames;
491 TrackContext *track_context;
495 MovieTrackingSettings settings;
497 short backwards, disable_failed;
499 } MovieTrackingContext;
501 MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, short backwards, short disable_failed)
503 MovieTrackingContext *context= MEM_callocN(sizeof(MovieTrackingContext), "trackingContext");
504 MovieTracking *tracking= &clip->tracking;
505 MovieTrackingSettings *settings= &tracking->settings;
506 MovieTrackingTrack *track;
507 TrackContext *track_context;
509 context->settings= *settings;
510 context->backwards= backwards;
511 context->disable_failed= disable_failed;
512 context->hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "tracking trackHash");
513 context->sync_frame= user->framenr;
514 context->first_time= 1;
517 track= tracking->tracks.first;
519 if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
520 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
522 if((marker->flag&MARKER_DISABLED)==0)
523 context->num_tracks++;
529 if(context->num_tracks) {
532 BKE_movieclip_acquire_size(clip, user, &width, &height);
534 /* create tracking data */
535 context->track_context= MEM_callocN(sizeof(TrackContext)*context->num_tracks, "tracking track_context");
537 track_context= context->track_context;
538 track= tracking->tracks.first;
540 if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
541 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
543 if((marker->flag&MARKER_DISABLED)==0) {
544 MovieTrackingTrack *new_track= BKE_tracking_copy_track(track);
546 track_context->track= new_track;
550 if(context->settings.tracker==TRACKER_KLT) {
551 float search_size_x= (track->search_max[0]-track->search_min[0])*width;
552 float search_size_y= (track->search_max[1]-track->search_min[1])*height;
553 float pattern_size_x= (track->pat_max[0]-track->pat_min[0])*width;
554 float pattern_size_y= (track->pat_max[1]-track->pat_min[1])*height;
556 int level= log(2.0f * MIN2(search_size_x, search_size_y) / MAX2(pattern_size_x, pattern_size_y))/M_LN2;
558 track_context->region_tracker= libmv_regionTrackerNew(100, level, 0.2);
560 else if(context->settings.tracker==TRACKER_SAD) {
561 /* notfing to initialize */
566 BLI_ghash_insert(context->hash, new_track, track);
577 context->user= *user;
582 void BKE_tracking_context_free(MovieTrackingContext *context)
585 TrackContext *track_context;
587 for(a= 0, track_context= context->track_context; a<context->num_tracks; a++, track_context++) {
588 BKE_tracking_free_track(context->track_context[a].track);
591 if(track_context->region_tracker)
592 libmv_regionTrackerDestroy(track_context->region_tracker);
594 if(track_context->patch)
595 MEM_freeN(track_context->patch);
597 if(track_context->pattern)
598 MEM_freeN(track_context->pattern);
600 if(track_context->warped)
601 MEM_freeN(track_context->warped);
604 MEM_freeN(track_context->track);
607 if(context->track_context)
608 MEM_freeN(context->track_context);
610 BLI_ghash_free(context->hash, NULL, NULL);
615 static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track)
619 if((track->flag&(TRACK_DISABLE_RED|TRACK_DISABLE_GREEN|TRACK_DISABLE_BLUE))==0)
622 for(y= 0; y<ibuf->y; y++) {
623 for (x= 0; x<ibuf->x; x++) {
624 int pixel= ibuf->x*y + x;
626 if(ibuf->rect_float) {
627 float *rrgbf= ibuf->rect_float + pixel*4;
629 if(track->flag&TRACK_DISABLE_RED) rrgbf[0]= 0;
630 if(track->flag&TRACK_DISABLE_GREEN) rrgbf[1]= 0;
631 if(track->flag&TRACK_DISABLE_BLUE) rrgbf[2]= 0;
633 char *rrgb= (char*)ibuf->rect + pixel*4;
635 if(track->flag&TRACK_DISABLE_RED) rrgb[0]= 0;
636 if(track->flag&TRACK_DISABLE_GREEN) rrgb[1]= 0;
637 if(track->flag&TRACK_DISABLE_BLUE) rrgb[2]= 0;
643 static ImBuf *acquire_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
644 float min[2], float max[2], int margin, int anchored, float pos[2], int origin[2])
648 int x1, y1, x2, y2, w, h;
651 copy_v2_v2(mpos, marker->pos);
653 add_v2_v2(mpos, track->offset);
657 x1= x-(int)(-min[0]*ibuf->x);
658 y1= y-(int)(-min[1]*ibuf->y);
659 x2= x+(int)(max[0]*ibuf->x);
660 y2= y+(int)(max[1]*ibuf->y);
662 /* dimensions should be odd */
666 /* happens due to rounding issues */
670 tmpibuf= IMB_allocImBuf(w+margin*2, h+margin*2, 32, IB_rect);
671 IMB_rectcpy(tmpibuf, ibuf, 0, 0, x1-margin, y1-margin, w+margin*2, h+margin*2);
674 pos[0]= x-x1+(mpos[0]*ibuf->x-x)+margin;
675 pos[1]= y-y1+(mpos[1]*ibuf->y-y)+margin;
679 origin[0]= x1-margin;
680 origin[1]= y1-margin;
683 disable_imbuf_channels(tmpibuf, track);
688 ImBuf *BKE_tracking_acquire_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
689 int margin, int anchored, float pos[2], int origin[2])
691 return acquire_area_imbuf(ibuf, track, marker, track->pat_min, track->pat_max, margin, anchored, pos, origin);
694 ImBuf *BKE_tracking_acquire_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
695 int margin, int anchored, float pos[2], int origin[2])
697 return acquire_area_imbuf(ibuf, track, marker, track->search_min, track->search_max, margin, anchored, pos, origin);
701 static float *acquire_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
702 int *width_r, int *height_r, float pos[2], int origin[2])
706 int x, y, width, height;
708 width= (track->search_max[0]-track->search_min[0])*ibuf->x;
709 height= (track->search_max[1]-track->search_min[1])*ibuf->y;
711 tmpibuf= BKE_tracking_acquire_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
712 disable_imbuf_channels(tmpibuf, track);
717 fp= pixels= MEM_callocN(width*height*sizeof(float), "tracking floatBuf");
718 for(y= 0; y<(int)height; y++) {
719 for (x= 0; x<(int)width; x++) {
720 int pixel= tmpibuf->x*y + x;
722 if(tmpibuf->rect_float) {
723 float *rrgbf= ibuf->rect_float + pixel*4;
725 *fp= (0.2126*rrgbf[0] + 0.7152*rrgbf[1] + 0.0722*rrgbf[2])/255;
727 char *rrgb= (char*)tmpibuf->rect + pixel*4;
729 *fp= (0.2126*rrgb[0] + 0.7152*rrgb[1] + 0.0722*rrgb[2])/255;
736 IMB_freeImBuf(tmpibuf);
741 static unsigned char *acquire_search_bytebuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
742 int *width_r, int *height_r, float pos[2], int origin[2])
745 unsigned char *pixels, *fp;
746 int x, y, width, height;
748 width= (track->search_max[0]-track->search_min[0])*ibuf->x;
749 height= (track->search_max[1]-track->search_min[1])*ibuf->y;
751 tmpibuf= BKE_tracking_acquire_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
752 disable_imbuf_channels(tmpibuf, track);
757 fp= pixels= MEM_callocN(width*height*sizeof(unsigned char), "tracking byteBuf");
758 for(y= 0; y<(int)height; y++) {
759 for (x= 0; x<(int)width; x++) {
760 int pixel= tmpibuf->x*y + x;
762 if(tmpibuf->rect_float) {
763 float *rrgbf= ibuf->rect_float + pixel*4;
765 *fp= (0.2126*rrgbf[0] + 0.7152*rrgbf[1] + 0.0722*rrgbf[2]);
767 char *rrgb= (char*)tmpibuf->rect + pixel*4;
769 *fp= (0.2126*rrgb[0] + 0.7152*rrgb[1] + 0.0722*rrgb[2]);
776 IMB_freeImBuf(tmpibuf);
781 static ImBuf *acquire_frame_ibuf(MovieTrackingContext *context, int framenr)
784 int framenr_old= context->user.framenr;
786 context->user.framenr= framenr;
788 ibuf= BKE_movieclip_acquire_ibuf_flag(context->clip, &context->user, 0);
790 context->user.framenr= framenr_old;
795 static ImBuf *acquire_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track,
796 MovieTrackingMarker *marker, MovieTrackingMarker **marker_keyed)
798 int framenr= marker->framenr;
799 int a= marker-track->markers;
801 *marker_keyed= marker;
803 while(a>=0 && a<track->markersnr) {
804 if((track->markers[a].flag&MARKER_TRACKED)==0) {
805 framenr= track->markers[a].framenr;
806 *marker_keyed= &track->markers[a];
810 if(context->backwards) a++;
814 return acquire_frame_ibuf(context, framenr);
817 static ImBuf *acquire_adjust_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, MovieTrackingMarker *marker,
818 int curfra, MovieTrackingMarker **marker_keyed)
822 if(context->settings.adjframes == 0) {
823 ibuf= acquire_keyframed_ibuf(context, track, marker, marker_keyed);
825 ibuf= acquire_frame_ibuf(context, curfra);
827 /* use current marker as keyframed position */
828 *marker_keyed= marker;
834 static void acquire_warped(TrackContext *track_context, int x, int y, int width, unsigned char *image)
838 for(i=0; i<track_context->patsize; i++) {
839 for(j=0; j<track_context->patsize; j++) {
840 track_context->warped[i*track_context->patsize+j]=
841 image[(y+i-track_context->patsize/2)*width+x+j-track_context->patsize/2];
848 void BKE_tracking_sync(MovieTrackingContext *context)
850 TrackContext *track_context;
851 MovieTracking *tracking= &context->clip->tracking;
852 MovieTrackingTrack *track;
853 ListBase tracks= {NULL, NULL}, new_tracks= {NULL, NULL};
854 ListBase *old_tracks= &context->clip->tracking.tracks;
857 /* duplicate currently tracking tracks to temporary list.
858 this is needed to keep names in unique state and it's faster to change names
859 of currently tracking tracks (if needed) */
860 for(a= 0, track_context= context->track_context; a<context->num_tracks; a++, track_context++) {
862 MovieTrackingTrack *new_track, *old;
864 track= track_context->track;
866 /* find original of tracking track in list of previously displayed tracks */
867 old= BLI_ghash_lookup(context->hash, track);
869 MovieTrackingTrack *cur= old_tracks->first;
878 /* original track was found, re-use flags and remove this track */
880 if(cur==tracking->act_track)
883 track->flag= cur->flag;
884 track->pat_flag= cur->pat_flag;
885 track->search_flag= cur->search_flag;
887 BKE_tracking_free_track(cur);
888 BLI_freelinkN(old_tracks, cur);
892 new_track= BKE_tracking_copy_track(track);
894 BLI_ghash_remove(context->hash, track, NULL, NULL); /* XXX: are we actually need this */
895 BLI_ghash_insert(context->hash, track, new_track);
897 if(replace_sel) /* update current selection in clip */
898 tracking->act_track= new_track;
900 BLI_addtail(&tracks, new_track);
903 /* move all tracks, which aren't tracking */
904 track= old_tracks->first;
906 MovieTrackingTrack *next= track->next;
908 track->next= track->prev= NULL;
909 BLI_addtail(&new_tracks, track);
914 /* now move all tracks which are currently tracking and keep their names unique */
917 MovieTrackingTrack *next= track->next;
919 BLI_remlink(&tracks, track);
921 track->next= track->prev= NULL;
922 BLI_addtail(&new_tracks, track);
924 BLI_uniquename(&new_tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
929 context->clip->tracking.tracks= new_tracks;
931 if(context->backwards) newframe= context->user.framenr+1;
932 else newframe= context->user.framenr-1;
934 context->sync_frame= newframe;
937 void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context)
939 user->framenr= context->sync_frame;
942 int BKE_tracking_next(MovieTrackingContext *context)
945 int curfra= context->user.framenr;
948 /* nothing to track, avoid unneeded frames reading to save time and memory */
949 if(!context->num_tracks)
952 if(context->backwards) context->user.framenr--;
953 else context->user.framenr++;
955 ibuf_new= BKE_movieclip_acquire_ibuf_flag(context->clip, &context->user, 0);
959 #pragma omp parallel for private(a) shared(ibuf_new, ok) if(context->num_tracks>1)
960 for(a= 0; a<context->num_tracks; a++) {
961 TrackContext *track_context= &context->track_context[a];
962 MovieTrackingTrack *track= track_context->track;
963 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, curfra);
965 if(marker && (marker->flag&MARKER_DISABLED)==0 && marker->framenr==curfra) {
967 int width, height, origin[2], tracked= 0, need_readjust= 0;
968 float pos[2], margin[2];
969 double x1, y1, x2, y2;
971 MovieTrackingMarker marker_new, *marker_keyed;
974 if(!context->settings.adjframes) need_readjust= context->first_time;
975 else need_readjust= context->frames%context->settings.adjframes == 0;
977 /* margin from frame boundaries */
978 sub_v2_v2v2(margin, track->pat_max, track->pat_min);
980 margin[0]= MAX2(margin[0], (float)context->settings.margin / ibuf_new->x);
981 margin[1]= MAX2(margin[1], (float)context->settings.margin / ibuf_new->y);
983 /* do not track markers which are too close to boundary */
984 if(marker->pos[0]<margin[0] || marker->pos[0]>1.f-margin[0] ||
985 marker->pos[1]<margin[1] || marker->pos[1]>1.f-margin[1]) {
988 else if(context->settings.tracker==TRACKER_KLT) {
993 /* calculate patch for keyframed position */
994 ibuf= acquire_adjust_ibuf(context, track, marker, curfra, &marker_keyed);
996 if(track_context->patch)
997 MEM_freeN(track_context->patch);
999 track_context->patch= acquire_search_floatbuf(ibuf, track, marker_keyed, &width, &height, pos, origin);
1001 IMB_freeImBuf(ibuf);
1004 patch_new= acquire_search_floatbuf(ibuf_new, track, marker, &width, &height, pos, origin);
1012 wndx= (int)((track->pat_max[0]-track->pat_min[0])*ibuf_new->x)/2;
1013 wndy= (int)((track->pat_max[1]-track->pat_min[1])*ibuf_new->y)/2;
1015 tracked= libmv_regionTrackerTrack(track_context->region_tracker, track_context->patch, patch_new,
1016 width, height, MAX2(wndx, wndy), x1, y1, &x2, &y2);
1018 MEM_freeN(patch_new);
1020 else if(context->settings.tracker==TRACKER_SAD) {
1021 unsigned char *image_new;
1023 float warp[3][2]={{0}};
1026 unsigned char *image;
1028 /* calculate pattern for keyframed position */
1029 ibuf= acquire_adjust_ibuf(context, track, marker, curfra, &marker_keyed);
1031 image= acquire_search_bytebuf(ibuf, track, marker_keyed, &width, &height, pos, origin);
1033 memset(warp, 0, sizeof(warp));
1039 /* pattern size is hardcoded to 16x16px in libmv */
1040 track_context->patsize= 16;
1042 if(!track_context->pattern)
1043 track_context->pattern= MEM_callocN(sizeof(unsigned char)*track_context->patsize*track_context->patsize, "trackking pattern");
1045 libmv_SADSamplePattern(image, width, warp, track_context->pattern);
1048 IMB_freeImBuf(ibuf);
1051 image_new= acquire_search_bytebuf(ibuf_new, track, marker, &width, &height, pos, origin);
1053 if(track_context->warped==NULL) {
1054 unsigned char *image_old;
1056 ibuf= acquire_frame_ibuf(context, curfra);
1058 if(track_context->warped==NULL)
1059 track_context->warped= MEM_callocN(sizeof(unsigned char)*track_context->patsize*track_context->patsize, "trackking warped");
1061 image_old= acquire_search_bytebuf(ibuf, track, marker, &width, &height, pos, origin);
1062 acquire_warped(track_context, pos[0], pos[1], width, image_old);
1063 IMB_freeImBuf(ibuf);
1064 MEM_freeN(image_old);
1067 memset(warp, 0, sizeof(warp));
1073 corr= libmv_SADTrackerTrack(track_context->pattern, track_context->warped, image_new, width, width, height, warp);
1078 tracked= corr>=context->settings.corr;
1081 acquire_warped(track_context, x2, y2, width, image_new);
1083 MEM_freeN(image_new);
1086 if(tracked || !context->disable_failed) {
1087 if(context->first_time) {
1090 if(context->backwards) prevframe= curfra+1;
1091 else prevframe= curfra-1;
1093 /* check if there's no keyframe/tracked markers before tracking marker.
1094 if so -- create disabled marker before currently tracking "segment" */
1095 if(!BKE_tracking_has_marker(track, prevframe)) {
1096 marker_new= *marker;
1097 marker_new.framenr= prevframe;
1099 marker_new.flag|= MARKER_DISABLED;
1101 #pragma omp critical
1103 BKE_tracking_insert_marker(track, &marker_new);
1108 memset(&marker_new, 0, sizeof(marker_new));
1111 marker_new.pos[0]= (origin[0]+x2)/ibuf_new->x;
1112 marker_new.pos[1]= (origin[1]+y2)/ibuf_new->y;
1114 copy_v2_v2(marker_new.pos, marker->pos);
1117 marker_new.flag|= MARKER_TRACKED;
1119 if(context->backwards) marker_new.framenr= curfra-1;
1120 else marker_new.framenr= curfra+1;
1122 #pragma omp critical
1124 BKE_tracking_insert_marker(track, &marker_new);
1128 marker_new= *marker;
1130 if(context->backwards) marker_new.framenr--;
1131 else marker_new.framenr++;
1133 marker_new.flag|= MARKER_DISABLED;
1135 #pragma omp critical
1137 BKE_tracking_insert_marker(track, &marker_new);
1146 IMB_freeImBuf(ibuf_new);
1148 context->first_time= 0;
1155 static struct libmv_Tracks *create_libmv_tracks(MovieTracking *tracking, int width, int height)
1158 MovieTrackingTrack *track;
1159 struct libmv_Tracks *tracks= libmv_tracksNew();
1161 track= tracking->tracks.first;
1165 for(a= 0; a<track->markersnr; a++) {
1166 MovieTrackingMarker *marker= &track->markers[a];
1168 if((marker->flag&MARKER_DISABLED)==0)
1169 libmv_tracksInsert(tracks, marker->framenr, tracknr,
1170 marker->pos[0]*width, marker->pos[1]*height);
1180 static int retrive_libmv_reconstruct(MovieTracking *tracking, struct libmv_Reconstruction *libmv_reconstruction)
1183 int sfra= INT_MAX, efra= INT_MIN, a, origin_set= 0;
1184 MovieTrackingTrack *track;
1185 MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
1186 MovieReconstructedCamera *reconstructed;
1187 float origin[3]= {0.0f, 0.f, 0.0f};
1190 track= tracking->tracks.first;
1194 if(libmv_reporojectionPointForTrack(libmv_reconstruction, tracknr, pos)) {
1195 track->bundle_pos[0]= pos[0];
1196 track->bundle_pos[1]= pos[1];
1197 track->bundle_pos[2]= pos[2];
1199 track->flag|= TRACK_HAS_BUNDLE;
1200 track->error= libmv_reporojectionErrorForTrack(libmv_reconstruction, tracknr);
1202 track->flag&= ~TRACK_HAS_BUNDLE;
1205 printf("No bundle for track #%d '%s'\n", tracknr, track->name);
1208 if(track->markersnr) {
1209 if(track->markers[0].framenr<sfra) sfra= track->markers[0].framenr;
1210 if(track->markers[track->markersnr-1].framenr>efra) efra= track->markers[track->markersnr-1].framenr;
1217 if(reconstruction->cameras)
1218 MEM_freeN(reconstruction->cameras);
1220 reconstruction->camnr= 0;
1221 reconstruction->cameras= NULL;
1222 reconstructed= MEM_callocN((efra-sfra+1)*sizeof(MovieReconstructedCamera), "temp reconstructed camera");
1224 for(a= sfra; a<=efra; a++) {
1227 if(libmv_reporojectionCameraForImage(libmv_reconstruction, a, matd)) {
1233 mat[i][j]= matd[i][j];
1236 copy_v3_v3(origin, mat[3]);
1241 sub_v3_v3(mat[3], origin);
1243 copy_m4_m4(reconstructed[reconstruction->camnr].mat, mat);
1244 reconstructed[reconstruction->camnr].framenr= a;
1245 reconstruction->camnr++;
1248 printf("No camera for frame %d\n", a);
1252 if(reconstruction->camnr) {
1253 reconstruction->cameras= MEM_callocN(reconstruction->camnr*sizeof(MovieReconstructedCamera), "reconstructed camera");
1254 memcpy(reconstruction->cameras, reconstructed, reconstruction->camnr*sizeof(MovieReconstructedCamera));
1258 track= tracking->tracks.first;
1260 if(track->flag&TRACK_HAS_BUNDLE)
1261 sub_v3_v3(track->bundle_pos, origin);
1267 MEM_freeN(reconstructed);
1274 float BKE_tracking_solve_reconstruction(MovieTracking *tracking, int width, int height)
1278 MovieTrackingCamera *camera= &tracking->camera;
1279 float aspy= 1.f/tracking->camera.pixel_aspect;
1280 struct libmv_Tracks *tracks= create_libmv_tracks(tracking, width, height*aspy);
1281 struct libmv_Reconstruction *reconstruction = libmv_solveReconstruction(tracks,
1282 tracking->settings.keyframe1, tracking->settings.keyframe2,
1284 camera->principal[0], camera->principal[1]*aspy,
1285 camera->k1, camera->k2, camera->k3);
1286 float error= libmv_reprojectionError(reconstruction);
1288 tracking->reconstruction.error= error;
1290 if(!retrive_libmv_reconstruct(tracking, reconstruction))
1293 libmv_destroyReconstruction(reconstruction);
1294 libmv_tracksDestroy(tracks);
1296 tracking->reconstruction.flag|= TRACKING_RECONSTRUCTED;
1303 void BKE_track_unique_name(MovieTracking *tracking, MovieTrackingTrack *track)
1305 BLI_uniquename(&tracking->tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
1308 MovieTrackingTrack *BKE_find_track_by_name(MovieTracking *tracking, const char *name)
1310 MovieTrackingTrack *track= tracking->tracks.first;
1313 if(!strcmp(track->name, name))
1322 static int reconstruction_camera_index(MovieTracking *tracking, int framenr, int nearest)
1324 MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
1325 MovieReconstructedCamera *cameras= reconstruction->cameras;
1328 if(!reconstruction->camnr)
1331 if(framenr<cameras[0].framenr) {
1332 if(nearest) return 0;
1336 if(framenr>cameras[reconstruction->camnr-1].framenr) {
1337 if(nearest) return reconstruction->camnr-1;
1341 if(reconstruction->last_camera<reconstruction->camnr)
1342 a= reconstruction->last_camera;
1344 if(cameras[a].framenr>=framenr)
1347 while(a>=0 && a<reconstruction->camnr) {
1348 int cfra= cameras[a].framenr;
1350 /* check if needed framenr was "skipped" -- no data for requested frame */
1352 if(d>0 && cfra>framenr) {
1353 /* interpolate with previous position */
1354 if(nearest) return a-1;
1358 if(d<0 && cfra<framenr) {
1359 /* interpolate with next position */
1360 if(nearest) return a;
1365 reconstruction->last_camera= a;
1376 MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking, int framenr)
1378 int a= reconstruction_camera_index(tracking, framenr, 0);
1383 return &tracking->reconstruction.cameras[a];
1386 void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, int framenr, float mat[4][4])
1388 MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
1389 MovieReconstructedCamera *cameras= reconstruction->cameras;
1390 int a= reconstruction_camera_index(tracking, framenr, 1);
1397 if(cameras[a].framenr!=framenr && a>0 && a<reconstruction->camnr-1) {
1398 float t= ((float)framenr-cameras[a].framenr) / (cameras[a+1].framenr-cameras[a].framenr);
1400 blend_m4_m4m4(mat, cameras[a].mat, cameras[a+1].mat, t);
1402 copy_m4_m4(mat, cameras[a].mat);
1406 void BKE_get_tracking_mat(Scene *scene, float mat[4][4])
1409 scene->camera= scene_find_camera(scene);
1412 where_is_object_mat(scene, scene->camera, mat);
1417 void BKE_tracking_projection_matrix(MovieTracking *tracking, int framenr, int winx, int winy, float mat[4][4])
1419 MovieReconstructedCamera *camera;
1420 float lens= tracking->camera.focal*tracking->camera.sensor_width/(float)winx;
1421 float viewfac, pixsize, left, right, bottom, top, clipsta, clipend;
1423 float ycor= 1.f/tracking->camera.pixel_aspect;
1429 viewfac= (lens*winx)/tracking->camera.sensor_width;
1431 viewfac= (ycor*lens*winy)/tracking->camera.sensor_width;
1433 pixsize= clipsta/viewfac;
1435 left= -0.5f*(float)winx*pixsize;
1436 bottom= -0.5f*ycor*(float)winy*pixsize;
1437 right= 0.5f*(float)winx*pixsize;
1438 top= 0.5f*ycor*(float)winy*pixsize;
1440 perspective_m4(winmat, left, right, bottom, top, clipsta, clipend);
1442 camera= BKE_tracking_get_reconstructed_camera(tracking, framenr);
1446 invert_m4_m4(imat, camera->mat);
1447 mul_m4_m4m4(mat, imat, winmat);
1448 } else copy_m4_m4(mat, winmat);
1451 void BKE_tracking_apply_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
1453 MovieTrackingCamera *camera= &tracking->camera;
1457 float aspy= 1.f/tracking->camera.pixel_aspect;
1459 /* normalize coords */
1460 x= (co[0]-camera->principal[0]) / camera->focal;
1461 y= (co[1]-camera->principal[1] * aspy) / camera->focal;
1463 libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
1464 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
1466 /* result is in image coords already */
1472 void BKE_tracking_invert_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
1474 MovieTrackingCamera *camera= &tracking->camera;
1477 double x= co[0], y= co[1];
1478 float aspy= 1.f/tracking->camera.pixel_aspect;
1480 libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
1481 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
1483 nco[0]= x * camera->focal + camera->principal[0];
1484 nco[1]= y * camera->focal + camera->principal[1] * aspy;
1489 /* flips upside-down */
1490 static unsigned char *acquire_ucharbuf(ImBuf *ibuf)
1493 unsigned char *pixels, *fp;
1495 fp= pixels= MEM_callocN(ibuf->x*ibuf->y*sizeof(unsigned char), "tracking ucharBuf");
1496 for(y= 0; y<ibuf->y; y++) {
1497 for (x= 0; x<ibuf->x; x++) {
1498 int pixel= ibuf->x*(ibuf->y-y-1) + x;
1500 if(ibuf->rect_float) {
1501 float *rrgbf= ibuf->rect_float + pixel*4;
1503 //*fp= 0.2126f*rrgbf[0] + 0.7152f*rrgbf[1] + 0.0722f*rrgbf[2];
1504 *fp= (11*rrgbf[0]+16*rrgbf[1]+5*rrgbf[2])/32;
1506 char *rrgb= (char*)ibuf->rect + pixel*4;
1508 //*fp= 0.2126f*rrgb[0] + 0.7152f*rrgb[1] + 0.0722f*rrgb[2];
1509 *fp= (11*rrgb[0]+16*rrgb[1]+5*rrgb[2])/32;
1520 void BKE_tracking_detect(MovieTracking *tracking, ImBuf *ibuf, int framenr, int margin, int count, int min_distance)
1523 struct libmv_Features *features;
1524 unsigned char *pixels= acquire_ucharbuf(ibuf);
1527 features= libmv_detectFeatures(pixels, ibuf->x, ibuf->y, ibuf->x, margin, count, min_distance);
1530 a= libmv_countFeatures(features);
1532 MovieTrackingTrack *track;
1533 double x, y, size, score;
1535 libmv_getFeature(features, a, &x, &y, &score, &size);
1537 track= BKE_tracking_add_track(tracking, x/ibuf->x, 1.0f-(y/ibuf->y), framenr, ibuf->x, ibuf->y);
1538 track->flag|= SELECT;
1539 track->pat_flag|= SELECT;
1540 track->search_flag|= SELECT;
1543 libmv_destroyFeatures(features);
1547 MovieTrackingTrack *BKE_tracking_indexed_bundle(MovieTracking *tracking, int bundlenr)
1549 MovieTrackingTrack *track= tracking->tracks.first;
1553 if(track->flag&TRACK_HAS_BUNDLE) {
1566 static int stabilization_median_point(MovieTracking *tracking, int framenr, float median[2])
1569 float min[2], max[2];
1570 MovieTrackingTrack *track;
1572 INIT_MINMAX2(min, max);
1574 track= tracking->tracks.first;
1576 if(track->flag&TRACK_USE_2D_STAB) {
1577 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
1579 DO_MINMAX2(marker->pos, min, max);
1587 median[0]= (max[0]+min[0])/2.f;
1588 median[1]= (max[1]+min[1])/2.f;
1593 static void calculate_stabdata(MovieTracking *tracking, int framenr, float width, float height,
1594 float firstmedian[2], float median[2], float loc[2], float *scale, float *angle)
1596 MovieTrackingStabilization *stab= &tracking->stabilization;
1598 *scale= (stab->scale-1.f)*stab->scaleinf+1.f;
1601 loc[0]= (firstmedian[0]-median[0])*width*(*scale);
1602 loc[1]= (firstmedian[1]-median[1])*height*(*scale);
1604 loc[0]-= (firstmedian[0]*(*scale)-firstmedian[0])*width;
1605 loc[1]-= (firstmedian[1]*(*scale)-firstmedian[1])*height;
1607 mul_v2_fl(loc, stab->locinf);
1609 if(stab->rot_track && stab->rotinf) {
1610 MovieTrackingMarker *marker;
1612 float x0= (float)width/2.f, y0= (float)height/2.f;
1613 float x= median[0]*width, y= median[1]*height;
1615 marker= BKE_tracking_get_marker(stab->rot_track, 1);
1616 sub_v2_v2v2(a, marker->pos, firstmedian);
1620 marker= BKE_tracking_get_marker(stab->rot_track, framenr);
1621 sub_v2_v2v2(b, marker->pos, median);
1625 *angle= -atan2(a[0]*b[1]-a[1]*b[0], a[0]*b[0]+a[1]*b[1]);
1626 *angle*= stab->rotinf;
1628 /* convert to rotation around image center */
1629 loc[0]-= (x0 + (x-x0)*cos(*angle)-(y-y0)*sin(*angle) - x);
1630 loc[1]-= (y0 + (x-x0)*sin(*angle)+(y-y0)*cos(*angle) - y);
1634 static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, int height)
1636 float firstmedian[2];
1637 MovieTrackingStabilization *stab= &tracking->stabilization;
1642 if(stabilization_median_point(tracking, 1, firstmedian)) {
1643 int sfra= INT_MAX, efra= INT_MIN, cfra;
1644 float delta[2]= {0.f, 0.f}, scalex= 1.f, scaley= 1.f;
1645 MovieTrackingTrack *track;
1649 track= tracking->tracks.first;
1651 if(track->flag&TRACK_USE_2D_STAB || track==stab->rot_track) {
1652 if(track->markersnr) {
1653 sfra= MIN2(sfra, track->markers[0].framenr);
1654 efra= MAX2(efra, track->markers[track->markersnr-1].framenr);
1661 for(cfra=sfra; cfra<=efra; cfra++) {
1662 float median[2], near[2];
1663 float loc[2], scale, angle;
1665 stabilization_median_point(tracking, cfra, median);
1667 calculate_stabdata(tracking, cfra, width, height, firstmedian, median,
1668 loc, &scale, &angle);
1671 loc[0]= fabsf(loc[0]);
1672 loc[1]= fabsf(loc[1]);
1674 delta[0]= MAX2(delta[0], loc[0]);
1675 delta[1]= MAX2(delta[1], loc[1]);
1677 near[0]= MIN2(median[0], 1.f-median[0]);
1678 near[1]= MIN2(median[1], 1.f-median[1]);
1679 near[0]= MAX2(near[0], 0.05);
1680 near[1]= MAX2(near[1], 0.05);
1682 scalex= 1.f+delta[0]/(near[0]*width);
1683 scaley= 1.f+delta[1]/(near[1]*height);
1687 float points[4][2]={{0.f, 0.f}, {0.f, height}, {width, height}, {width, 0.f}};
1689 BKE_tracking_stabdata_to_mat4(width, height, loc, scale, angle, mat);
1691 for(i= 0; i<4; i++) {
1693 float a[3]= {0.f}, b[3]= {0.f};
1695 copy_v3_v3(a, points[i]);
1696 copy_v3_v3(b, points[(i+1)%4]);
1701 for(j= 0; j<4; j++) {
1702 float point[3]= {points[j][0], points[j][1], 0.f};
1705 sub_v3_v3v3(v1, b, a);
1706 sub_v3_v3v3(v2, point, a);
1708 if(cross_v2v2(v1, v2) >= 0.f) {
1709 float dist= dist_to_line_v2(point, a, b);
1711 scalex= MAX2(scalex, (width+2*dist)/width);
1713 scaley= MAX2(scaley, (height+2*dist)/height);
1721 stab->scale= MAX2(scalex, scaley);
1723 if(stab->maxscale>0.f)
1724 stab->scale= MIN2(stab->scale, stab->maxscale);
1734 static ImBuf* stabilize_alloc_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill)
1738 if(cacheibuf && (cacheibuf->x != srcibuf->x || cacheibuf->y != srcibuf->y)) {
1739 IMB_freeImBuf(cacheibuf);
1745 if(srcibuf->rect_float)
1746 flags|= IB_rectfloat;
1750 float col[4]= {0.f, 0.f, 0.f, 0.f};
1751 IMB_rectfill(cacheibuf, col);
1755 cacheibuf= IMB_allocImBuf(srcibuf->x, srcibuf->y, srcibuf->depth, flags);
1756 cacheibuf->profile= srcibuf->profile;
1762 void BKE_tracking_stabilization_data(MovieTracking *tracking, int framenr, int width, int height, float loc[2], float *scale, float *angle)
1764 float firstmedian[2], median[2];
1765 MovieTrackingStabilization *stab= &tracking->stabilization;
1767 if((stab->flag&TRACKING_2D_STABILIZATION)==0) {
1775 if(stabilization_median_point(tracking, 1, firstmedian)) {
1776 stabilization_median_point(tracking, framenr, median);
1778 if((stab->flag&TRACKING_AUTOSCALE)==0)
1782 if(stab->flag&TRACKING_AUTOSCALE)
1783 stabilization_auto_scale_factor(tracking, width, height);
1785 calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle);
1789 calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle);
1798 ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, float loc[2], float *scale, float *angle)
1800 float tloc[2], tscale, tangle;
1801 MovieTrackingStabilization *stab= &tracking->stabilization;
1803 float width= ibuf->x, height= ibuf->y;
1805 if(loc) copy_v2_v2(tloc, loc);
1806 if(scale) tscale= *scale;
1808 if((stab->flag&TRACKING_2D_STABILIZATION)==0) {
1809 if(loc) zero_v2(loc);
1810 if(scale) *scale= 1.f;
1815 BKE_tracking_stabilization_data(tracking, framenr, width, height, tloc, &tscale, &tangle);
1817 tmpibuf= stabilize_alloc_ibuf(NULL, ibuf, 1);
1819 /* scale would be handled by matrix transformation when angle is non-zero */
1820 if(tscale!=1.f && tangle==0.f) {
1822 float scale= (stab->scale-1.f)*stab->scaleinf+1.f;
1824 stabilization_auto_scale_factor(tracking, width, height);
1826 scaleibuf= stabilize_alloc_ibuf(stab->scaleibuf, ibuf, 0);
1827 stab->scaleibuf= scaleibuf;
1829 IMB_rectcpy(scaleibuf, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y);
1830 IMB_scalefastImBuf(scaleibuf, ibuf->x*scale, ibuf->y*scale);
1836 /* if angle is zero, then it's much faster to use rect copy
1837 but could be issues with subpixel precisions */
1838 IMB_rectcpy(tmpibuf, ibuf, tloc[0], tloc[1], 0, 0, ibuf->x, ibuf->y);
1843 BKE_tracking_stabdata_to_mat4(ibuf->x, ibuf->y, tloc, tscale, tangle, mat);
1846 for(j=0; j<tmpibuf->y; j++) {
1847 for(i=0; i<tmpibuf->x;i++) {
1848 float vec[3]= {i, j, 0};
1850 mul_v3_m4v3(vec, mat, vec);
1852 /* TODO: add selector for interpolation method */
1853 neareast_interpolation(ibuf, tmpibuf, vec[0], vec[1], i, j);
1858 tmpibuf->userflags|= IB_MIPMAP_INVALID;
1860 if(tmpibuf->rect_float)
1861 tmpibuf->userflags|= IB_RECT_INVALID;
1863 if(loc) copy_v2_v2(loc, tloc);
1864 if(scale) *scale= tscale;
1865 if(angle) *angle= tangle;
1870 void BKE_tracking_stabdata_to_mat4(int width, int height, float loc[2], float scale, float angle, float mat[4][4])
1872 float lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4];
1873 float svec[3]= {scale, scale, scale};
1880 /* image center as rotation center */
1881 cmat[3][0]= (float)width/2.f;
1882 cmat[3][1]= (float)height/2.f;
1883 invert_m4_m4(icmat, cmat);
1885 size_to_mat4(smat, svec); /* scale matrix */
1886 add_v2_v2(lmat[3], loc); /* tranlation matrix */
1887 rotate_m4(rmat, 'Z', angle); /* rotation matrix */
1889 /* compose transformation matrix */
1890 mul_serie_m4(mat, lmat, smat, cmat, rmat, icmat, NULL, NULL, NULL);
1893 ImBuf *BKE_tracking_undistort(MovieTracking *tracking, ImBuf *ibuf)
1896 MovieTrackingCamera *camera= &tracking->camera;
1897 float aspy= 1.f/tracking->camera.pixel_aspect;
1899 resibuf= IMB_dupImBuf(ibuf);
1901 if(ibuf->rect_float) {
1902 libmv_undistortFloat(camera->focal,
1903 camera->principal[0], camera->principal[1] * aspy,
1904 camera->k1, camera->k2, camera->k3,
1905 ibuf->rect_float, resibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels);
1907 ibuf->userflags|= IB_RECT_INVALID;
1909 libmv_undistortByte(camera->focal,
1910 camera->principal[0], camera->principal[1] * aspy,
1911 camera->k1, camera->k2, camera->k3,
1912 (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect, ibuf->x, ibuf->y, ibuf->channels);
1918 ImBuf *BKE_tracking_distort(MovieTracking *tracking, ImBuf *ibuf)
1921 MovieTrackingCamera *camera= &tracking->camera;
1922 float aspy= 1.f/tracking->camera.pixel_aspect;
1924 resibuf= IMB_dupImBuf(ibuf);
1926 if(ibuf->rect_float) {
1927 libmv_distortFloat(camera->focal,
1928 camera->principal[0], camera->principal[1] * aspy,
1929 camera->k1, camera->k2, camera->k3,
1930 ibuf->rect_float, resibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels);
1932 ibuf->userflags|= IB_RECT_INVALID;
1934 libmv_distortByte(camera->focal,
1935 camera->principal[0], camera->principal[1] * aspy,
1936 camera->k1, camera->k2, camera->k3,
1937 (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect, ibuf->x, ibuf->y, ibuf->channels);