Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2011 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * Contributor(s): Blender Foundation, 00022 * Sergey Sharybin 00023 * 00024 * ***** END GPL LICENSE BLOCK ***** 00025 */ 00026 00031 #include <stddef.h> 00032 #include <limits.h> 00033 #include <math.h> 00034 #include <memory.h> 00035 00036 #include "MEM_guardedalloc.h" 00037 00038 #include "DNA_gpencil_types.h" 00039 #include "DNA_camera_types.h" 00040 #include "DNA_movieclip_types.h" 00041 #include "DNA_object_types.h" /* SELECT */ 00042 #include "DNA_scene_types.h" 00043 00044 #include "BLI_utildefines.h" 00045 #include "BLI_math.h" 00046 #include "BLI_math_base.h" 00047 #include "BLI_listbase.h" 00048 #include "BLI_ghash.h" 00049 #include "BLI_path_util.h" 00050 #include "BLI_string.h" 00051 #include "BLI_threads.h" 00052 00053 #include "BKE_global.h" 00054 #include "BKE_tracking.h" 00055 #include "BKE_movieclip.h" 00056 #include "BKE_object.h" 00057 #include "BKE_scene.h" 00058 #include "BKE_main.h" // XXX: ... 00059 00060 #include "IMB_imbuf_types.h" 00061 #include "IMB_imbuf.h" 00062 00063 #ifdef WITH_LIBMV 00064 # include "libmv-capi.h" 00065 #else 00066 struct libmv_Features; 00067 #endif 00068 00069 typedef struct MovieDistortion { 00070 struct libmv_CameraIntrinsics *intrinsics; 00071 } MovieDistortion; 00072 00073 static struct { 00074 ListBase tracks; 00075 } tracking_clipboard; 00076 00077 /*********************** common functions *************************/ 00078 00079 void BKE_tracking_init_settings(MovieTracking *tracking) 00080 { 00081 tracking->camera.sensor_width= 35.0f; 00082 tracking->camera.pixel_aspect= 1.0f; 00083 tracking->camera.units= CAMERA_UNITS_MM; 00084 00085 tracking->settings.default_tracker= TRACKER_HYBRID; 00086 tracking->settings.default_minimum_correlation= 0.75; 00087 tracking->settings.default_pattern_size= 11; 00088 tracking->settings.default_search_size= 51; 00089 tracking->settings.default_pyramid_levels= 2; 00090 tracking->settings.keyframe1= 1; 00091 tracking->settings.keyframe2= 30; 00092 tracking->settings.dist= 1; 00093 tracking->settings.object_distance= 1; 00094 00095 tracking->stabilization.scaleinf= 1.0f; 00096 tracking->stabilization.locinf= 1.0f; 00097 tracking->stabilization.rotinf= 1.0f; 00098 tracking->stabilization.maxscale= 2.0f; 00099 00100 BKE_tracking_new_object(tracking, "Camera"); 00101 } 00102 00103 void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event) 00104 { 00105 int a; 00106 float pat_min[2]; 00107 float pat_max[2]; 00108 float max_pyramid_level_factor = 1.0; 00109 00110 if (track->tracker == TRACKER_KLT) { 00111 max_pyramid_level_factor= 1 << (track->pyramid_levels - 1); 00112 } 00113 00114 /* sort */ 00115 for(a= 0; a<2; a++) { 00116 if(track->pat_min[a]>track->pat_max[a]) 00117 SWAP(float, track->pat_min[a], track->pat_max[a]); 00118 00119 if(track->search_min[a]>track->search_max[a]) 00120 SWAP(float, track->search_min[a], track->search_max[a]); 00121 } 00122 00123 /* compute the effective pattern size, which differs from the fine resolution 00124 * pattern size for the pyramid KLT tracker */ 00125 for(a= 0; a<2; a++) { 00126 pat_min[a] = max_pyramid_level_factor * track->pat_min[a]; 00127 pat_max[a] = max_pyramid_level_factor * track->pat_max[a]; 00128 } 00129 00130 if(event==CLAMP_PAT_DIM) { 00131 for(a= 0; a<2; a++) { 00132 /* search shouldn't be resized smaller than pattern */ 00133 track->search_min[a]= MIN2(pat_min[a], track->search_min[a]); 00134 track->search_max[a]= MAX2(pat_max[a], track->search_max[a]); 00135 } 00136 } 00137 else if(event==CLAMP_PAT_POS) { 00138 float dim[2]; 00139 sub_v2_v2v2(dim, track->pat_max, track->pat_min); 00140 00141 for(a= 0; a<2; a++) { 00142 /* pattern shouldn't be moved outside of search */ 00143 if(pat_min[a] < track->search_min[a]) { 00144 track->pat_min[a]= track->search_min[a] - (pat_min[a] - track->pat_min[a]); 00145 track->pat_max[a]= track->pat_min[a] + dim[a]; 00146 } 00147 if(track->pat_max[a] > track->search_max[a]) { 00148 track->pat_max[a]= track->search_max[a] - (pat_max[a] - track->pat_max[a]); 00149 track->pat_min[a]= track->pat_max[a] - dim[a]; 00150 } 00151 } 00152 } 00153 else if(event==CLAMP_SEARCH_DIM) { 00154 for(a= 0; a<2; a++) { 00155 /* search shouldn't be resized smaller than pattern */ 00156 track->search_min[a]= MIN2(pat_min[a], track->search_min[a]); 00157 track->search_max[a]= MAX2(pat_max[a], track->search_max[a]); 00158 } 00159 } 00160 else if(event==CLAMP_SEARCH_POS) { 00161 float dim[2]; 00162 sub_v2_v2v2(dim, track->search_max, track->search_min); 00163 00164 for(a= 0; a<2; a++) { 00165 /* search shouldn't be moved inside pattern */ 00166 if(track->search_min[a] > pat_min[a]) { 00167 track->search_min[a]= pat_min[a]; 00168 track->search_max[a]= track->search_min[a]+dim[a]; 00169 } 00170 if(track->search_max[a] < pat_max[a]) { 00171 track->search_max[a]= pat_max[a]; 00172 track->search_min[a]= track->search_max[a]-dim[a]; 00173 } 00174 } 00175 } 00176 else if(event==CLAMP_PYRAMID_LEVELS || (event==CLAMP_SEARCH_DIM && track->tracker == TRACKER_KLT)) { 00177 float dim[2]; 00178 sub_v2_v2v2(dim, track->pat_max, track->pat_min); 00179 { 00180 float search_ratio= 2.3f * max_pyramid_level_factor; 00181 00182 /* resize the search area to something sensible based 00183 * on the number of pyramid levels */ 00184 for(a= 0; a<2; a++) { 00185 track->search_min[a]= search_ratio * track->pat_min[a]; 00186 track->search_max[a]= search_ratio * track->pat_max[a]; 00187 } 00188 } 00189 } 00190 00191 /* marker's center should be in center of pattern */ 00192 if(event==CLAMP_PAT_DIM || event==CLAMP_PAT_POS) { 00193 float dim[2]; 00194 sub_v2_v2v2(dim, track->pat_max, track->pat_min); 00195 00196 for(a= 0; a<2; a++) { 00197 track->pat_min[a]= -dim[a]/2.0f; 00198 track->pat_max[a]= dim[a]/2.0f; 00199 } 00200 } 00201 } 00202 00203 void BKE_tracking_track_flag(MovieTrackingTrack *track, int area, int flag, int clear) 00204 { 00205 if(area==TRACK_AREA_NONE) 00206 return; 00207 00208 if(clear) { 00209 if(area&TRACK_AREA_POINT) track->flag&= ~flag; 00210 if(area&TRACK_AREA_PAT) track->pat_flag&= ~flag; 00211 if(area&TRACK_AREA_SEARCH) track->search_flag&= ~flag; 00212 } else { 00213 if(area&TRACK_AREA_POINT) track->flag|= flag; 00214 if(area&TRACK_AREA_PAT) track->pat_flag|= flag; 00215 if(area&TRACK_AREA_SEARCH) track->search_flag|= flag; 00216 } 00217 } 00218 00219 MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tracksbase, float x, float y, 00220 int framenr, int width, int height) 00221 { 00222 MovieTrackingTrack *track; 00223 MovieTrackingMarker marker; 00224 MovieTrackingSettings *settings= &tracking->settings; 00225 00226 float half_pattern= (float)settings->default_pattern_size/2.0f; 00227 float half_search= (float)settings->default_search_size/2.0f; 00228 float pat[2], search[2]; 00229 00230 pat[0]= half_pattern/(float)width; 00231 pat[1]= half_pattern/(float)height; 00232 00233 search[0]= half_search/(float)width; 00234 search[1]= half_search/(float)height; 00235 00236 track= MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track"); 00237 strcpy(track->name, "Track"); 00238 00239 track->tracker= settings->default_tracker; 00240 track->pyramid_levels= settings->default_pyramid_levels; 00241 track->minimum_correlation= settings->default_minimum_correlation; 00242 track->margin= settings->default_margin; 00243 track->pattern_match= settings->default_pattern_match; 00244 track->frames_limit= settings->default_frames_limit; 00245 00246 memset(&marker, 0, sizeof(marker)); 00247 marker.pos[0]= x; 00248 marker.pos[1]= y; 00249 marker.framenr= framenr; 00250 00251 copy_v2_v2(track->pat_max, pat); 00252 negate_v2_v2(track->pat_min, pat); 00253 00254 copy_v2_v2(track->search_max, search); 00255 negate_v2_v2(track->search_min, search); 00256 00257 BKE_tracking_insert_marker(track, &marker); 00258 00259 if(track->tracker == TRACKER_KLT) 00260 BKE_tracking_clamp_track(track, CLAMP_PYRAMID_LEVELS); 00261 00262 BLI_addtail(tracksbase, track); 00263 BKE_track_unique_name(tracksbase, track); 00264 00265 return track; 00266 } 00267 00268 MovieTrackingMarker *BKE_tracking_insert_marker(MovieTrackingTrack *track, MovieTrackingMarker *marker) 00269 { 00270 MovieTrackingMarker *old_marker= NULL; 00271 00272 if(track->markersnr) 00273 old_marker= BKE_tracking_exact_marker(track, marker->framenr); 00274 00275 if(old_marker) { 00276 *old_marker= *marker; 00277 00278 return old_marker; 00279 } else { 00280 int a= track->markersnr; 00281 00282 while(a--) { 00283 if(track->markers[a].framenr<marker->framenr) 00284 break; 00285 } 00286 00287 track->markersnr++; 00288 00289 if(track->markers) track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr); 00290 else track->markers= MEM_callocN(sizeof(MovieTrackingMarker), "MovieTracking markers"); 00291 00292 memmove(track->markers+a+2, track->markers+a+1, (track->markersnr-a-2)*sizeof(MovieTrackingMarker)); 00293 track->markers[a+1]= *marker; 00294 00295 track->last_marker= a+1; 00296 00297 return &track->markers[a+1]; 00298 } 00299 } 00300 00301 void BKE_tracking_delete_marker(MovieTrackingTrack *track, int framenr) 00302 { 00303 int a= 0; 00304 00305 while(a<track->markersnr) { 00306 if(track->markers[a].framenr==framenr) { 00307 if(track->markersnr>1) { 00308 memmove(track->markers+a, track->markers+a+1, (track->markersnr-a-1)*sizeof(MovieTrackingMarker)); 00309 track->markersnr--; 00310 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr); 00311 } else { 00312 MEM_freeN(track->markers); 00313 track->markers= NULL; 00314 track->markersnr= 0; 00315 } 00316 00317 break; 00318 } 00319 00320 a++; 00321 } 00322 } 00323 00324 MovieTrackingMarker *BKE_tracking_get_marker(MovieTrackingTrack *track, int framenr) 00325 { 00326 int a= track->markersnr-1; 00327 00328 if(!track->markersnr) 00329 return NULL; 00330 00331 /* approximate pre-first framenr marker with first marker */ 00332 if(framenr<track->markers[0].framenr) 00333 return &track->markers[0]; 00334 00335 if(track->last_marker<track->markersnr) 00336 a= track->last_marker; 00337 00338 if(track->markers[a].framenr<=framenr) { 00339 while(a<track->markersnr && track->markers[a].framenr<=framenr) { 00340 if(track->markers[a].framenr==framenr) { 00341 track->last_marker= a; 00342 return &track->markers[a]; 00343 } 00344 a++; 00345 } 00346 00347 /* if there's no marker for exact position, use nearest marker from left side */ 00348 return &track->markers[a-1]; 00349 } else { 00350 while(a>=0 && track->markers[a].framenr>=framenr) { 00351 if(track->markers[a].framenr==framenr) { 00352 track->last_marker= a; 00353 return &track->markers[a]; 00354 } 00355 00356 a--; 00357 } 00358 00359 /* if there's no marker for exact position, use nearest marker from left side */ 00360 return &track->markers[a]; 00361 } 00362 00363 return NULL; 00364 } 00365 00366 MovieTrackingMarker *BKE_tracking_ensure_marker(MovieTrackingTrack *track, int framenr) 00367 { 00368 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr); 00369 00370 if(marker->framenr!=framenr) { 00371 MovieTrackingMarker marker_new; 00372 00373 marker_new= *marker; 00374 marker_new.framenr= framenr; 00375 00376 BKE_tracking_insert_marker(track, &marker_new); 00377 marker= BKE_tracking_get_marker(track, framenr); 00378 } 00379 00380 return marker; 00381 } 00382 00383 MovieTrackingMarker *BKE_tracking_exact_marker(MovieTrackingTrack *track, int framenr) 00384 { 00385 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr); 00386 00387 if(marker->framenr!=framenr) 00388 return NULL; 00389 00390 return marker; 00391 } 00392 00393 int BKE_tracking_has_marker(MovieTrackingTrack *track, int framenr) 00394 { 00395 return BKE_tracking_exact_marker(track, framenr) != 0; 00396 } 00397 00398 void BKE_tracking_free_track(MovieTrackingTrack *track) 00399 { 00400 if(track->markers) MEM_freeN(track->markers); 00401 } 00402 00403 static void put_disabled_marker(MovieTrackingTrack *track, MovieTrackingMarker *ref_marker, int before, int overwrite) 00404 { 00405 MovieTrackingMarker marker_new; 00406 00407 marker_new= *ref_marker; 00408 marker_new.flag&= ~MARKER_TRACKED; 00409 marker_new.flag|= MARKER_DISABLED; 00410 00411 if(before) marker_new.framenr--; 00412 else marker_new.framenr++; 00413 00414 if(!BKE_tracking_has_marker(track, marker_new.framenr) || overwrite) 00415 BKE_tracking_insert_marker(track, &marker_new); 00416 } 00417 00418 void BKE_tracking_clear_path(MovieTrackingTrack *track, int ref_frame, int action) 00419 { 00420 int a; 00421 00422 if(action==TRACK_CLEAR_REMAINED) { 00423 a= 1; 00424 while(a<track->markersnr) { 00425 if(track->markers[a].framenr>ref_frame) { 00426 track->markersnr= a; 00427 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr); 00428 00429 break; 00430 } 00431 00432 a++; 00433 } 00434 00435 if(track->markersnr) 00436 put_disabled_marker(track, &track->markers[track->markersnr-1], 0, 1); 00437 } else if(action==TRACK_CLEAR_UPTO) { 00438 a= track->markersnr-1; 00439 while(a>=0) { 00440 if(track->markers[a].framenr<=ref_frame) { 00441 memmove(track->markers, track->markers+a, (track->markersnr-a)*sizeof(MovieTrackingMarker)); 00442 00443 track->markersnr= track->markersnr-a; 00444 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr); 00445 00446 break; 00447 } 00448 00449 a--; 00450 } 00451 00452 if(track->markersnr) 00453 put_disabled_marker(track, &track->markers[0], 1, 1); 00454 } else if(action==TRACK_CLEAR_ALL) { 00455 MovieTrackingMarker *marker, marker_new; 00456 00457 marker= BKE_tracking_get_marker(track, ref_frame); 00458 marker_new= *marker; 00459 00460 MEM_freeN(track->markers); 00461 track->markers= NULL; 00462 track->markersnr= 0; 00463 00464 BKE_tracking_insert_marker(track, &marker_new); 00465 00466 put_disabled_marker(track, &marker_new, 1, 1); 00467 put_disabled_marker(track, &marker_new, 0, 1); 00468 } 00469 } 00470 00471 int BKE_tracking_test_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track) 00472 { 00473 int a= 0, b= 0; 00474 int count= 0; 00475 00476 while(a<src_track->markersnr || b<dst_track->markersnr) { 00477 if(b>=dst_track->markersnr) { 00478 a++; 00479 count++; 00480 } 00481 else if(a>=src_track->markersnr) { 00482 b++; 00483 count++; 00484 } 00485 else if(src_track->markers[a].framenr<dst_track->markers[b].framenr) { 00486 a++; 00487 count++; 00488 } else if(src_track->markers[a].framenr>dst_track->markers[b].framenr) { 00489 b++; 00490 count++; 00491 } else { 00492 if((src_track->markers[a].flag&MARKER_DISABLED)==0 && (dst_track->markers[b].flag&MARKER_DISABLED)==0) 00493 return 0; 00494 00495 a++; 00496 b++; 00497 count++; 00498 } 00499 } 00500 00501 return count; 00502 } 00503 00504 void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track) 00505 { 00506 int i, a= 0, b= 0, tot; 00507 MovieTrackingMarker *markers; 00508 00509 tot= BKE_tracking_test_join_tracks(dst_track, src_track); 00510 00511 markers= MEM_callocN(tot*sizeof(MovieTrackingMarker), "tracking joined tracks"); 00512 00513 for(i= 0; i<tot; i++) { 00514 if(b>=dst_track->markersnr) { 00515 markers[i]= src_track->markers[a++]; 00516 } 00517 else if(a>=src_track->markersnr) { 00518 markers[i]= dst_track->markers[b++]; 00519 } 00520 else if(src_track->markers[a].framenr<dst_track->markers[b].framenr) { 00521 markers[i]= src_track->markers[a++]; 00522 } else if(src_track->markers[a].framenr>dst_track->markers[b].framenr) { 00523 markers[i]= dst_track->markers[b++]; 00524 } else { 00525 if((src_track->markers[a].flag&MARKER_DISABLED)) markers[i]= dst_track->markers[b]; 00526 else markers[i]= src_track->markers[a++]; 00527 00528 a++; 00529 b++; 00530 } 00531 } 00532 00533 MEM_freeN(dst_track->markers); 00534 00535 dst_track->markers= markers; 00536 dst_track->markersnr= tot; 00537 } 00538 00539 static void tracking_tracks_free(ListBase *tracks) 00540 { 00541 MovieTrackingTrack *track; 00542 00543 for(track= tracks->first; track; track= track->next) { 00544 BKE_tracking_free_track(track); 00545 } 00546 00547 BLI_freelistN(tracks); 00548 } 00549 00550 static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruction) 00551 { 00552 if(reconstruction->cameras) 00553 MEM_freeN(reconstruction->cameras); 00554 } 00555 00556 static void tracking_object_free(MovieTrackingObject *object) 00557 { 00558 tracking_tracks_free(&object->tracks); 00559 tracking_reconstruction_free(&object->reconstruction); 00560 } 00561 00562 static void tracking_objects_free(ListBase *objects) 00563 { 00564 MovieTrackingObject *object; 00565 00566 for(object= objects->first; object; object= object->next) 00567 tracking_object_free(object); 00568 00569 BLI_freelistN(objects); 00570 } 00571 00572 void BKE_tracking_free(MovieTracking *tracking) 00573 { 00574 tracking_tracks_free(&tracking->tracks); 00575 tracking_reconstruction_free(&tracking->reconstruction); 00576 tracking_objects_free(&tracking->objects); 00577 00578 if(tracking->stabilization.scaleibuf) 00579 IMB_freeImBuf(tracking->stabilization.scaleibuf); 00580 00581 if(tracking->camera.intrinsics) 00582 BKE_tracking_distortion_destroy(tracking->camera.intrinsics); 00583 } 00584 00585 static MovieTrackingTrack *duplicate_track(MovieTrackingTrack *track) 00586 { 00587 MovieTrackingTrack *new_track; 00588 00589 new_track = MEM_callocN(sizeof(MovieTrackingTrack), "tracksMapMerge new_track"); 00590 00591 *new_track= *track; 00592 new_track->next = new_track->prev = NULL; 00593 00594 new_track->markers = MEM_dupallocN(new_track->markers); 00595 00596 return new_track; 00597 } 00598 00599 /*********************** clipboard *************************/ 00600 00601 void BKE_tracking_free_clipboard(void) 00602 { 00603 MovieTrackingTrack *track = tracking_clipboard.tracks.first, *next_track; 00604 00605 while (track) { 00606 next_track = track->next; 00607 00608 BKE_tracking_free_track(track); 00609 MEM_freeN(track); 00610 00611 track = next_track; 00612 } 00613 } 00614 00615 void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingObject *object) 00616 { 00617 ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); 00618 MovieTrackingTrack *track = tracksbase->first; 00619 00620 while (track) { 00621 if (TRACK_SELECTED(track)) { 00622 MovieTrackingTrack *new_track = duplicate_track(track); 00623 00624 BLI_addtail(&tracking_clipboard.tracks, new_track); 00625 } 00626 00627 track = track->next; 00628 } 00629 } 00630 00631 int BKE_tracking_clipboard_has_tracks(void) 00632 { 00633 return tracking_clipboard.tracks.first != NULL; 00634 } 00635 00636 void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingObject *object) 00637 { 00638 ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); 00639 MovieTrackingTrack *track = tracking_clipboard.tracks.first; 00640 00641 while (track) { 00642 MovieTrackingTrack *new_track = duplicate_track(track); 00643 00644 BLI_addtail(tracksbase, new_track); 00645 BKE_track_unique_name(tracksbase, new_track); 00646 00647 track = track->next; 00648 } 00649 } 00650 00651 /*********************** tracks map *************************/ 00652 00653 typedef struct TracksMap { 00654 char object_name[MAX_NAME]; 00655 int is_camera; 00656 00657 int num_tracks; 00658 int customdata_size; 00659 00660 char *customdata; 00661 MovieTrackingTrack *tracks; 00662 00663 GHash *hash; 00664 00665 int ptr; 00666 } TracksMap; 00667 00668 static TracksMap *tracks_map_new(const char *object_name, int is_camera, int num_tracks, int customdata_size) 00669 { 00670 TracksMap *map= MEM_callocN(sizeof(TracksMap), "TrackingsMap"); 00671 00672 BLI_strncpy(map->object_name, object_name, sizeof(map->object_name)); 00673 map->is_camera= is_camera; 00674 00675 map->num_tracks= num_tracks; 00676 map->customdata_size= customdata_size; 00677 00678 map->tracks= MEM_callocN(sizeof(MovieTrackingTrack)*num_tracks, "TrackingsMap tracks"); 00679 00680 if(customdata_size) 00681 map->customdata= MEM_callocN(customdata_size*num_tracks, "TracksMap customdata"); 00682 00683 map->hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "TracksMap hash"); 00684 00685 return map; 00686 } 00687 00688 static int tracks_map_size(TracksMap *map) 00689 { 00690 return map->num_tracks; 00691 } 00692 00693 static void tracks_map_get(TracksMap *map, int index, MovieTrackingTrack **track, void **customdata) 00694 { 00695 *track= &map->tracks[index]; 00696 00697 if(map->customdata) 00698 *customdata= &map->customdata[index*map->customdata_size]; 00699 } 00700 00701 static void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *customdata) 00702 { 00703 MovieTrackingTrack new_track= *track; 00704 00705 new_track.markers= MEM_dupallocN(new_track.markers); 00706 00707 map->tracks[map->ptr]= new_track; 00708 00709 if(customdata) 00710 memcpy(&map->customdata[map->ptr*map->customdata_size], customdata, map->customdata_size); 00711 00712 BLI_ghash_insert(map->hash, &map->tracks[map->ptr], track); 00713 00714 map->ptr++; 00715 } 00716 00717 static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) 00718 { 00719 MovieTrackingTrack *track; 00720 MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking); 00721 ListBase tracks= {NULL, NULL}, new_tracks= {NULL, NULL}; 00722 ListBase *old_tracks; 00723 int a; 00724 00725 if(map->is_camera) { 00726 old_tracks= &tracking->tracks; 00727 } else { 00728 MovieTrackingObject *object= BKE_tracking_named_object(tracking, map->object_name); 00729 00730 if(!object) { 00731 /* object was deleted by user, create new one */ 00732 object= BKE_tracking_new_object(tracking, map->object_name); 00733 } 00734 00735 old_tracks= &object->tracks; 00736 } 00737 00738 /* duplicate currently operating tracks to temporary list. 00739 this is needed to keep names in unique state and it's faster to change names 00740 of currently operating tracks (if needed) */ 00741 for(a= 0; a<map->num_tracks; a++) { 00742 int replace_sel= 0; 00743 MovieTrackingTrack *new_track, *old; 00744 00745 track= &map->tracks[a]; 00746 00747 /* find original of operating track in list of previously displayed tracks */ 00748 old= BLI_ghash_lookup(map->hash, track); 00749 if(old) { 00750 MovieTrackingTrack *cur= old_tracks->first; 00751 00752 while(cur) { 00753 if(cur==old) 00754 break; 00755 00756 cur= cur->next; 00757 } 00758 00759 /* original track was found, re-use flags and remove this track */ 00760 if(cur) { 00761 if(act_track) 00762 replace_sel= 1; 00763 00764 track->flag= cur->flag; 00765 track->pat_flag= cur->pat_flag; 00766 track->search_flag= cur->search_flag; 00767 00768 BKE_tracking_free_track(cur); 00769 BLI_freelinkN(old_tracks, cur); 00770 } 00771 } 00772 00773 new_track= duplicate_track(track); 00774 00775 BLI_ghash_remove(map->hash, track, NULL, NULL); /* XXX: are we actually need this */ 00776 BLI_ghash_insert(map->hash, track, new_track); 00777 00778 if(replace_sel) /* update current selection in clip */ 00779 tracking->act_track= new_track; 00780 00781 BLI_addtail(&tracks, new_track); 00782 } 00783 00784 /* move all tracks, which aren't operating */ 00785 track= old_tracks->first; 00786 while(track) { 00787 MovieTrackingTrack *next= track->next; 00788 00789 track->next= track->prev= NULL; 00790 BLI_addtail(&new_tracks, track); 00791 00792 track= next; 00793 } 00794 00795 /* now move all tracks which are currently operating and keep their names unique */ 00796 track= tracks.first; 00797 while(track) { 00798 MovieTrackingTrack *next= track->next; 00799 00800 BLI_remlink(&tracks, track); 00801 00802 track->next= track->prev= NULL; 00803 BLI_addtail(&new_tracks, track); 00804 00805 BLI_uniquename(&new_tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name)); 00806 00807 track= next; 00808 } 00809 00810 *old_tracks= new_tracks; 00811 } 00812 00813 static void tracks_map_free(TracksMap *map, void (*customdata_free) (void *customdata)) 00814 { 00815 int i= 0; 00816 00817 BLI_ghash_free(map->hash, NULL, NULL); 00818 00819 for(i= 0; i<map->num_tracks; i++) { 00820 if(map->customdata && customdata_free) 00821 customdata_free(&map->customdata[i*map->customdata_size]); 00822 00823 BKE_tracking_free_track(&map->tracks[i]); 00824 } 00825 00826 if(map->customdata) 00827 MEM_freeN(map->customdata); 00828 00829 MEM_freeN(map->tracks); 00830 MEM_freeN(map); 00831 } 00832 00833 /*********************** tracking *************************/ 00834 00835 typedef struct TrackContext { 00836 #ifdef WITH_LIBMV 00837 float keyframed_pos[2]; 00838 00839 /* ** KLT tracker ** */ 00840 struct libmv_RegionTracker *region_tracker; 00841 float *patch; /* keyframed patch */ 00842 00843 /* ** SAD tracker ** */ 00844 int pattern_size; /* size of pattern */ 00845 unsigned char *pattern; /* keyframed pattern */ 00846 unsigned char *warped; /* warped version of reference */ 00847 #else 00848 int pad; 00849 #endif 00850 } TrackContext; 00851 00852 typedef struct MovieTrackingContext { 00853 MovieClipUser user; 00854 MovieClip *clip; 00855 int clip_flag; 00856 00857 int first_time, frames; 00858 00859 MovieTrackingSettings settings; 00860 TracksMap *tracks_map; 00861 00862 short backwards, sequence; 00863 int sync_frame; 00864 } MovieTrackingContext; 00865 00866 MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, short backwards, short sequence) 00867 { 00868 MovieTrackingContext *context= MEM_callocN(sizeof(MovieTrackingContext), "trackingContext"); 00869 MovieTracking *tracking= &clip->tracking; 00870 MovieTrackingSettings *settings= &tracking->settings; 00871 ListBase *tracksbase= BKE_tracking_get_tracks(tracking); 00872 MovieTrackingTrack *track; 00873 MovieTrackingObject *object= BKE_tracking_active_object(tracking); 00874 int num_tracks= 0; 00875 00876 context->settings= *settings; 00877 context->backwards= backwards; 00878 context->sync_frame= user->framenr; 00879 context->first_time= 1; 00880 context->sequence= sequence; 00881 00882 /* count */ 00883 track= tracksbase->first; 00884 while(track) { 00885 if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) { 00886 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr); 00887 00888 if((marker->flag&MARKER_DISABLED)==0) 00889 num_tracks++; 00890 } 00891 00892 track= track->next; 00893 } 00894 00895 if(num_tracks) { 00896 int width, height; 00897 00898 context->tracks_map= tracks_map_new(object->name, object->flag & TRACKING_OBJECT_CAMERA, 00899 num_tracks, sizeof(TrackContext)); 00900 00901 BKE_movieclip_get_size(clip, user, &width, &height); 00902 00903 /* create tracking data */ 00904 track= tracksbase->first; 00905 while(track) { 00906 if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) { 00907 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr); 00908 00909 if((marker->flag&MARKER_DISABLED)==0) { 00910 TrackContext track_context; 00911 00912 memset(&track_context, 0, sizeof(TrackContext)); 00913 00914 #ifdef WITH_LIBMV 00915 { 00916 float patx, paty; 00917 patx= (int)((track->pat_max[0]-track->pat_min[0])*width); 00918 paty= (int)((track->pat_max[1]-track->pat_min[1])*height); 00919 00920 if(ELEM(track->tracker, TRACKER_KLT, TRACKER_HYBRID)) { 00921 float search_size_x= (track->search_max[0]-track->search_min[0])*width; 00922 float search_size_y= (track->search_max[1]-track->search_min[1])*height; 00923 float pattern_size_x= (track->pat_max[0]-track->pat_min[0])*width; 00924 float pattern_size_y= (track->pat_max[1]-track->pat_min[1])*height; 00925 int wndx= (int)patx/2, wndy= (int)paty/2; 00926 00927 /* compute the maximum pyramid size */ 00928 float search_to_pattern_ratio= MIN2(search_size_x, search_size_y) 00929 / MAX2(pattern_size_x, pattern_size_y); 00930 float log2_search_to_pattern_ratio = log(floor(search_to_pattern_ratio)) / M_LN2; 00931 int max_pyramid_levels= floor(log2_search_to_pattern_ratio + 1); 00932 00933 /* try to accomodate the user's choice of pyramid level in a way 00934 * that doesn't cause the coarsest pyramid pattern to be larger 00935 * than the search size */ 00936 int level= MIN2(track->pyramid_levels, max_pyramid_levels); 00937 00938 if(track->tracker==TRACKER_KLT) 00939 track_context.region_tracker= libmv_pyramidRegionTrackerNew(100, level, MAX2(wndx, wndy), track->minimum_correlation); 00940 else 00941 track_context.region_tracker= libmv_hybridRegionTrackerNew(100, MAX2(wndx, wndy), track->minimum_correlation); 00942 } 00943 else if(track->tracker==TRACKER_SAD) { 00944 track_context.pattern_size= MAX2(patx, paty); 00945 } 00946 } 00947 #endif 00948 00949 tracks_map_insert(context->tracks_map, track, &track_context); 00950 } 00951 } 00952 00953 track= track->next; 00954 } 00955 } 00956 00957 context->clip= clip; 00958 00959 /* store needed clip flags passing to get_buffer functions 00960 * - MCLIP_USE_PROXY is needed to because timecode affects on movie clip 00961 * only in case Proxy/Timecode flag is set, so store this flag to use 00962 * timecodes properly but reset render size to SIZE_FULL so correct resolution 00963 * would be used for images 00964 * - MCLIP_USE_PROXY_CUSTOM_DIR is needed because proxy/timecode files might 00965 * be stored in a different location 00966 * ignore all the rest pssible flags for now */ 00967 context->clip_flag= clip->flag&MCLIP_TIMECODE_FLAGS; 00968 00969 context->user= *user; 00970 context->user.render_size= 0; 00971 context->user.render_flag= MCLIP_PROXY_RENDER_SIZE_FULL; 00972 00973 if(!sequence) 00974 BLI_begin_threaded_malloc(); 00975 00976 return context; 00977 } 00978 00979 static void track_context_free(void *customdata) 00980 { 00981 TrackContext *track_context= (TrackContext *)customdata; 00982 00983 #if WITH_LIBMV 00984 if(track_context->region_tracker) 00985 libmv_regionTrackerDestroy(track_context->region_tracker); 00986 00987 if(track_context->patch) 00988 MEM_freeN(track_context->patch); 00989 00990 if(track_context->pattern) 00991 MEM_freeN(track_context->pattern); 00992 00993 if(track_context->warped) 00994 MEM_freeN(track_context->warped); 00995 #else 00996 (void) track_context; 00997 #endif 00998 } 00999 01000 void BKE_tracking_context_free(MovieTrackingContext *context) 01001 { 01002 if(!context->sequence) 01003 BLI_end_threaded_malloc(); 01004 01005 tracks_map_free(context->tracks_map, track_context_free); 01006 01007 MEM_freeN(context); 01008 } 01009 01010 /* zap channels from the imbuf that are disabled by the user. this can lead to 01011 * better tracks sometimes. however, instead of simply zeroing the channels 01012 * out, do a partial grayscale conversion so the display is better. */ 01013 void BKE_tracking_disable_imbuf_channels(ImBuf *ibuf, int disable_red, int disable_green, int disable_blue, int grayscale) 01014 { 01015 int x, y; 01016 float scale; 01017 01018 if(!disable_red && !disable_green && !disable_blue && !grayscale) 01019 return; 01020 01021 /* If only some components are selected, it's important to rescale the result 01022 * appropriately so that e.g. if only blue is selected, it's not zeroed out. */ 01023 scale = (disable_red ? 0.0f : 0.2126f) + 01024 (disable_green ? 0.0f : 0.7152f) + 01025 (disable_blue ? 0.0f : 0.0722f); 01026 01027 for(y= 0; y<ibuf->y; y++) { 01028 for (x= 0; x<ibuf->x; x++) { 01029 int pixel= ibuf->x*y + x; 01030 01031 if(ibuf->rect_float) { 01032 float *rrgbf= ibuf->rect_float + pixel*4; 01033 float r = disable_red ? 0.0f : rrgbf[0]; 01034 float g = disable_green ? 0.0f : rrgbf[1]; 01035 float b = disable_blue ? 0.0f : rrgbf[2]; 01036 if (grayscale) { 01037 float gray = (0.2126f*r + 0.7152f*g + 0.0722f*b) / scale; 01038 rrgbf[0] = rrgbf[1] = rrgbf[2] = gray; 01039 } else { 01040 rrgbf[0] = r; 01041 rrgbf[1] = g; 01042 rrgbf[2] = b; 01043 } 01044 } else { 01045 char *rrgb= (char*)ibuf->rect + pixel*4; 01046 char r = disable_red ? 0 : rrgb[0]; 01047 char g = disable_green ? 0 : rrgb[1]; 01048 char b = disable_blue ? 0 : rrgb[2]; 01049 if (grayscale) { 01050 float gray = (0.2126f*r + 0.7152f*g + 0.0722f*b) / scale; 01051 rrgb[0] = rrgb[1] = rrgb[2] = gray; 01052 } else { 01053 rrgb[0] = r; 01054 rrgb[1] = g; 01055 rrgb[2] = b; 01056 } 01057 } 01058 } 01059 } 01060 } 01061 01062 static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale) 01063 { 01064 BKE_tracking_disable_imbuf_channels(ibuf, track->flag&TRACK_DISABLE_RED, 01065 track->flag&TRACK_DISABLE_GREEN, track->flag&TRACK_DISABLE_RED, grayscale); 01066 } 01067 01068 static ImBuf *get_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, 01069 float min[2], float max[2], int margin, int anchored, float pos[2], int origin[2]) 01070 { 01071 ImBuf *tmpibuf; 01072 int x, y; 01073 int x1, y1, w, h; 01074 float mpos[2]; 01075 01076 copy_v2_v2(mpos, marker->pos); 01077 if(anchored) 01078 add_v2_v2(mpos, track->offset); 01079 01080 if(pos) 01081 zero_v2(pos); 01082 01083 x= mpos[0]*ibuf->x; 01084 y= mpos[1]*ibuf->y; 01085 01086 w= (max[0]-min[0])*ibuf->x; 01087 h= (max[1]-min[1])*ibuf->y; 01088 01089 w= w|1; 01090 h= h|1; 01091 01092 x1= x-(int)(w/2.0f); 01093 y1= y-(int)(h/2.0f); 01094 01095 /* dimensions should be odd */ 01096 tmpibuf= IMB_allocImBuf(w+margin*2, h+margin*2, 32, IB_rect); 01097 IMB_rectcpy(tmpibuf, ibuf, 0, 0, x1-margin, y1-margin, w+margin*2, h+margin*2); 01098 01099 if(pos != NULL) { 01100 pos[0]= mpos[0]*ibuf->x-x1+margin; 01101 pos[1]= mpos[1]*ibuf->y-y1+margin; 01102 } 01103 01104 if(origin != NULL) { 01105 origin[0]= x1-margin; 01106 origin[1]= y1-margin; 01107 } 01108 01109 if((track->flag & TRACK_PREVIEW_GRAYSCALE) || 01110 (track->flag & TRACK_DISABLE_RED) || 01111 (track->flag & TRACK_DISABLE_GREEN) || 01112 (track->flag & TRACK_DISABLE_BLUE)) 01113 { 01114 disable_imbuf_channels(tmpibuf, track, 1 /* grayscale */); 01115 } 01116 01117 return tmpibuf; 01118 } 01119 01120 ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, 01121 int margin, int anchored, float pos[2], int origin[2]) 01122 { 01123 return get_area_imbuf(ibuf, track, marker, track->pat_min, track->pat_max, margin, anchored, pos, origin); 01124 } 01125 01126 ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, 01127 int margin, int anchored, float pos[2], int origin[2]) 01128 { 01129 return get_area_imbuf(ibuf, track, marker, track->search_min, track->search_max, margin, anchored, pos, origin); 01130 } 01131 01132 #ifdef WITH_LIBMV 01133 static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, 01134 int *width_r, int *height_r, float pos[2], int origin[2]) 01135 { 01136 ImBuf *tmpibuf; 01137 float *pixels, *fp; 01138 int x, y, width, height; 01139 01140 width= (track->search_max[0]-track->search_min[0])*ibuf->x; 01141 height= (track->search_max[1]-track->search_min[1])*ibuf->y; 01142 01143 tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin); 01144 disable_imbuf_channels(tmpibuf, track, 0 /* don't grayscale */); 01145 01146 *width_r= width; 01147 *height_r= height; 01148 01149 fp= pixels= MEM_callocN(width*height*sizeof(float), "tracking floatBuf"); 01150 for(y= 0; y<(int)height; y++) { 01151 for (x= 0; x<(int)width; x++) { 01152 int pixel= tmpibuf->x*y + x; 01153 01154 if(tmpibuf->rect_float) { 01155 float *rrgbf= tmpibuf->rect_float + pixel*4; 01156 *fp= 0.2126*rrgbf[0] + 0.7152*rrgbf[1] + 0.0722*rrgbf[2]; 01157 } else { 01158 unsigned char *rrgb= (unsigned char*)tmpibuf->rect + pixel*4; 01159 *fp= (0.2126*rrgb[0] + 0.7152*rrgb[1] + 0.0722*rrgb[2])/255.0f; 01160 } 01161 fp++; 01162 } 01163 } 01164 01165 IMB_freeImBuf(tmpibuf); 01166 01167 return pixels; 01168 } 01169 01170 static unsigned char *get_ucharbuf(ImBuf *ibuf) 01171 { 01172 int x, y; 01173 unsigned char *pixels, *cp; 01174 01175 cp= pixels= MEM_callocN(ibuf->x*ibuf->y*sizeof(unsigned char), "tracking ucharBuf"); 01176 for(y= 0; y<ibuf->y; y++) { 01177 for (x= 0; x<ibuf->x; x++) { 01178 int pixel= ibuf->x*y + x; 01179 01180 if(ibuf->rect_float) { 01181 const float *rrgbf= ibuf->rect_float + pixel*4; 01182 const float grey_f= 0.2126f*rrgbf[0] + 0.7152f*rrgbf[1] + 0.0722f*rrgbf[2]; 01183 *cp= FTOCHAR(grey_f); 01184 } else { 01185 const unsigned char *rrgb= (unsigned char*)ibuf->rect + pixel*4; 01186 *cp= 0.2126f*rrgb[0] + 0.7152f*rrgb[1] + 0.0722f*rrgb[2]; 01187 } 01188 cp++; 01189 } 01190 } 01191 01192 return pixels; 01193 } 01194 01195 static unsigned char *get_search_bytebuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, 01196 int *width_r, int *height_r, float pos[2], int origin[2]) 01197 { 01198 ImBuf *tmpibuf; 01199 unsigned char *pixels; 01200 01201 tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin); 01202 disable_imbuf_channels(tmpibuf, track, 0 /* don't grayscale */); 01203 01204 *width_r= tmpibuf->x; 01205 *height_r= tmpibuf->y; 01206 01207 pixels= get_ucharbuf(tmpibuf); 01208 01209 IMB_freeImBuf(tmpibuf); 01210 01211 return pixels; 01212 } 01213 01214 static ImBuf *get_frame_ibuf(MovieTrackingContext *context, int framenr) 01215 { 01216 ImBuf *ibuf; 01217 MovieClipUser user= context->user; 01218 01219 user.framenr= framenr; 01220 01221 ibuf= BKE_movieclip_get_ibuf_flag(context->clip, &user, context->clip_flag); 01222 01223 return ibuf; 01224 } 01225 01226 static ImBuf *get_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, 01227 MovieTrackingMarker *marker, MovieTrackingMarker **marker_keyed) 01228 { 01229 int framenr= marker->framenr; 01230 int a= marker-track->markers; 01231 01232 *marker_keyed= marker; 01233 01234 while(a>=0 && a<track->markersnr) { 01235 int next= (context->backwards) ? a+1 : a-1; 01236 int is_keyframed= 0; 01237 MovieTrackingMarker *cur_marker= &track->markers[a]; 01238 MovieTrackingMarker *next_marker= NULL; 01239 01240 if(next>=0 && next<track->markersnr) 01241 next_marker= &track->markers[next]; 01242 01243 /* if next mrker is disabled, stop searching keyframe and use current frame as keyframe */ 01244 if(next_marker && next_marker->flag&MARKER_DISABLED) 01245 is_keyframed= 1; 01246 01247 is_keyframed|= (cur_marker->flag&MARKER_TRACKED)==0; 01248 01249 if(is_keyframed) { 01250 framenr= cur_marker->framenr; 01251 *marker_keyed= cur_marker; 01252 break; 01253 } 01254 01255 a= next; 01256 } 01257 01258 return get_frame_ibuf(context, framenr); 01259 } 01260 01261 static ImBuf *get_adjust_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, MovieTrackingMarker *marker, 01262 int curfra, MovieTrackingMarker **marker_keyed) 01263 { 01264 ImBuf *ibuf= NULL; 01265 01266 if(track->pattern_match == TRACK_MATCH_KEYFRAME) { 01267 ibuf= get_keyframed_ibuf(context, track, marker, marker_keyed); 01268 } else { 01269 ibuf= get_frame_ibuf(context, curfra); 01270 01271 /* use current marker as keyframed position */ 01272 *marker_keyed= marker; 01273 } 01274 01275 return ibuf; 01276 } 01277 01278 static void get_warped(TrackContext *track_context, int x, int y, int width, unsigned char *image) 01279 { 01280 int i, j; 01281 01282 for(i=0; i<track_context->pattern_size; i++) { 01283 for(j=0; j<track_context->pattern_size; j++) { 01284 track_context->warped[i*track_context->pattern_size+j]= 01285 image[(y+i-track_context->pattern_size/2)*width+x+j-track_context->pattern_size/2]; 01286 } 01287 } 01288 } 01289 01290 #endif 01291 01292 void BKE_tracking_sync(MovieTrackingContext *context) 01293 { 01294 MovieTracking *tracking= &context->clip->tracking; 01295 int newframe; 01296 01297 tracks_map_merge(context->tracks_map, tracking); 01298 01299 if(context->backwards) newframe= context->user.framenr+1; 01300 else newframe= context->user.framenr-1; 01301 01302 context->sync_frame= newframe; 01303 } 01304 01305 void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context) 01306 { 01307 user->framenr= context->sync_frame; 01308 } 01309 01310 int BKE_tracking_next(MovieTrackingContext *context) 01311 { 01312 ImBuf *ibuf_new; 01313 int curfra= context->user.framenr; 01314 int a, ok= 0, map_size; 01315 01316 map_size= tracks_map_size(context->tracks_map); 01317 01318 /* nothing to track, avoid unneeded frames reading to save time and memory */ 01319 if(!map_size) 01320 return 0; 01321 01322 if(context->backwards) context->user.framenr--; 01323 else context->user.framenr++; 01324 01325 ibuf_new= BKE_movieclip_get_ibuf_flag(context->clip, &context->user, context->clip_flag); 01326 if(!ibuf_new) 01327 return 0; 01328 01329 #pragma omp parallel for private(a) shared(ibuf_new, ok) if(map_size>1) 01330 for(a= 0; a<map_size; a++) { 01331 TrackContext *track_context = NULL; 01332 MovieTrackingTrack *track; 01333 MovieTrackingMarker *marker; 01334 01335 tracks_map_get(context->tracks_map, a, &track, (void**)&track_context); 01336 01337 marker= BKE_tracking_exact_marker(track, curfra); 01338 01339 if(marker && (marker->flag&MARKER_DISABLED)==0) { 01340 #ifdef WITH_LIBMV 01341 int width, height, origin[2], tracked= 0, need_readjust= 0; 01342 float pos[2], margin[2], dim[2]; 01343 double x1, y1, x2, y2; 01344 ImBuf *ibuf= NULL; 01345 MovieTrackingMarker marker_new, *marker_keyed; 01346 int onbound= 0, nextfra; 01347 01348 if(track->pattern_match==TRACK_MATCH_KEYFRAME) 01349 need_readjust= context->first_time; 01350 else 01351 need_readjust= 1; 01352 01353 if(context->backwards) nextfra= curfra-1; 01354 else nextfra= curfra+1; 01355 01356 /* margin from frame boundaries */ 01357 sub_v2_v2v2(dim, track->pat_max, track->pat_min); 01358 margin[0]= margin[1]= MAX2(dim[0], dim[1]) / 2.0f; 01359 01360 margin[0]= MAX2(margin[0], (float)track->margin / ibuf_new->x); 01361 margin[1]= MAX2(margin[1], (float)track->margin / ibuf_new->y); 01362 01363 /* do not track markers which are too close to boundary */ 01364 if(marker->pos[0]<margin[0] || marker->pos[0]>1.0f-margin[0] || 01365 marker->pos[1]<margin[1] || marker->pos[1]>1.0f-margin[1]) { 01366 onbound= 1; 01367 } 01368 else if(ELEM(track->tracker, TRACKER_KLT, TRACKER_HYBRID)) { 01369 float *patch_new; 01370 01371 if(need_readjust) { 01372 /* calculate patch for keyframed position */ 01373 ibuf= get_adjust_ibuf(context, track, marker, curfra, &marker_keyed); 01374 01375 if(track_context->patch) 01376 MEM_freeN(track_context->patch); 01377 01378 track_context->patch= get_search_floatbuf(ibuf, track, marker_keyed, &width, &height, track_context->keyframed_pos, origin); 01379 01380 IMB_freeImBuf(ibuf); 01381 } 01382 01383 patch_new= get_search_floatbuf(ibuf_new, track, marker, &width, &height, pos, origin); 01384 01385 x1= track_context->keyframed_pos[0]; 01386 y1= track_context->keyframed_pos[1]; 01387 01388 x2= pos[0]; 01389 y2= pos[1]; 01390 01391 tracked= libmv_regionTrackerTrack(track_context->region_tracker, track_context->patch, patch_new, 01392 width, height, x1, y1, &x2, &y2); 01393 01394 MEM_freeN(patch_new); 01395 } 01396 else if(track->tracker==TRACKER_SAD) { 01397 unsigned char *image_new; 01398 float correlation; 01399 float warp[3][2]={{0}}; 01400 01401 if(need_readjust) { 01402 unsigned char *image; 01403 01404 /* calculate pattern for keyframed position */ 01405 ibuf= get_adjust_ibuf(context, track, marker, curfra, &marker_keyed); 01406 01407 image= get_search_bytebuf(ibuf, track, marker_keyed, &width, &height, pos, origin); 01408 01409 memset(warp, 0, sizeof(warp)); 01410 warp[0][0]= 1; 01411 warp[1][1]= 1; 01412 warp[2][0]= pos[0]; 01413 warp[2][1]= pos[1]; 01414 01415 if(!track_context->pattern) { 01416 int square= track_context->pattern_size*track_context->pattern_size; 01417 track_context->pattern= MEM_callocN(sizeof(unsigned char)*square, "trackking pattern"); 01418 } 01419 01420 libmv_SADSamplePattern(image, width, warp, track_context->pattern, track_context->pattern_size); 01421 01422 MEM_freeN(image); 01423 IMB_freeImBuf(ibuf); 01424 } 01425 01426 image_new= get_search_bytebuf(ibuf_new, track, marker, &width, &height, pos, origin); 01427 01428 if(track_context->warped==NULL) { 01429 unsigned char *image_old; 01430 01431 ibuf= get_frame_ibuf(context, curfra); 01432 01433 if(track_context->warped==NULL) { 01434 int square= track_context->pattern_size*track_context->pattern_size; 01435 track_context->warped= MEM_callocN(sizeof(unsigned char)*square, "trackking warped"); 01436 } 01437 01438 image_old= get_search_bytebuf(ibuf, track, marker, &width, &height, pos, origin); 01439 get_warped(track_context, pos[0], pos[1], width, image_old); 01440 IMB_freeImBuf(ibuf); 01441 MEM_freeN(image_old); 01442 } 01443 01444 memset(warp, 0, sizeof(warp)); 01445 warp[0][0]= 1; 01446 warp[1][1]= 1; 01447 warp[2][0]= pos[0]; 01448 warp[2][1]= pos[1]; 01449 01450 correlation= libmv_SADTrackerTrack(track_context->pattern, track_context->warped, 01451 track_context->pattern_size, image_new, width, width, height, warp); 01452 01453 x2= warp[2][0]; 01454 y2= warp[2][1]; 01455 01456 tracked= track->minimum_correlation < correlation; 01457 01458 if(tracked) 01459 get_warped(track_context, x2, y2, width, image_new); 01460 01461 MEM_freeN(image_new); 01462 } 01463 01464 if(tracked && !onbound && finite(x2) && finite(y2)) { 01465 if(context->first_time) { 01466 #pragma omp critical 01467 { 01468 /* check if there's no keyframe/tracked markers before tracking marker. 01469 if so -- create disabled marker before currently tracking "segment" */ 01470 put_disabled_marker(track, marker, !context->backwards, 0); 01471 } 01472 } 01473 01474 memset(&marker_new, 0, sizeof(marker_new)); 01475 01476 if(!onbound) { 01477 marker_new.pos[0]= (origin[0]+x2)/ibuf_new->x; 01478 marker_new.pos[1]= (origin[1]+y2)/ibuf_new->y; 01479 } else { 01480 copy_v2_v2(marker_new.pos, marker->pos); 01481 } 01482 01483 marker_new.flag|= MARKER_TRACKED; 01484 marker_new.framenr= nextfra; 01485 01486 #pragma omp critical 01487 { 01488 BKE_tracking_insert_marker(track, &marker_new); 01489 } 01490 01491 /* make currently tracked segment be finished with disabled marker */ 01492 #pragma omp critical 01493 { 01494 put_disabled_marker(track, &marker_new, context->backwards, 0); 01495 } 01496 } else { 01497 marker_new= *marker; 01498 01499 marker_new.framenr= nextfra; 01500 marker_new.flag|= MARKER_DISABLED; 01501 01502 #pragma omp critical 01503 { 01504 BKE_tracking_insert_marker(track, &marker_new); 01505 } 01506 } 01507 01508 ok= 1; 01509 #endif 01510 } 01511 } 01512 01513 IMB_freeImBuf(ibuf_new); 01514 01515 context->first_time= 0; 01516 context->frames++; 01517 01518 return ok; 01519 } 01520 01521 /*********************** camera solving *************************/ 01522 01523 typedef struct MovieReconstructContext { 01524 #ifdef WITH_LIBMV 01525 struct libmv_Tracks *tracks; 01526 int keyframe1, keyframe2; 01527 short refine_flags; 01528 01529 struct libmv_Reconstruction *reconstruction; 01530 #endif 01531 char object_name[MAX_NAME]; 01532 int is_camera; 01533 01534 float focal_length; 01535 float principal_point[2]; 01536 float k1, k2, k3; 01537 01538 float reprojection_error; 01539 01540 TracksMap *tracks_map; 01541 01542 int sfra, efra; 01543 } MovieReconstructContext; 01544 01545 typedef struct ReconstructProgressData { 01546 short *stop; 01547 short *do_update; 01548 float *progress; 01549 char *stats_message; 01550 int message_size; 01551 } ReconstructProgressData; 01552 01553 #if WITH_LIBMV 01554 static struct libmv_Tracks *create_libmv_tracks(ListBase *tracksbase, int width, int height) 01555 { 01556 int tracknr= 0; 01557 MovieTrackingTrack *track; 01558 struct libmv_Tracks *tracks= libmv_tracksNew(); 01559 01560 track= tracksbase->first; 01561 while(track) { 01562 int a= 0; 01563 01564 for(a= 0; a<track->markersnr; a++) { 01565 MovieTrackingMarker *marker= &track->markers[a]; 01566 01567 if((marker->flag&MARKER_DISABLED)==0) 01568 libmv_tracksInsert(tracks, marker->framenr, tracknr, 01569 marker->pos[0]*width, marker->pos[1]*height); 01570 } 01571 01572 track= track->next; 01573 tracknr++; 01574 } 01575 01576 return tracks; 01577 } 01578 01579 static void retrieve_libmv_reconstruct_intrinscis(MovieReconstructContext *context, MovieTracking *tracking) 01580 { 01581 struct libmv_Reconstruction *libmv_reconstruction= context->reconstruction; 01582 struct libmv_CameraIntrinsics *libmv_intrinsics = libmv_ReconstructionExtractIntrinsics(libmv_reconstruction); 01583 01584 float aspy= 1.0f/tracking->camera.pixel_aspect; 01585 01586 double focal_length, principal_x, principal_y, k1, k2, k3; 01587 int width, height; 01588 01589 libmv_CameraIntrinsicsExtract(libmv_intrinsics, &focal_length, &principal_x, &principal_y, 01590 &k1, &k2, &k3, &width, &height); 01591 01592 tracking->camera.focal= focal_length; 01593 tracking->camera.principal[0]= principal_x; 01594 01595 /* todo: verify divide by aspy is correct */ 01596 tracking->camera.principal[1]= principal_y / aspy; 01597 tracking->camera.k1= k1; 01598 tracking->camera.k2= k2; 01599 } 01600 01601 static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, MovieTracking *tracking) 01602 { 01603 struct libmv_Reconstruction *libmv_reconstruction= context->reconstruction; 01604 MovieTrackingReconstruction *reconstruction= NULL; 01605 MovieReconstructedCamera *reconstructed; 01606 MovieTrackingTrack *track; 01607 ListBase *tracksbase= NULL; 01608 int ok= 1, tracknr= 0, a, origin_set= 0; 01609 int sfra= context->sfra, efra= context->efra; 01610 float imat[4][4]; 01611 01612 if(context->is_camera) { 01613 tracksbase= &tracking->tracks; 01614 reconstruction= &tracking->reconstruction; 01615 } 01616 else { 01617 MovieTrackingObject *object= BKE_tracking_named_object(tracking, context->object_name); 01618 01619 tracksbase= &object->tracks; 01620 reconstruction= &object->reconstruction; 01621 } 01622 01623 unit_m4(imat); 01624 01625 track= tracksbase->first; 01626 while(track) { 01627 double pos[3]; 01628 01629 if(libmv_reporojectionPointForTrack(libmv_reconstruction, tracknr, pos)) { 01630 track->bundle_pos[0]= pos[0]; 01631 track->bundle_pos[1]= pos[1]; 01632 track->bundle_pos[2]= pos[2]; 01633 01634 track->flag|= TRACK_HAS_BUNDLE; 01635 track->error= libmv_reporojectionErrorForTrack(libmv_reconstruction, tracknr); 01636 } else { 01637 track->flag&= ~TRACK_HAS_BUNDLE; 01638 ok= 0; 01639 01640 printf("No bundle for track #%d '%s'\n", tracknr, track->name); 01641 } 01642 01643 track= track->next; 01644 tracknr++; 01645 } 01646 01647 if(reconstruction->cameras) 01648 MEM_freeN(reconstruction->cameras); 01649 01650 reconstruction->camnr= 0; 01651 reconstruction->cameras= NULL; 01652 reconstructed= MEM_callocN((efra-sfra+1)*sizeof(MovieReconstructedCamera), "temp reconstructed camera"); 01653 01654 for(a= sfra; a<=efra; a++) { 01655 double matd[4][4]; 01656 01657 if(libmv_reporojectionCameraForImage(libmv_reconstruction, a, matd)) { 01658 int i, j; 01659 float mat[4][4]; 01660 float error= libmv_reporojectionErrorForImage(libmv_reconstruction, a); 01661 01662 for(i=0; i<4; i++) 01663 for(j= 0; j<4; j++) 01664 mat[i][j]= matd[i][j]; 01665 01666 if(!origin_set) { 01667 copy_m4_m4(imat, mat); 01668 invert_m4(imat); 01669 origin_set= 1; 01670 } 01671 01672 if(origin_set) 01673 mult_m4_m4m4(mat, imat, mat); 01674 01675 copy_m4_m4(reconstructed[reconstruction->camnr].mat, mat); 01676 reconstructed[reconstruction->camnr].framenr= a; 01677 reconstructed[reconstruction->camnr].error= error; 01678 reconstruction->camnr++; 01679 } else { 01680 ok= 0; 01681 printf("No camera for frame %d\n", a); 01682 } 01683 } 01684 01685 if(reconstruction->camnr) { 01686 reconstruction->cameras= MEM_callocN(reconstruction->camnr*sizeof(MovieReconstructedCamera), "reconstructed camera"); 01687 memcpy(reconstruction->cameras, reconstructed, reconstruction->camnr*sizeof(MovieReconstructedCamera)); 01688 } 01689 01690 if(origin_set) { 01691 track= tracksbase->first; 01692 while(track) { 01693 if(track->flag&TRACK_HAS_BUNDLE) 01694 mul_v3_m4v3(track->bundle_pos, imat, track->bundle_pos); 01695 01696 track= track->next; 01697 } 01698 } 01699 01700 MEM_freeN(reconstructed); 01701 01702 return ok; 01703 } 01704 01705 static int retrieve_libmv_reconstruct(MovieReconstructContext *context, MovieTracking *tracking) 01706 { 01707 /* take the intrinscis back from libmv */ 01708 retrieve_libmv_reconstruct_intrinscis(context, tracking); 01709 01710 return retrieve_libmv_reconstruct_tracks(context, tracking); 01711 } 01712 01713 static int get_refine_intrinsics_flags(MovieTracking *tracking, MovieTrackingObject *object) 01714 { 01715 int refine= tracking->settings.refine_camera_intrinsics; 01716 int flags= 0; 01717 01718 if((object->flag&TRACKING_OBJECT_CAMERA)==0) 01719 return 0; 01720 01721 if(refine&REFINE_FOCAL_LENGTH) 01722 flags|= LIBMV_REFINE_FOCAL_LENGTH; 01723 01724 if(refine&REFINE_PRINCIPAL_POINT) 01725 flags|= LIBMV_REFINE_PRINCIPAL_POINT; 01726 01727 if(refine&REFINE_RADIAL_DISTORTION_K1) 01728 flags|= REFINE_RADIAL_DISTORTION_K1; 01729 01730 if(refine&REFINE_RADIAL_DISTORTION_K2) 01731 flags|= REFINE_RADIAL_DISTORTION_K2; 01732 01733 return flags; 01734 } 01735 01736 static int count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tracksbase) 01737 { 01738 int tot= 0; 01739 int frame1= tracking->settings.keyframe1, frame2= tracking->settings.keyframe2; 01740 MovieTrackingTrack *track; 01741 01742 track= tracksbase->first; 01743 while(track) { 01744 if(BKE_tracking_has_marker(track, frame1)) 01745 if(BKE_tracking_has_marker(track, frame2)) 01746 tot++; 01747 01748 track= track->next; 01749 } 01750 01751 return tot; 01752 } 01753 #endif 01754 01755 int BKE_tracking_can_reconstruct(MovieTracking *tracking, MovieTrackingObject *object, char *error_msg, int error_size) 01756 { 01757 #if WITH_LIBMV 01758 ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object); 01759 01760 if(count_tracks_on_both_keyframes(tracking, tracksbase)<8) { 01761 BLI_strncpy(error_msg, "At least 8 tracks on both of keyframes are needed for reconstruction", error_size); 01762 return 0; 01763 } 01764 01765 return 1; 01766 #else 01767 BLI_strncpy(error_msg, "Blender is compiled without motion tracking library", error_size); 01768 (void)tracking; 01769 (void)object; 01770 01771 return 0; 01772 #endif 01773 } 01774 01775 MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking *tracking, 01776 MovieTrackingObject *object, int keyframe1, int keyframe2, int width, int height) 01777 { 01778 MovieReconstructContext *context= MEM_callocN(sizeof(MovieReconstructContext), "MovieReconstructContext data"); 01779 MovieTrackingCamera *camera= &tracking->camera; 01780 ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object); 01781 float aspy= 1.0f/tracking->camera.pixel_aspect; 01782 int num_tracks= BLI_countlist(tracksbase); 01783 int sfra= INT_MAX, efra= INT_MIN; 01784 MovieTrackingTrack *track; 01785 01786 BLI_strncpy(context->object_name, object->name, sizeof(context->object_name)); 01787 context->is_camera = object->flag&TRACKING_OBJECT_CAMERA; 01788 01789 context->tracks_map= tracks_map_new(context->object_name, context->is_camera, num_tracks, 0); 01790 01791 track= tracksbase->first; 01792 while(track) { 01793 int first= 0, last= track->markersnr-1; 01794 MovieTrackingMarker *first_marker= &track->markers[0]; 01795 MovieTrackingMarker *last_marker= &track->markers[track->markersnr-1]; 01796 01797 /* find first not-disabled marker */ 01798 while(first<=track->markersnr-1 && first_marker->flag&MARKER_DISABLED) { 01799 first++; 01800 first_marker++; 01801 } 01802 01803 /* find last not-disabled marker */ 01804 while(last>=0 && last_marker->flag&MARKER_DISABLED) { 01805 last--; 01806 last_marker--; 01807 } 01808 01809 if(first<track->markersnr-1) 01810 sfra= MIN2(sfra, first_marker->framenr); 01811 01812 if(last>=0) 01813 efra= MAX2(efra, last_marker->framenr); 01814 01815 tracks_map_insert(context->tracks_map, track, NULL); 01816 01817 track= track->next; 01818 } 01819 01820 context->sfra= sfra; 01821 context->efra= efra; 01822 01823 #ifdef WITH_LIBMV 01824 context->tracks= create_libmv_tracks(tracksbase, width, height*aspy); 01825 context->keyframe1= keyframe1; 01826 context->keyframe2= keyframe2; 01827 context->refine_flags= get_refine_intrinsics_flags(tracking, object); 01828 #else 01829 (void) width; 01830 (void) height; 01831 (void) keyframe1; 01832 (void) keyframe2; 01833 #endif 01834 01835 context->focal_length= camera->focal; 01836 context->principal_point[0]= camera->principal[0]; 01837 context->principal_point[1]= camera->principal[1]*aspy; 01838 01839 context->k1= camera->k1; 01840 context->k2= camera->k2; 01841 context->k2= camera->k2; 01842 01843 return context; 01844 } 01845 01846 void BKE_tracking_reconstruction_context_free(MovieReconstructContext *context) 01847 { 01848 #ifdef WITH_LIBMV 01849 if(context->reconstruction) 01850 libmv_destroyReconstruction(context->reconstruction); 01851 01852 libmv_tracksDestroy(context->tracks); 01853 #endif 01854 01855 tracks_map_free(context->tracks_map, NULL); 01856 01857 MEM_freeN(context); 01858 } 01859 01860 #ifdef WITH_LIBMV 01861 static void solve_reconstruction_update_cb(void *customdata, double progress, const char *message) 01862 { 01863 ReconstructProgressData *progressdata= customdata; 01864 01865 if(progressdata->progress) { 01866 *progressdata->progress= progress; 01867 *progressdata->do_update= 1; 01868 } 01869 01870 BLI_snprintf(progressdata->stats_message, progressdata->message_size, 01871 "Solving camera | %s", message); 01872 } 01873 #endif 01874 01875 #if 0 01876 static int solve_reconstruction_testbreak_cb(void *customdata) 01877 { 01878 ReconstructProgressData *progressdata= customdata; 01879 01880 if(progressdata->stop && *progressdata->stop) 01881 return 1; 01882 01883 return G.afbreek; 01884 } 01885 #endif 01886 01887 void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short *stop, 01888 short *do_update, float *progress, char *stats_message, int message_size) 01889 { 01890 #ifdef WITH_LIBMV 01891 float error; 01892 01893 ReconstructProgressData progressdata; 01894 01895 progressdata.stop= stop; 01896 progressdata.do_update= do_update; 01897 progressdata.progress= progress; 01898 progressdata.stats_message= stats_message; 01899 progressdata.message_size= message_size; 01900 01901 context->reconstruction = libmv_solveReconstruction(context->tracks, 01902 context->keyframe1, context->keyframe2, 01903 context->refine_flags, 01904 context->focal_length, 01905 context->principal_point[0], context->principal_point[1], 01906 context->k1, context->k2, context->k3, 01907 solve_reconstruction_update_cb, &progressdata); 01908 01909 error= libmv_reprojectionError(context->reconstruction); 01910 01911 context->reprojection_error= error; 01912 #else 01913 (void) context; 01914 (void) stop; 01915 (void) do_update; 01916 (void) progress; 01917 (void) stats_message; 01918 (void) message_size; 01919 #endif 01920 } 01921 01922 int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTracking *tracking) 01923 { 01924 MovieTrackingReconstruction *reconstruction; 01925 01926 tracks_map_merge(context->tracks_map, tracking); 01927 01928 if(context->is_camera) { 01929 reconstruction= &tracking->reconstruction; 01930 } 01931 else { 01932 MovieTrackingObject *object; 01933 01934 object= BKE_tracking_named_object(tracking, context->object_name); 01935 reconstruction= &object->reconstruction; 01936 } 01937 01938 reconstruction->error= context->reprojection_error; 01939 reconstruction->flag|= TRACKING_RECONSTRUCTED; 01940 01941 #ifdef WITH_LIBMV 01942 if(!retrieve_libmv_reconstruct(context, tracking)) 01943 return 0; 01944 #endif 01945 01946 return 1; 01947 } 01948 01949 void BKE_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track) 01950 { 01951 BLI_uniquename(tracksbase, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name)); 01952 } 01953 01954 MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, MovieTrackingObject *object, const char *name) 01955 { 01956 ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object); 01957 MovieTrackingTrack *track= tracksbase->first; 01958 01959 while(track) { 01960 if(!strcmp(track->name, name)) 01961 return track; 01962 01963 track= track->next; 01964 } 01965 01966 return NULL; 01967 } 01968 01969 static int reconstruction_camera_index(MovieTrackingReconstruction *reconstruction, int framenr, int nearest) 01970 { 01971 MovieReconstructedCamera *cameras= reconstruction->cameras; 01972 int a= 0, d= 1; 01973 01974 if(!reconstruction->camnr) 01975 return -1; 01976 01977 if(framenr<cameras[0].framenr) { 01978 if(nearest) return 0; 01979 else return -1; 01980 } 01981 01982 if(framenr>cameras[reconstruction->camnr-1].framenr) { 01983 if(nearest) return reconstruction->camnr-1; 01984 else return -1; 01985 } 01986 01987 if(reconstruction->last_camera<reconstruction->camnr) 01988 a= reconstruction->last_camera; 01989 01990 if(cameras[a].framenr>=framenr) 01991 d= -1; 01992 01993 while(a>=0 && a<reconstruction->camnr) { 01994 int cfra= cameras[a].framenr; 01995 01996 /* check if needed framenr was "skipped" -- no data for requested frame */ 01997 01998 if(d>0 && cfra>framenr) { 01999 /* interpolate with previous position */ 02000 if(nearest) return a-1; 02001 else break; 02002 } 02003 02004 if(d<0 && cfra<framenr) { 02005 /* interpolate with next position */ 02006 if(nearest) return a; 02007 else break; 02008 } 02009 02010 if(cfra==framenr) { 02011 reconstruction->last_camera= a; 02012 02013 return a; 02014 } 02015 02016 a+= d; 02017 } 02018 02019 return -1; 02020 } 02021 02022 static void scale_reconstructed_camera(MovieTrackingObject *object, float mat[4][4]) 02023 { 02024 if((object->flag&TRACKING_OBJECT_CAMERA)==0) { 02025 float smat[4][4]; 02026 02027 scale_m4_fl(smat, 1.0f/object->scale); 02028 mult_m4_m4m4(mat, mat, smat); 02029 } 02030 } 02031 02032 MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking, 02033 MovieTrackingObject *object, int framenr) 02034 { 02035 MovieTrackingReconstruction *reconstruction; 02036 int a; 02037 02038 reconstruction= BKE_tracking_object_reconstruction(tracking, object); 02039 a= reconstruction_camera_index(reconstruction, framenr, 0); 02040 02041 if(a==-1) 02042 return NULL; 02043 02044 return &reconstruction->cameras[a]; 02045 } 02046 02047 void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, MovieTrackingObject *object, 02048 int framenr, float mat[4][4]) 02049 { 02050 MovieTrackingReconstruction *reconstruction; 02051 MovieReconstructedCamera *cameras; 02052 int a; 02053 02054 reconstruction= BKE_tracking_object_reconstruction(tracking, object); 02055 cameras= reconstruction->cameras; 02056 a= reconstruction_camera_index(reconstruction, framenr, 1); 02057 02058 if(a==-1) { 02059 unit_m4(mat); 02060 return; 02061 } 02062 02063 if(cameras[a].framenr!=framenr && a>0 && a<reconstruction->camnr-1) { 02064 float t= ((float)framenr-cameras[a].framenr) / (cameras[a+1].framenr-cameras[a].framenr); 02065 02066 blend_m4_m4m4(mat, cameras[a].mat, cameras[a+1].mat, t); 02067 } else { 02068 copy_m4_m4(mat, cameras[a].mat); 02069 } 02070 02071 scale_reconstructed_camera(object, mat); 02072 } 02073 02074 void BKE_get_tracking_mat(Scene *scene, Object *ob, float mat[4][4]) 02075 { 02076 if(!ob) { 02077 if(scene->camera) ob= scene->camera; 02078 else ob= scene_find_camera(scene); 02079 } 02080 02081 if(ob) 02082 where_is_object_mat(scene, ob, mat); 02083 else 02084 unit_m4(mat); 02085 } 02086 02087 void BKE_tracking_camera_shift(MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty) 02088 { 02089 *shiftx= (0.5f*winx-tracking->camera.principal[0]) / winx; 02090 *shifty= (0.5f*winy-tracking->camera.principal[1]) / winx; 02091 } 02092 02093 void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camera *camera, int width, int height) 02094 { 02095 float focal= tracking->camera.focal; 02096 02097 camera->sensor_x= tracking->camera.sensor_width; 02098 camera->sensor_fit= CAMERA_SENSOR_FIT_AUTO; 02099 camera->lens= focal*camera->sensor_x/width; 02100 02101 scene->r.xsch= width*tracking->camera.pixel_aspect; 02102 scene->r.ysch= height; 02103 02104 scene->r.xasp= 1.0f; 02105 scene->r.yasp= 1.0f; 02106 02107 BKE_tracking_camera_shift(tracking, width, height, &camera->shiftx, &camera->shifty); 02108 } 02109 02110 void BKE_tracking_projection_matrix(MovieTracking *tracking, MovieTrackingObject *object, 02111 int framenr, int winx, int winy, float mat[4][4]) 02112 { 02113 MovieReconstructedCamera *camera; 02114 float lens= tracking->camera.focal*tracking->camera.sensor_width/(float)winx; 02115 float viewfac, pixsize, left, right, bottom, top, clipsta, clipend; 02116 float winmat[4][4]; 02117 float ycor= 1.0f/tracking->camera.pixel_aspect; 02118 float shiftx, shifty, winside= MAX2(winx, winy); 02119 02120 BKE_tracking_camera_shift(tracking, winx, winy, &shiftx, &shifty); 02121 02122 clipsta= 0.1f; 02123 clipend= 1000.0f; 02124 02125 if(winx >= winy) 02126 viewfac= (lens*winx)/tracking->camera.sensor_width; 02127 else 02128 viewfac= (ycor*lens*winy)/tracking->camera.sensor_width; 02129 02130 pixsize= clipsta/viewfac; 02131 02132 left= -0.5f*(float)winx + shiftx*winside; 02133 bottom= -0.5f*(ycor)*(float)winy + shifty*winside; 02134 right= 0.5f*(float)winx + shiftx*winside; 02135 top= 0.5f*(ycor)*(float)winy + shifty*winside; 02136 02137 left *= pixsize; 02138 right *= pixsize; 02139 bottom *= pixsize; 02140 top *= pixsize; 02141 02142 perspective_m4(winmat, left, right, bottom, top, clipsta, clipend); 02143 02144 camera= BKE_tracking_get_reconstructed_camera(tracking, object, framenr); 02145 02146 if(camera) { 02147 float imat[4][4]; 02148 02149 invert_m4_m4(imat, camera->mat); 02150 mult_m4_m4m4(mat, winmat, imat); 02151 } else copy_m4_m4(mat, winmat); 02152 } 02153 02154 ListBase *BKE_tracking_get_tracks(MovieTracking *tracking) 02155 { 02156 MovieTrackingObject *object= BKE_tracking_active_object(tracking); 02157 02158 if(object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) { 02159 return &object->tracks; 02160 } 02161 02162 return &tracking->tracks; 02163 } 02164 02165 MovieTrackingTrack *BKE_tracking_active_track(MovieTracking *tracking) 02166 { 02167 ListBase *tracksbase; 02168 02169 if(!tracking->act_track) 02170 return NULL; 02171 02172 tracksbase= BKE_tracking_get_tracks(tracking); 02173 02174 /* check that active track is in current tracks list */ 02175 if(BLI_findindex(tracksbase, tracking->act_track) >= 0) 02176 return tracking->act_track; 02177 02178 return NULL; 02179 } 02180 02181 MovieTrackingObject *BKE_tracking_active_object(MovieTracking *tracking) 02182 { 02183 return BLI_findlink(&tracking->objects, tracking->objectnr); 02184 } 02185 02186 MovieTrackingObject *BKE_tracking_get_camera_object(MovieTracking *tracking) 02187 { 02188 MovieTrackingObject *object= tracking->objects.first; 02189 02190 while(object) { 02191 if(object->flag & TRACKING_OBJECT_CAMERA) 02192 return object; 02193 02194 object= object->next; 02195 } 02196 02197 return NULL; 02198 } 02199 02200 ListBase *BKE_tracking_object_tracks(MovieTracking *tracking, MovieTrackingObject *object) 02201 { 02202 if(object->flag & TRACKING_OBJECT_CAMERA) { 02203 return &tracking->tracks; 02204 } 02205 02206 return &object->tracks; 02207 } 02208 02209 MovieTrackingReconstruction *BKE_tracking_object_reconstruction(MovieTracking *tracking, MovieTrackingObject *object) 02210 { 02211 if(object->flag & TRACKING_OBJECT_CAMERA) { 02212 return &tracking->reconstruction; 02213 } 02214 02215 return &object->reconstruction; 02216 } 02217 02218 MovieTrackingReconstruction *BKE_tracking_get_reconstruction(MovieTracking *tracking) 02219 { 02220 MovieTrackingObject *object= BKE_tracking_active_object(tracking); 02221 02222 return BKE_tracking_object_reconstruction(tracking, object); 02223 } 02224 02225 void BKE_tracking_apply_intrinsics(MovieTracking *tracking, float co[2], float nco[2]) 02226 { 02227 MovieTrackingCamera *camera= &tracking->camera; 02228 02229 #ifdef WITH_LIBMV 02230 double x, y; 02231 float aspy= 1.0f/tracking->camera.pixel_aspect; 02232 02233 /* normalize coords */ 02234 x= (co[0]-camera->principal[0]) / camera->focal; 02235 y= (co[1]-camera->principal[1] * aspy) / camera->focal; 02236 02237 libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy, 02238 camera->k1, camera->k2, camera->k3, x, y, &x, &y); 02239 02240 /* result is in image coords already */ 02241 nco[0]= x; 02242 nco[1]= y; 02243 #else 02244 (void)camera; 02245 (void)co; 02246 (void)nco; 02247 #endif 02248 } 02249 02250 void BKE_tracking_invert_intrinsics(MovieTracking *tracking, float co[2], float nco[2]) 02251 { 02252 MovieTrackingCamera *camera= &tracking->camera; 02253 02254 #ifdef WITH_LIBMV 02255 double x= co[0], y= co[1]; 02256 float aspy= 1.0f/tracking->camera.pixel_aspect; 02257 02258 libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy, 02259 camera->k1, camera->k2, camera->k3, x, y, &x, &y); 02260 02261 nco[0]= x * camera->focal + camera->principal[0]; 02262 nco[1]= y * camera->focal + camera->principal[1] * aspy; 02263 #else 02264 (void)camera; 02265 (void)co; 02266 (void)nco; 02267 #endif 02268 } 02269 02270 #ifdef WITH_LIBMV 02271 static int point_in_stroke(bGPDstroke *stroke, float x, float y) 02272 { 02273 int i, prev; 02274 int count= 0; 02275 bGPDspoint *points= stroke->points; 02276 02277 prev= stroke->totpoints-1; 02278 02279 for(i= 0; i<stroke->totpoints; i++) { 02280 if((points[i].y<y && points[prev].y>=y) || (points[prev].y<y && points[i].y>=y)) { 02281 float fac= (y-points[i].y)/(points[prev].y-points[i].y); 02282 02283 if (points[i].x+fac*(points[prev].x-points[i].x)<x) 02284 count++; 02285 } 02286 02287 prev= i; 02288 } 02289 02290 return count%2; 02291 } 02292 02293 static int point_in_layer(bGPDlayer *layer, float x, float y) 02294 { 02295 bGPDframe *frame= layer->frames.first; 02296 02297 while(frame) { 02298 bGPDstroke *stroke= frame->strokes.first; 02299 while(stroke) { 02300 if(point_in_stroke(stroke, x, y)) 02301 return 1; 02302 02303 stroke= stroke->next; 02304 } 02305 frame= frame->next; 02306 } 02307 02308 return 0; 02309 } 02310 02311 static void retrieve_libmv_features(MovieTracking *tracking, ListBase *tracksbase, 02312 struct libmv_Features *features, int framenr, int width, int height, 02313 bGPDlayer *layer, int place_outside_layer) 02314 { 02315 int a; 02316 02317 a= libmv_countFeatures(features); 02318 while(a--) { 02319 MovieTrackingTrack *track; 02320 double x, y, size, score; 02321 int ok= 1; 02322 float xu, yu; 02323 02324 libmv_getFeature(features, a, &x, &y, &score, &size); 02325 02326 xu= x/width; 02327 yu= y/height; 02328 02329 if(layer) 02330 ok= point_in_layer(layer, xu, yu)!=place_outside_layer; 02331 02332 if(ok) { 02333 track= BKE_tracking_add_track(tracking, tracksbase, xu, yu, framenr, width, height); 02334 track->flag|= SELECT; 02335 track->pat_flag|= SELECT; 02336 track->search_flag|= SELECT; 02337 } 02338 } 02339 } 02340 #endif 02341 02342 void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImBuf *ibuf, 02343 int framenr, int margin, int min_trackness, int min_distance, bGPDlayer *layer, 02344 int place_outside_layer) 02345 { 02346 #ifdef WITH_LIBMV 02347 struct libmv_Features *features; 02348 unsigned char *pixels= get_ucharbuf(ibuf); 02349 02350 features= libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x, 02351 margin, min_trackness, min_distance); 02352 02353 MEM_freeN(pixels); 02354 02355 retrieve_libmv_features(tracking, tracksbase, features, framenr, 02356 ibuf->x, ibuf->y, layer, place_outside_layer); 02357 02358 libmv_destroyFeatures(features); 02359 #else 02360 (void)tracking; 02361 (void)tracksbase; 02362 (void)ibuf; 02363 (void)framenr; 02364 (void)margin; 02365 (void)min_trackness; 02366 (void)min_distance; 02367 (void)layer; 02368 (void)place_outside_layer; 02369 #endif 02370 } 02371 02372 MovieTrackingTrack *BKE_tracking_indexed_track(MovieTracking *tracking, int tracknr, ListBase **tracksbase_r) 02373 { 02374 MovieTrackingObject *object; 02375 int cur= 1; 02376 02377 object= tracking->objects.first; 02378 while(object) { 02379 ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object); 02380 MovieTrackingTrack *track= tracksbase->first; 02381 02382 while(track) { 02383 if(track->flag&TRACK_HAS_BUNDLE) { 02384 if(cur==tracknr) { 02385 *tracksbase_r= tracksbase; 02386 return track; 02387 } 02388 02389 cur++; 02390 } 02391 02392 track= track->next; 02393 } 02394 02395 object= object->next; 02396 } 02397 02398 *tracksbase_r= NULL; 02399 02400 return NULL; 02401 } 02402 02403 static int stabilization_median_point(MovieTracking *tracking, int framenr, float median[2]) 02404 { 02405 int ok= 0; 02406 float min[2], max[2]; 02407 MovieTrackingTrack *track; 02408 02409 INIT_MINMAX2(min, max); 02410 02411 (void) tracking; 02412 02413 track= tracking->tracks.first; 02414 while(track) { 02415 if(track->flag&TRACK_USE_2D_STAB) { 02416 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr); 02417 02418 DO_MINMAX2(marker->pos, min, max); 02419 02420 ok= 1; 02421 } 02422 02423 track= track->next; 02424 } 02425 02426 median[0]= (max[0]+min[0])/2.0f; 02427 median[1]= (max[1]+min[1])/2.0f; 02428 02429 return ok; 02430 } 02431 02432 static void calculate_stabdata(MovieTracking *tracking, int framenr, float width, float height, 02433 float firstmedian[2], float median[2], float loc[2], float *scale, float *angle) 02434 { 02435 MovieTrackingStabilization *stab= &tracking->stabilization; 02436 02437 *scale= (stab->scale-1.0f)*stab->scaleinf+1.0f; 02438 *angle= 0.0f; 02439 02440 loc[0]= (firstmedian[0]-median[0])*width*(*scale); 02441 loc[1]= (firstmedian[1]-median[1])*height*(*scale); 02442 02443 mul_v2_fl(loc, stab->locinf); 02444 02445 if((stab->flag&TRACKING_STABILIZE_ROTATION) && stab->rot_track && stab->rotinf) { 02446 MovieTrackingMarker *marker; 02447 float a[2], b[2]; 02448 float x0= (float)width/2.0f, y0= (float)height/2.0f; 02449 float x= median[0]*width, y= median[1]*height; 02450 02451 marker= BKE_tracking_get_marker(stab->rot_track, 1); 02452 sub_v2_v2v2(a, marker->pos, firstmedian); 02453 a[0]*= width; 02454 a[1]*= height; 02455 02456 marker= BKE_tracking_get_marker(stab->rot_track, framenr); 02457 sub_v2_v2v2(b, marker->pos, median); 02458 b[0]*= width; 02459 b[1]*= height; 02460 02461 *angle= -atan2(a[0]*b[1]-a[1]*b[0], a[0]*b[0]+a[1]*b[1]); 02462 *angle*= stab->rotinf; 02463 02464 /* convert to rotation around image center */ 02465 loc[0]-= (x0 + (x-x0)*cosf(*angle)-(y-y0)*sinf(*angle) - x)*(*scale); 02466 loc[1]-= (y0 + (x-x0)*sinf(*angle)+(y-y0)*cosf(*angle) - y)*(*scale); 02467 } 02468 } 02469 02470 static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, int height) 02471 { 02472 float firstmedian[2]; 02473 MovieTrackingStabilization *stab= &tracking->stabilization; 02474 02475 if(stab->ok) 02476 return stab->scale; 02477 02478 if(stabilization_median_point(tracking, 1, firstmedian)) { 02479 int sfra= INT_MAX, efra= INT_MIN, cfra; 02480 float delta[2]= {0.0f, 0.0f}, scalex= 1.0f, scaley= 1.0f; 02481 MovieTrackingTrack *track; 02482 02483 stab->scale= 1.0f; 02484 02485 track= tracking->tracks.first; 02486 while(track) { 02487 if(track->flag&TRACK_USE_2D_STAB || 02488 ((stab->flag&TRACKING_STABILIZE_ROTATION) && track==stab->rot_track)) { 02489 sfra= MIN2(sfra, track->markers[0].framenr); 02490 efra= MAX2(efra, track->markers[track->markersnr-1].framenr); 02491 } 02492 02493 track= track->next; 02494 } 02495 02496 for(cfra=sfra; cfra<=efra; cfra++) { 02497 float median[2], near[2]; 02498 float loc[2], scale, angle; 02499 02500 stabilization_median_point(tracking, cfra, median); 02501 02502 calculate_stabdata(tracking, cfra, width, height, firstmedian, median, 02503 loc, &scale, &angle); 02504 02505 if(angle==0.0f) { 02506 loc[0]= fabsf(loc[0]); 02507 loc[1]= fabsf(loc[1]); 02508 02509 delta[0]= MAX2(delta[0], loc[0]); 02510 delta[1]= MAX2(delta[1], loc[1]); 02511 02512 near[0]= MIN2(median[0], 1.0f-median[0]); 02513 near[1]= MIN2(median[1], 1.0f-median[1]); 02514 near[0]= MAX2(near[0], 0.05f); 02515 near[1]= MAX2(near[1], 0.05f); 02516 02517 scalex= 1.0f+delta[0]/(near[0]*width); 02518 scaley= 1.0f+delta[1]/(near[1]*height); 02519 } else { 02520 int i; 02521 float mat[4][4]; 02522 float points[4][2]={{0.0f, 0.0f}, {0.0f, height}, {width, height}, {width, 0.0f}}; 02523 02524 BKE_tracking_stabdata_to_mat4(width, height, loc, scale, angle, mat); 02525 02526 for(i= 0; i<4; i++) { 02527 int j; 02528 float a[3]= {0.0f, 0.0f, 0.0f}, b[3]= {0.0f, 0.0f, 0.0f}; 02529 02530 copy_v3_v3(a, points[i]); 02531 copy_v3_v3(b, points[(i+1)%4]); 02532 02533 mul_m4_v3(mat, a); 02534 mul_m4_v3(mat, b); 02535 02536 for(j= 0; j<4; j++) { 02537 float point[3]= {points[j][0], points[j][1], 0.0f}; 02538 float v1[3], v2[3]; 02539 02540 sub_v3_v3v3(v1, b, a); 02541 sub_v3_v3v3(v2, point, a); 02542 02543 if(cross_v2v2(v1, v2) >= 0.0f) { 02544 float dist= dist_to_line_v2(point, a, b); 02545 if(i%2==0) { 02546 scalex= MAX2(scalex, (width+2*dist)/width); 02547 } else { 02548 scaley= MAX2(scaley, (height+2*dist)/height); 02549 } 02550 } 02551 } 02552 } 02553 } 02554 } 02555 02556 stab->scale= MAX2(scalex, scaley); 02557 02558 if(stab->maxscale>0.0f) 02559 stab->scale= MIN2(stab->scale, stab->maxscale); 02560 } else { 02561 stab->scale= 1.0f; 02562 } 02563 02564 stab->ok= 1; 02565 02566 return stab->scale; 02567 } 02568 02569 static ImBuf* stabilize_alloc_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill) 02570 { 02571 int flags; 02572 02573 if(cacheibuf && (cacheibuf->x != srcibuf->x || cacheibuf->y != srcibuf->y)) { 02574 IMB_freeImBuf(cacheibuf); 02575 cacheibuf= NULL; 02576 } 02577 02578 flags= IB_rect; 02579 02580 if(srcibuf->rect_float) 02581 flags|= IB_rectfloat; 02582 02583 if(cacheibuf) { 02584 if(fill) { 02585 float col[4]= {0.0f, 0.0f, 0.0f, 0.0f}; 02586 IMB_rectfill(cacheibuf, col); 02587 } 02588 } 02589 else { 02590 cacheibuf= IMB_allocImBuf(srcibuf->x, srcibuf->y, srcibuf->planes, flags); 02591 cacheibuf->profile= srcibuf->profile; 02592 } 02593 02594 return cacheibuf; 02595 } 02596 02597 void BKE_tracking_stabilization_data(MovieTracking *tracking, int framenr, int width, int height, float loc[2], float *scale, float *angle) 02598 { 02599 float firstmedian[2], median[2]; 02600 MovieTrackingStabilization *stab= &tracking->stabilization; 02601 02602 if((stab->flag&TRACKING_2D_STABILIZATION)==0) { 02603 zero_v2(loc); 02604 *scale= 1.0f; 02605 *angle= 0.0f; 02606 02607 return; 02608 } 02609 02610 if(stabilization_median_point(tracking, 1, firstmedian)) { 02611 stabilization_median_point(tracking, framenr, median); 02612 02613 if((stab->flag&TRACKING_AUTOSCALE)==0) 02614 stab->scale= 1.0f; 02615 02616 if(!stab->ok) { 02617 if(stab->flag&TRACKING_AUTOSCALE) 02618 stabilization_auto_scale_factor(tracking, width, height); 02619 02620 calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle); 02621 02622 stab->ok= 1; 02623 } else { 02624 calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle); 02625 } 02626 } else { 02627 zero_v2(loc); 02628 *scale= 1.0f; 02629 *angle= 0.0f; 02630 } 02631 } 02632 02633 ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, float loc[2], float *scale, float *angle) 02634 { 02635 float tloc[2], tscale, tangle; 02636 MovieTrackingStabilization *stab= &tracking->stabilization; 02637 ImBuf *tmpibuf; 02638 float width= ibuf->x, height= ibuf->y; 02639 02640 if(loc) copy_v2_v2(tloc, loc); 02641 if(scale) tscale= *scale; 02642 02643 if((stab->flag&TRACKING_2D_STABILIZATION)==0) { 02644 if(loc) zero_v2(loc); 02645 if(scale) *scale= 1.0f; 02646 02647 return ibuf; 02648 } 02649 02650 BKE_tracking_stabilization_data(tracking, framenr, width, height, tloc, &tscale, &tangle); 02651 02652 tmpibuf= stabilize_alloc_ibuf(NULL, ibuf, 1); 02653 02654 /* scale would be handled by matrix transformation when angle is non-zero */ 02655 if(tscale!=1.0f && tangle==0.0f) { 02656 ImBuf *scaleibuf; 02657 02658 stabilization_auto_scale_factor(tracking, width, height); 02659 02660 scaleibuf= stabilize_alloc_ibuf(stab->scaleibuf, ibuf, 0); 02661 stab->scaleibuf= scaleibuf; 02662 02663 IMB_rectcpy(scaleibuf, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y); 02664 IMB_scalefastImBuf(scaleibuf, ibuf->x*tscale, ibuf->y*tscale); 02665 02666 ibuf= scaleibuf; 02667 } 02668 02669 if(tangle==0.0f) { 02670 /* if angle is zero, then it's much faster to use rect copy 02671 but could be issues with subpixel precisions */ 02672 IMB_rectcpy(tmpibuf, ibuf, tloc[0]-(tscale-1.0f)*width/2.0f, tloc[1]-(tscale-1.0f)*height/2.0f, 0, 0, ibuf->x, ibuf->y); 02673 } else { 02674 float mat[4][4]; 02675 int i, j; 02676 02677 BKE_tracking_stabdata_to_mat4(ibuf->x, ibuf->y, tloc, tscale, tangle, mat); 02678 invert_m4(mat); 02679 02680 for(j=0; j<tmpibuf->y; j++) { 02681 for(i=0; i<tmpibuf->x;i++) { 02682 float vec[3]= {i, j, 0}; 02683 02684 mul_v3_m4v3(vec, mat, vec); 02685 02686 /* TODO: add selector for interpolation method */ 02687 neareast_interpolation(ibuf, tmpibuf, vec[0], vec[1], i, j); 02688 } 02689 } 02690 } 02691 02692 tmpibuf->userflags|= IB_MIPMAP_INVALID; 02693 02694 if(tmpibuf->rect_float) 02695 tmpibuf->userflags|= IB_RECT_INVALID; 02696 02697 if(loc) copy_v2_v2(loc, tloc); 02698 if(scale) *scale= tscale; 02699 if(angle) *angle= tangle; 02700 02701 return tmpibuf; 02702 } 02703 02704 void BKE_tracking_stabdata_to_mat4(int width, int height, float loc[2], float scale, float angle, float mat[4][4]) 02705 { 02706 float lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4]; 02707 float svec[3]= {scale, scale, scale}; 02708 02709 unit_m4(rmat); 02710 unit_m4(lmat); 02711 unit_m4(smat); 02712 unit_m4(cmat); 02713 02714 /* image center as rotation center */ 02715 cmat[3][0]= (float)width/2.0f; 02716 cmat[3][1]= (float)height/2.0f; 02717 invert_m4_m4(icmat, cmat); 02718 02719 size_to_mat4(smat, svec); /* scale matrix */ 02720 add_v2_v2(lmat[3], loc); /* tranlation matrix */ 02721 rotate_m4(rmat, 'Z', angle); /* rotation matrix */ 02722 02723 /* compose transformation matrix */ 02724 mul_serie_m4(mat, lmat, cmat, rmat, smat, icmat, NULL, NULL, NULL); 02725 } 02726 02727 MovieDistortion *BKE_tracking_distortion_create(void) 02728 { 02729 MovieDistortion *distortion; 02730 02731 distortion= MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create"); 02732 02733 return distortion; 02734 } 02735 02736 MovieDistortion *BKE_tracking_distortion_copy(MovieDistortion *distortion) 02737 { 02738 MovieDistortion *new_distortion; 02739 02740 new_distortion= MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create"); 02741 02742 #ifdef WITH_LIBMV 02743 new_distortion->intrinsics= libmv_CameraIntrinsicsCopy(distortion->intrinsics); 02744 #else 02745 (void)distortion; 02746 #endif 02747 02748 return new_distortion; 02749 } 02750 02751 void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking, int width, int height) 02752 { 02753 MovieTrackingCamera *camera= &tracking->camera; 02754 float aspy= 1.0f/tracking->camera.pixel_aspect; 02755 02756 #ifdef WITH_LIBMV 02757 if(!distortion->intrinsics) { 02758 distortion->intrinsics= libmv_CameraIntrinsicsNew(camera->focal, 02759 camera->principal[0], camera->principal[1] * aspy, 02760 camera->k1, camera->k2, camera->k3, width, height * aspy); 02761 } else { 02762 libmv_CameraIntrinsicsUpdate(distortion->intrinsics, camera->focal, 02763 camera->principal[0], camera->principal[1] * aspy, 02764 camera->k1, camera->k2, camera->k3, width, height * aspy); 02765 } 02766 #else 02767 (void)distortion; 02768 (void)width; 02769 (void)height; 02770 (void)camera; 02771 (void)aspy; 02772 #endif 02773 } 02774 02775 ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *tracking, 02776 ImBuf *ibuf, int width, int height, float overscan, int undistort) 02777 { 02778 ImBuf *resibuf; 02779 02780 BKE_tracking_distortion_update(distortion, tracking, width, height); 02781 02782 resibuf= IMB_dupImBuf(ibuf); 02783 02784 if(ibuf->rect_float) { 02785 #ifdef WITH_LIBMV 02786 if(undistort) { 02787 libmv_CameraIntrinsicsUndistortFloat(distortion->intrinsics, 02788 ibuf->rect_float, resibuf->rect_float, 02789 ibuf->x, ibuf->y, overscan, ibuf->channels); 02790 } else { 02791 libmv_CameraIntrinsicsDistortFloat(distortion->intrinsics, 02792 ibuf->rect_float, resibuf->rect_float, 02793 ibuf->x, ibuf->y, overscan, ibuf->channels); 02794 } 02795 #endif 02796 02797 ibuf->userflags|= IB_RECT_INVALID; 02798 } else { 02799 #ifdef WITH_LIBMV 02800 if(undistort) { 02801 libmv_CameraIntrinsicsUndistortByte(distortion->intrinsics, 02802 (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect, 02803 ibuf->x, ibuf->y, overscan, ibuf->channels); 02804 } else { 02805 libmv_CameraIntrinsicsDistortByte(distortion->intrinsics, 02806 (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect, 02807 ibuf->x, ibuf->y, overscan, ibuf->channels); 02808 } 02809 #endif 02810 } 02811 02812 #ifndef WITH_LIBMV 02813 (void)overscan; 02814 (void)undistort; 02815 #endif 02816 02817 return resibuf; 02818 } 02819 02820 void BKE_tracking_distortion_destroy(MovieDistortion *distortion) 02821 { 02822 #ifdef WITH_LIBMV 02823 libmv_CameraIntrinsicsDestroy(distortion->intrinsics); 02824 #endif 02825 02826 MEM_freeN(distortion); 02827 } 02828 02829 ImBuf *BKE_tracking_undistort(MovieTracking *tracking, ImBuf *ibuf, int width, int height, float overscan) 02830 { 02831 MovieTrackingCamera *camera= &tracking->camera; 02832 02833 if(camera->intrinsics == NULL) 02834 camera->intrinsics= BKE_tracking_distortion_create(); 02835 02836 return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, width, height, overscan, 1); 02837 } 02838 02839 ImBuf *BKE_tracking_distort(MovieTracking *tracking, ImBuf *ibuf, int width, int height, float overscan) 02840 { 02841 MovieTrackingCamera *camera= &tracking->camera; 02842 02843 if(camera->intrinsics == NULL) 02844 camera->intrinsics= BKE_tracking_distortion_create(); 02845 02846 return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, width, height, overscan, 0); 02847 } 02848 02849 /* area - which part of marker should be selected. see TRACK_AREA_* constants */ 02850 void BKE_tracking_select_track(ListBase *tracksbase, MovieTrackingTrack *track, int area, int extend) 02851 { 02852 if(extend) { 02853 BKE_tracking_track_flag(track, area, SELECT, 0); 02854 } else { 02855 MovieTrackingTrack *cur= tracksbase->first; 02856 02857 while(cur) { 02858 if(cur==track) { 02859 BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1); 02860 BKE_tracking_track_flag(cur, area, SELECT, 0); 02861 } 02862 else { 02863 BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1); 02864 } 02865 02866 cur= cur->next; 02867 } 02868 } 02869 } 02870 02871 void BKE_tracking_deselect_track(MovieTrackingTrack *track, int area) 02872 { 02873 BKE_tracking_track_flag(track, area, SELECT, 1); 02874 } 02875 02876 MovieTrackingObject *BKE_tracking_new_object(MovieTracking *tracking, const char *name) 02877 { 02878 MovieTrackingObject *object= MEM_callocN(sizeof(MovieTrackingObject), "tracking object"); 02879 02880 if(tracking->tot_object==0) { 02881 /* first object is always camera */ 02882 BLI_strncpy(object->name, "Camera", sizeof(object->name)); 02883 02884 object->flag|= TRACKING_OBJECT_CAMERA; 02885 } 02886 else { 02887 BLI_strncpy(object->name, name, sizeof(object->name)); 02888 } 02889 02890 BLI_addtail(&tracking->objects, object); 02891 02892 tracking->tot_object++; 02893 tracking->objectnr= BLI_countlist(&tracking->objects) - 1; 02894 02895 BKE_tracking_object_unique_name(tracking, object); 02896 02897 return object; 02898 } 02899 02900 void BKE_tracking_remove_object(MovieTracking *tracking, MovieTrackingObject *object) 02901 { 02902 MovieTrackingTrack *track; 02903 int index= BLI_findindex(&tracking->objects, object); 02904 02905 if(index<0) 02906 return; 02907 02908 if(object->flag & TRACKING_OBJECT_CAMERA) { 02909 /* object used for camera solving can't be deleted */ 02910 return; 02911 } 02912 02913 track= object->tracks.first; 02914 while(track) { 02915 if(track==tracking->act_track) 02916 tracking->act_track= NULL; 02917 02918 track= track->next; 02919 } 02920 02921 tracking_object_free(object); 02922 BLI_freelinkN(&tracking->objects, object); 02923 02924 tracking->tot_object--; 02925 02926 if(index>0) 02927 tracking->objectnr= index-1; 02928 else 02929 tracking->objectnr= 0; 02930 } 02931 02932 void BKE_tracking_object_unique_name(MovieTracking *tracking, MovieTrackingObject *object) 02933 { 02934 BLI_uniquename(&tracking->objects, object, "Object", '.', offsetof(MovieTrackingObject, name), sizeof(object->name)); 02935 } 02936 02937 MovieTrackingObject *BKE_tracking_named_object(MovieTracking *tracking, const char *name) 02938 { 02939 MovieTrackingObject *object= tracking->objects.first; 02940 02941 while(object) { 02942 if(!strcmp(object->name, name)) 02943 return object; 02944 02945 object= object->next; 02946 } 02947 02948 return NULL; 02949 }