Blender  V3.3
tracking_util.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2011 Blender Foundation. All rights reserved. */
3 
11 #include <stddef.h>
12 
13 #include "MEM_guardedalloc.h"
14 
15 #include "DNA_movieclip_types.h"
16 
17 #include "BLI_ghash.h"
18 #include "BLI_listbase.h"
19 #include "BLI_math.h"
20 #include "BLI_string.h"
21 #include "BLI_string_utils.h"
22 #include "BLI_threads.h"
23 #include "BLI_utildefines.h"
24 
25 #include "BLT_translation.h"
26 
27 #include "BKE_movieclip.h"
28 #include "BKE_tracking.h"
29 
30 #include "IMB_imbuf.h"
31 #include "IMB_imbuf_types.h"
32 #include "IMB_moviecache.h"
33 
34 #include "tracking_private.h"
35 
36 #include "libmv-capi.h"
37 
38 /* Uncomment this to have caching-specific debug prints. */
39 // #define DEBUG_CACHE
40 
41 #ifdef DEBUG_CACHE
42 # define CACHE_PRINTF(...) printf(__VA_ARGS__)
43 #else
44 # define CACHE_PRINTF(...)
45 #endif
46 
47 /* -------------------------------------------------------------------- */
51 TracksMap *tracks_map_new(const char *object_name,
52  bool is_camera,
53  int num_tracks,
54  int customdata_size)
55 {
56  TracksMap *map = MEM_callocN(sizeof(TracksMap), "TrackingsMap");
57 
58  BLI_strncpy(map->object_name, object_name, sizeof(map->object_name));
59  map->is_camera = is_camera;
60 
61  map->num_tracks = num_tracks;
62  map->customdata_size = customdata_size;
63 
64  map->tracks = MEM_callocN(sizeof(MovieTrackingTrack) * num_tracks, "TrackingsMap tracks");
65 
66  if (customdata_size) {
67  map->customdata = MEM_callocN(customdata_size * num_tracks, "TracksMap customdata");
68  }
69 
70  map->hash = BLI_ghash_ptr_new("TracksMap hash");
71 
72  BLI_spin_init(&map->spin_lock);
73 
74  return map;
75 }
76 
78 {
79  return map->num_tracks;
80 }
81 
83  int index,
84  MovieTrackingTrack **track,
85  void **customdata)
86 {
87  *track = &map->tracks[index];
88 
89  if (map->customdata) {
90  *customdata = &map->customdata[index * map->customdata_size];
91  }
92 }
93 
94 void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *customdata)
95 {
96  MovieTrackingTrack new_track = *track;
97 
98  new_track.markers = MEM_dupallocN(new_track.markers);
99 
100  map->tracks[map->ptr] = new_track;
101 
102  if (customdata) {
103  memcpy(&map->customdata[map->ptr * map->customdata_size], customdata, map->customdata_size);
104  }
105 
106  BLI_ghash_insert(map->hash, &map->tracks[map->ptr], track);
107 
108  map->ptr++;
109 }
110 
112 {
113  MovieTrackingTrack *track;
114  ListBase tracks = {NULL, NULL}, new_tracks = {NULL, NULL};
115  ListBase *old_tracks;
116 
117  if (map->is_camera) {
118  old_tracks = &tracking->tracks;
119  }
120  else {
121  MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, map->object_name);
122 
123  if (!object) {
124  /* object was deleted by user, create new one */
125  object = BKE_tracking_object_add(tracking, map->object_name);
126  }
127 
128  old_tracks = &object->tracks;
129  }
130 
131  /* duplicate currently operating tracks to temporary list.
132  * this is needed to keep names in unique state and it's faster to change names
133  * of currently operating tracks (if needed)
134  */
135  for (int a = 0; a < map->num_tracks; a++) {
136  MovieTrackingTrack *old_track;
137  bool mapped_to_old = false;
138 
139  track = &map->tracks[a];
140 
141  /* find original of operating track in list of previously displayed tracks */
142  old_track = BLI_ghash_lookup(map->hash, track);
143  if (old_track) {
144  if (BLI_findindex(old_tracks, old_track) != -1) {
145  BLI_remlink(old_tracks, old_track);
146 
147  BLI_spin_lock(&map->spin_lock);
148 
149  /* Copy flags like selection back to the track map. */
150  track->flag = old_track->flag;
151  track->pat_flag = old_track->pat_flag;
152  track->search_flag = old_track->search_flag;
153 
154  /* Copy all the rest settings back from the map to the actual tracks. */
155  MEM_freeN(old_track->markers);
156  *old_track = *track;
157  old_track->markers = MEM_dupallocN(old_track->markers);
158 
159  BLI_spin_unlock(&map->spin_lock);
160 
161  BLI_addtail(&tracks, old_track);
162 
163  mapped_to_old = true;
164  }
165  }
166 
167  if (mapped_to_old == false) {
169 
170  /* Update old-new track mapping */
171  BLI_ghash_reinsert(map->hash, track, new_track, NULL, NULL);
172 
173  BLI_addtail(&tracks, new_track);
174  }
175  }
176 
177  /* move all tracks, which aren't operating */
178  track = old_tracks->first;
179  while (track) {
180  MovieTrackingTrack *next = track->next;
181  BLI_addtail(&new_tracks, track);
182  track = next;
183  }
184 
185  /* now move all tracks which are currently operating and keep their names unique */
186  track = tracks.first;
187  while (track) {
188  MovieTrackingTrack *next = track->next;
189 
190  BLI_remlink(&tracks, track);
191 
192  track->next = track->prev = NULL;
193  BLI_addtail(&new_tracks, track);
194 
195  BLI_uniquename(&new_tracks,
196  track,
198  '.',
199  offsetof(MovieTrackingTrack, name),
200  sizeof(track->name));
201 
202  track = next;
203  }
204 
205  *old_tracks = new_tracks;
206 }
207 
208 void tracks_map_free(TracksMap *map, void (*customdata_free)(void *customdata))
209 {
210  BLI_ghash_free(map->hash, NULL, NULL);
211 
212  for (int i = 0; i < map->num_tracks; i++) {
213  if (map->customdata && customdata_free) {
214  customdata_free(&map->customdata[i * map->customdata_size]);
215  }
216 
217  BKE_tracking_track_free(&map->tracks[i]);
218  }
219 
220  if (map->customdata) {
221  MEM_freeN(map->customdata);
222  }
223 
224  MEM_freeN(map->tracks);
225 
226  BLI_spin_end(&map->spin_lock);
227 
228  MEM_freeN(map);
229 }
230 
233 /* -------------------------------------------------------------------- */
237 /* Three coordinate frames: Frame, Search, and Marker
238  * Two units: Pixels, Unified
239  * Notation: {coordinate frame}_{unit}; for example, "search_pixel" are search
240  * window relative coordinates in pixels, and "frame_unified" are unified 0..1
241  * coordinates relative to the entire frame.
242  */
243 static void unified_to_pixel(int frame_width,
244  int frame_height,
245  const float unified_coords[2],
246  float pixel_coords[2])
247 {
248  pixel_coords[0] = unified_coords[0] * frame_width;
249  pixel_coords[1] = unified_coords[1] * frame_height;
250 }
251 
253  const float marker_unified_coords[2],
254  float frame_unified_coords[2])
255 {
256  frame_unified_coords[0] = marker_unified_coords[0] + marker->pos[0];
257  frame_unified_coords[1] = marker_unified_coords[1] + marker->pos[1];
258 }
259 
260 static void marker_unified_to_frame_pixel_coordinates(int frame_width,
261  int frame_height,
262  const MovieTrackingMarker *marker,
263  const float marker_unified_coords[2],
264  float frame_pixel_coords[2])
265 {
266  marker_to_frame_unified(marker, marker_unified_coords, frame_pixel_coords);
267  unified_to_pixel(frame_width, frame_height, frame_pixel_coords, frame_pixel_coords);
268 }
269 
271  int frame_height,
272  const MovieTrackingMarker *marker,
273  float frame_pixel[2])
274 {
275  /* Get the lower left coordinate of the search window and snap to pixel coordinates */
277  frame_width, frame_height, marker, marker->search_min, frame_pixel);
278  frame_pixel[0] = (int)frame_pixel[0];
279  frame_pixel[1] = (int)frame_pixel[1];
280 }
281 
282 static void pixel_to_unified(int frame_width,
283  int frame_height,
284  const float pixel_coords[2],
285  float unified_coords[2])
286 {
287  unified_coords[0] = pixel_coords[0] / frame_width;
288  unified_coords[1] = pixel_coords[1] / frame_height;
289 }
290 
291 static void marker_unified_to_search_pixel(int frame_width,
292  int frame_height,
293  const MovieTrackingMarker *marker,
294  const float marker_unified[2],
295  float search_pixel[2])
296 {
297  float frame_pixel[2];
298  float search_origin_frame_pixel[2];
299 
301  frame_width, frame_height, marker, marker_unified, frame_pixel);
303  frame_width, frame_height, marker, search_origin_frame_pixel);
304  sub_v2_v2v2(search_pixel, frame_pixel, search_origin_frame_pixel);
305 }
306 
307 static void search_pixel_to_marker_unified(int frame_width,
308  int frame_height,
309  const MovieTrackingMarker *marker,
310  const float search_pixel[2],
311  float marker_unified[2])
312 {
313  float frame_unified[2];
314  float search_origin_frame_pixel[2];
315 
317  frame_width, frame_height, marker, search_origin_frame_pixel);
318  add_v2_v2v2(frame_unified, search_pixel, search_origin_frame_pixel);
319  pixel_to_unified(frame_width, frame_height, frame_unified, frame_unified);
320 
321  /* marker pos is in frame unified */
322  sub_v2_v2v2(marker_unified, frame_unified, marker->pos);
323 }
324 
326  int frame_height,
327  const MovieTrackingMarker *marker,
328  double search_pixel_x[5],
329  double search_pixel_y[5])
330 {
331  float unified_coords[2];
332  float pixel_coords[2];
333 
334  /* Convert the corners into search space coordinates. */
335  for (int i = 0; i < 4; i++) {
337  frame_width, frame_height, marker, marker->pattern_corners[i], pixel_coords);
338  search_pixel_x[i] = pixel_coords[0] - 0.5f;
339  search_pixel_y[i] = pixel_coords[1] - 0.5f;
340  }
341 
342  /* Convert the center position (aka "pos"); this is the origin */
343  unified_coords[0] = 0.0f;
344  unified_coords[1] = 0.0f;
345  marker_unified_to_search_pixel(frame_width, frame_height, marker, unified_coords, pixel_coords);
346 
347  search_pixel_x[4] = pixel_coords[0] - 0.5f;
348  search_pixel_y[4] = pixel_coords[1] - 0.5f;
349 }
350 
352  int frame_height,
353  MovieTrackingMarker *marker,
354  const double search_pixel_x[5],
355  const double search_pixel_y[5])
356 {
357  float marker_unified[2];
358  float search_pixel[2];
359 
360  /* Convert the corners into search space coordinates. */
361  for (int i = 0; i < 4; i++) {
362  search_pixel[0] = search_pixel_x[i] + 0.5;
363  search_pixel[1] = search_pixel_y[i] + 0.5;
365  frame_width, frame_height, marker, search_pixel, marker->pattern_corners[i]);
366  }
367 
368  /* Convert the center position (aka "pos"); this is the origin */
369  search_pixel[0] = search_pixel_x[4] + 0.5;
370  search_pixel[1] = search_pixel_y[4] + 0.5;
371  search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker_unified);
372 
373  /* If the tracker tracked nothing, then "marker_unified" would be zero.
374  * Otherwise, the entire patch shifted, and that delta should be applied to
375  * all the coordinates.
376  */
377  for (int i = 0; i < 4; i++) {
378  marker->pattern_corners[i][0] -= marker_unified[0];
379  marker->pattern_corners[i][1] -= marker_unified[1];
380  }
381 
382  marker->pos[0] += marker_unified[0];
383  marker->pos[1] += marker_unified[1];
384 }
385 
388 /* -------------------------------------------------------------------- */
393  const MovieTrackingMarker *ref_marker,
394  bool before,
395  bool overwrite)
396 {
397  MovieTrackingMarker marker_new;
398 
399  marker_new = *ref_marker;
400  marker_new.flag &= ~MARKER_TRACKED;
401  marker_new.flag |= MARKER_DISABLED;
402 
403  if (before) {
404  marker_new.framenr--;
405  }
406  else {
407  marker_new.framenr++;
408  }
409 
410  if (overwrite || !BKE_tracking_track_has_marker_at_frame(track, marker_new.framenr)) {
411  BKE_tracking_marker_insert(track, &marker_new);
412  }
413 }
414 
416  const MovieTrackingCamera *camera, libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
417 {
418  switch (camera->distortion_model) {
420  camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_POLYNOMIAL;
421  camera_intrinsics_options->polynomial_k1 = camera->k1;
422  camera_intrinsics_options->polynomial_k2 = camera->k2;
423  camera_intrinsics_options->polynomial_k3 = camera->k3;
424  camera_intrinsics_options->polynomial_p1 = 0.0;
425  camera_intrinsics_options->polynomial_p2 = 0.0;
426  return;
427 
429  camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_DIVISION;
430  camera_intrinsics_options->division_k1 = camera->division_k1;
431  camera_intrinsics_options->division_k2 = camera->division_k2;
432  return;
433 
435  camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_NUKE;
436  camera_intrinsics_options->nuke_k1 = camera->nuke_k1;
437  camera_intrinsics_options->nuke_k2 = camera->nuke_k2;
438  return;
440  camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_BROWN;
441  camera_intrinsics_options->brown_k1 = camera->brown_k1;
442  camera_intrinsics_options->brown_k2 = camera->brown_k2;
443  camera_intrinsics_options->brown_k3 = camera->brown_k3;
444  camera_intrinsics_options->brown_k4 = camera->brown_k4;
445  camera_intrinsics_options->brown_p1 = camera->brown_p1;
446  camera_intrinsics_options->brown_p2 = camera->brown_p2;
447  return;
448  }
449 
450  /* Unknown distortion model, which might be due to opening newer file in older Blender.
451  * Fallback to a known and supported model with 0 distortion. */
452  camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_POLYNOMIAL;
453  camera_intrinsics_options->polynomial_k1 = 0.0;
454  camera_intrinsics_options->polynomial_k2 = 0.0;
455  camera_intrinsics_options->polynomial_k3 = 0.0;
456  camera_intrinsics_options->polynomial_p1 = 0.0;
457  camera_intrinsics_options->polynomial_p2 = 0.0;
458 }
459 
461  const libmv_CameraIntrinsicsOptions *camera_intrinsics_options, MovieTrackingCamera *camera)
462 {
463  switch (camera_intrinsics_options->distortion_model) {
465  camera->distortion_model = TRACKING_DISTORTION_MODEL_POLYNOMIAL;
466  camera->k1 = camera_intrinsics_options->polynomial_k1;
467  camera->k2 = camera_intrinsics_options->polynomial_k2;
468  camera->k3 = camera_intrinsics_options->polynomial_k3;
469  return;
470 
472  camera->distortion_model = TRACKING_DISTORTION_MODEL_DIVISION;
473  camera->division_k1 = camera_intrinsics_options->division_k1;
474  camera->division_k2 = camera_intrinsics_options->division_k2;
475  return;
476 
478  camera->distortion_model = TRACKING_DISTORTION_MODEL_NUKE;
479  camera->nuke_k1 = camera_intrinsics_options->nuke_k1;
480  camera->nuke_k2 = camera_intrinsics_options->nuke_k2;
481  return;
483  camera->distortion_model = TRACKING_DISTORTION_MODEL_BROWN;
484  camera->brown_k1 = camera_intrinsics_options->brown_k1;
485  camera->brown_k2 = camera_intrinsics_options->brown_k2;
486  camera->brown_k3 = camera_intrinsics_options->brown_k3;
487  camera->brown_k4 = camera_intrinsics_options->brown_k4;
488  camera->brown_p1 = camera_intrinsics_options->brown_p1;
489  camera->brown_p2 = camera_intrinsics_options->brown_p2;
490  return;
491  }
492 
493  /* Libmv returned distortion model which is not known to Blender. This is a logical error in code
494  * and Blender side is to be updated to match Libmv. */
495  BLI_assert_msg(0, "Unknown distortion model");
496 }
497 
499  MovieTracking *tracking,
500  int calibration_width,
501  int calibration_height,
502  libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
503 {
504  MovieTrackingCamera *camera = &tracking->camera;
505  float aspy = 1.0f / tracking->camera.pixel_aspect;
506 
507  camera_intrinsics_options->num_threads = BLI_system_thread_count();
508 
509  camera_intrinsics_options->focal_length = camera->focal;
510 
511  camera_intrinsics_options->principal_point_x = camera->principal[0];
512  camera_intrinsics_options->principal_point_y = camera->principal[1] * aspy;
513 
514  distortion_model_parameters_from_tracking(camera, camera_intrinsics_options);
515 
516  camera_intrinsics_options->image_width = calibration_width;
517  camera_intrinsics_options->image_height = (int)(calibration_height * aspy);
518 }
519 
521  MovieTracking *tracking, const libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
522 {
523  float aspy = 1.0f / tracking->camera.pixel_aspect;
524  MovieTrackingCamera *camera = &tracking->camera;
525 
526  camera->focal = camera_intrinsics_options->focal_length;
527 
528  camera->principal[0] = camera_intrinsics_options->principal_point_x;
529  camera->principal[1] = camera_intrinsics_options->principal_point_y / (double)aspy;
530 
531  distortion_model_parameters_from_options(camera_intrinsics_options, camera);
532 }
533 
535  int current_frame,
536  bool backwards)
537 {
538  MovieTrackingMarker *marker_keyed = NULL;
539  MovieTrackingMarker *marker_keyed_fallback = NULL;
540  int a = BKE_tracking_marker_get(track, current_frame) - track->markers;
541 
542  while (a >= 0 && a < track->markersnr) {
543  int next = backwards ? a + 1 : a - 1;
544  bool is_keyframed = false;
545  MovieTrackingMarker *cur_marker = &track->markers[a];
546  MovieTrackingMarker *next_marker = NULL;
547 
548  if (next >= 0 && next < track->markersnr) {
549  next_marker = &track->markers[next];
550  }
551 
552  if ((cur_marker->flag & MARKER_DISABLED) == 0) {
553  /* If it'll happen so we didn't find a real keyframe marker,
554  * fallback to the first marker in current tracked segment
555  * as a keyframe.
556  */
557  if (next_marker == NULL) {
558  /* Could happen when trying to get reference marker for the fist
559  * one on the segment which isn't surrounded by disabled markers.
560  *
561  * There's no really good choice here, just use the reference
562  * marker which looks correct..
563  */
564  if (marker_keyed_fallback == NULL) {
565  marker_keyed_fallback = cur_marker;
566  }
567  }
568  else if (next_marker->flag & MARKER_DISABLED) {
569  if (marker_keyed_fallback == NULL) {
570  marker_keyed_fallback = cur_marker;
571  }
572  }
573 
574  is_keyframed |= (cur_marker->flag & MARKER_TRACKED) == 0;
575  }
576 
577  if (is_keyframed) {
578  marker_keyed = cur_marker;
579 
580  break;
581  }
582 
583  a = next;
584  }
585 
586  if (marker_keyed == NULL) {
587  marker_keyed = marker_keyed_fallback;
588  }
589 
590  return marker_keyed;
591 }
592 
595 /* -------------------------------------------------------------------- */
600  int clip_index,
601  int frame)
602 {
603  MovieClip *clip;
604  MovieClipUser user;
605  ImBuf *ibuf;
606  int scene_frame;
607 
608  BLI_assert(clip_index < accessor->num_clips);
609 
610  clip = accessor->clips[clip_index];
611  scene_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, frame);
612  BKE_movieclip_user_set_frame(&user, scene_frame);
614  user.render_flag = 0;
615  ibuf = BKE_movieclip_get_ibuf(clip, &user);
616 
617  return ibuf;
618 }
619 
621 {
622  ImBuf *grayscale = IMB_allocImBuf(ibuf->x, ibuf->y, 32, 0);
623 
624  BLI_assert(ELEM(ibuf->channels, 3, 4));
625 
626  /* TODO(sergey): Bummer, currently IMB API only allows to create 4 channels
627  * float buffer, so we do it manually here.
628  *
629  * Will generalize it later.
630  */
631  const size_t size = (size_t)grayscale->x * (size_t)grayscale->y * sizeof(float);
632  grayscale->channels = 1;
633  if ((grayscale->rect_float = MEM_callocN(size, "tracking grayscale image")) != NULL) {
634  grayscale->mall |= IB_rectfloat;
635  grayscale->flags |= IB_rectfloat;
636 
637  for (int i = 0; i < grayscale->x * grayscale->y; i++) {
638  const float *pixel = ibuf->rect_float + ibuf->channels * i;
639 
640  grayscale->rect_float[i] = 0.2126f * pixel[0] + 0.7152f * pixel[1] + 0.0722f * pixel[2];
641  }
642  }
643 
644  return grayscale;
645 }
646 
647 static void ibuf_to_float_image(const ImBuf *ibuf, libmv_FloatImage *float_image)
648 {
649  BLI_assert(ibuf->rect_float != NULL);
650  float_image->buffer = ibuf->rect_float;
651  float_image->width = ibuf->x;
652  float_image->height = ibuf->y;
653  float_image->channels = ibuf->channels;
654 }
655 
657 {
658  ImBuf *ibuf = IMB_allocImBuf(float_image->width, float_image->height, 32, 0);
659  size_t size = (size_t)ibuf->x * (size_t)ibuf->y * float_image->channels * sizeof(float);
660  ibuf->channels = float_image->channels;
661  if ((ibuf->rect_float = MEM_callocN(size, "tracking grayscale image")) != NULL) {
662  ibuf->mall |= IB_rectfloat;
663  ibuf->flags |= IB_rectfloat;
664 
665  memcpy(ibuf->rect_float, float_image->buffer, size);
666  }
667  return ibuf;
668 }
669 
671  int clip_index,
672  int frame,
674  int downscale,
675  const libmv_Region *region,
677 {
678  /* First try to get fully processed image from the cache. */
679  CACHE_PRINTF("Calculate new buffer for frame %d\n", frame);
680  /* And now we do postprocessing of the original frame. */
681  ImBuf *orig_ibuf = accessor_get_preprocessed_ibuf(accessor, clip_index, frame);
682  if (orig_ibuf == NULL) {
683  return NULL;
684  }
685  ImBuf *final_ibuf;
686  /* Cut a region if requested. */
687  if (region != NULL) {
688  int width = region->max[0] - region->min[0], height = region->max[1] - region->min[1];
689 
690  /* If the requested region goes outside of the actual frame we still
691  * return the requested region size, but only fill it's partially with
692  * the data we can.
693  */
694  int clamped_origin_x = max_ii((int)region->min[0], 0),
695  clamped_origin_y = max_ii((int)region->min[1], 0);
696  int dst_offset_x = clamped_origin_x - (int)region->min[0],
697  dst_offset_y = clamped_origin_y - (int)region->min[1];
698  int clamped_width = width - dst_offset_x, clamped_height = height - dst_offset_y;
699  clamped_width = min_ii(clamped_width, orig_ibuf->x - clamped_origin_x);
700  clamped_height = min_ii(clamped_height, orig_ibuf->y - clamped_origin_y);
701 
702  final_ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat);
703 
704  if (orig_ibuf->rect_float != NULL) {
705  IMB_rectcpy(final_ibuf,
706  orig_ibuf,
707  dst_offset_x,
708  dst_offset_y,
709  clamped_origin_x,
710  clamped_origin_y,
711  clamped_width,
712  clamped_height);
713  }
714  else {
715  /* TODO(sergey): We don't do any color space or alpha conversion
716  * here. Probably Libmv is better to work in the linear space,
717  * but keep sRGB space here for compatibility for now.
718  */
719  for (int y = 0; y < clamped_height; y++) {
720  for (int x = 0; x < clamped_width; x++) {
721  int src_x = x + clamped_origin_x, src_y = y + clamped_origin_y;
722  int dst_x = x + dst_offset_x, dst_y = y + dst_offset_y;
723  int dst_index = (dst_y * width + dst_x) * 4,
724  src_index = (src_y * orig_ibuf->x + src_x) * 4;
725  rgba_uchar_to_float(final_ibuf->rect_float + dst_index,
726  (unsigned char *)orig_ibuf->rect + src_index);
727  }
728  }
729  }
730  }
731  else {
732  /* Libmv only works with float images,
733  *
734  * This would likely make it so loads of float buffers are being stored
735  * in the cache which is nice on the one hand (faster re-use of the
736  * frames) but on the other hand it bumps the memory usage up.
737  */
739  IMB_float_from_rect(orig_ibuf);
741  final_ibuf = orig_ibuf;
742  }
743  /* Downscale if needed. */
744  if (downscale > 0) {
745  if (final_ibuf == orig_ibuf) {
746  final_ibuf = IMB_dupImBuf(orig_ibuf);
747  }
748  IMB_scaleImBuf(final_ibuf, orig_ibuf->x / (1 << downscale), orig_ibuf->y / (1 << downscale));
749  }
750  /* Apply possible transformation. */
751  if (transform != NULL) {
752  libmv_FloatImage input_image, output_image;
753  ibuf_to_float_image(final_ibuf, &input_image);
754  libmv_frameAccessorgetTransformRun(transform, &input_image, &output_image);
755  if (final_ibuf != orig_ibuf) {
756  IMB_freeImBuf(final_ibuf);
757  }
758  final_ibuf = float_image_to_ibuf(&output_image);
759  libmv_floatImageDestroy(&output_image);
760  }
761  /* Transform number of channels. */
763  BLI_assert(ELEM(orig_ibuf->channels, 3, 4));
764  /* pass */
765  }
766  else /* if (input_mode == LIBMV_IMAGE_MODE_MONO) */ {
768  if (final_ibuf->channels != 1) {
769  ImBuf *grayscale_ibuf = make_grayscale_ibuf_copy(final_ibuf);
770  if (final_ibuf != orig_ibuf) {
771  /* We dereference original frame later. */
772  IMB_freeImBuf(final_ibuf);
773  }
774  final_ibuf = grayscale_ibuf;
775  }
776  }
777  /* It's possible processing still didn't happen at this point,
778  * but we really need a copy of the buffer to be transformed
779  * and to be put to the cache.
780  */
781  if (final_ibuf == orig_ibuf) {
782  final_ibuf = IMB_dupImBuf(orig_ibuf);
783  }
784  IMB_freeImBuf(orig_ibuf);
785  return final_ibuf;
786 }
787 
789  int clip_index,
790  int frame,
792  int downscale,
793  const libmv_Region *region,
795  float **destination,
796  int *width,
797  int *height,
798  int *channels)
799 {
801  ImBuf *ibuf;
802 
803  BLI_assert(clip_index >= 0 && clip_index < accessor->num_clips);
804 
805  ibuf = accessor_get_ibuf(accessor, clip_index, frame, input_mode, downscale, region, transform);
806 
807  if (ibuf) {
808  *destination = ibuf->rect_float;
809  *width = ibuf->x;
810  *height = ibuf->y;
811  *channels = ibuf->channels;
812  }
813  else {
814  *destination = NULL;
815  *width = 0;
816  *height = 0;
817  *channels = 0;
818  }
819 
820  return ibuf;
821 }
822 
824 {
825  ImBuf *ibuf = (ImBuf *)cache_key;
826  IMB_freeImBuf(ibuf);
827 }
828 
830  int clip_index,
831  int frame,
832  int track_index,
833  const libmv_Region *region,
834  float **r_destination,
835  int *r_width,
836  int *r_height)
837 {
838  /* Perform sanity checks first. */
840  BLI_assert(clip_index < accessor->num_clips);
841  BLI_assert(track_index < accessor->num_tracks);
842  MovieTrackingTrack *track = accessor->tracks[track_index];
843  /* Early output, track does not use mask. */
844  if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) == 0) {
845  return NULL;
846  }
847  MovieClip *clip = accessor->clips[clip_index];
848  /* Construct fake user so we can access movie clip. */
849  MovieClipUser user;
850  int scene_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, frame);
851  BKE_movieclip_user_set_frame(&user, scene_frame);
853  user.render_flag = 0;
854  /* Get frame width and height so we can convert stroke coordinates
855  * and other things from normalized to pixel space.
856  */
857  int frame_width, frame_height;
858  BKE_movieclip_get_size(clip, &user, &frame_width, &frame_height);
859  /* Actual mask sampling. */
860  MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, frame);
861  const float region_min[2] = {
862  region->min[0] - marker->pos[0] * frame_width,
863  region->min[1] - marker->pos[1] * frame_height,
864  };
865  const float region_max[2] = {
866  region->max[0] - marker->pos[0] * frame_width,
867  region->max[1] - marker->pos[1] * frame_height,
868  };
869  *r_destination = tracking_track_get_mask_for_region(
870  frame_width, frame_height, region_min, region_max, track);
871  *r_width = region->max[0] - region->min[0];
872  *r_height = region->max[1] - region->min[1];
873  return *r_destination;
874 }
875 
877 {
878  if (cache_key != NULL) {
879  float *mask = (float *)cache_key;
880  MEM_freeN(mask);
881  }
882 }
883 
885  int num_clips,
887  int num_tracks)
888 {
890  "tracking image accessor");
891 
892  BLI_assert(num_clips <= MAX_ACCESSOR_CLIP);
893 
894  memcpy(accessor->clips, clips, num_clips * sizeof(MovieClip *));
895  accessor->num_clips = num_clips;
896 
897  accessor->tracks = MEM_malloc_arrayN(
898  num_tracks, sizeof(MovieTrackingTrack *), "image accessor tracks");
899  memcpy(accessor->tracks, tracks, num_tracks * sizeof(MovieTrackingTrack *));
900  accessor->num_tracks = num_tracks;
901 
907 
908  BLI_spin_init(&accessor->cache_lock);
909 
910  return accessor;
911 }
912 
914 {
916  BLI_spin_end(&accessor->cache_lock);
917  MEM_freeN(accessor->tracks);
918  MEM_freeN(accessor);
919 }
920 
typedef float(TangentPoint)[2]
void BKE_movieclip_user_set_frame(struct MovieClipUser *user, int framenr)
Definition: movieclip.c:1614
void BKE_movieclip_get_size(struct MovieClip *clip, struct MovieClipUser *user, int *width, int *height)
Definition: movieclip.c:1520
struct ImBuf * BKE_movieclip_get_ibuf(struct MovieClip *clip, struct MovieClipUser *user)
Definition: movieclip.c:1329
float BKE_movieclip_remap_clip_to_scene_frame(const struct MovieClip *clip, float framenr)
struct MovieTrackingTrack * BKE_tracking_track_duplicate(struct MovieTrackingTrack *track)
Definition: tracking.c:576
struct MovieTrackingMarker * BKE_tracking_marker_insert(struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker)
Definition: tracking.c:1302
struct MovieTrackingObject * BKE_tracking_object_add(struct MovieTracking *tracking, const char *name)
Definition: tracking.c:1998
struct MovieTrackingMarker * BKE_tracking_marker_get_exact(struct MovieTrackingTrack *track, int framenr)
Definition: tracking.c:1457
void BKE_tracking_track_free(struct MovieTrackingTrack *track)
Definition: tracking.c:606
bool BKE_tracking_track_has_marker_at_frame(struct MovieTrackingTrack *track, int framenr)
Definition: tracking.c:722
struct MovieTrackingObject * BKE_tracking_object_get_named(struct MovieTracking *tracking, const char *name)
Definition: tracking.c:2077
struct MovieTrackingMarker * BKE_tracking_marker_get(struct MovieTrackingTrack *track, int framenr)
Definition: tracking.c:1424
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:715
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:734
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:710
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:863
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4])
Definition: math_color.c:383
MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
bool BLI_uniquename(struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_len)
Definition: string_utils.c:309
void BLI_thread_unlock(int type)
Definition: threads.cc:361
@ LOCK_MOVIECLIP
Definition: BLI_threads.h:71
void BLI_thread_lock(int type)
Definition: threads.cc:356
int BLI_system_thread_count(void)
Definition: threads.cc:281
void BLI_spin_init(SpinLock *spin)
Definition: threads.cc:419
void BLI_spin_unlock(SpinLock *spin)
Definition: threads.cc:452
void BLI_spin_lock(SpinLock *spin)
Definition: threads.cc:433
void BLI_spin_end(SpinLock *spin)
Definition: threads.cc:467
#define ELEM(...)
#define CTX_DATA_(context, msgid)
#define BLT_I18NCONTEXT_ID_MOVIECLIP
typedef double(DMatrix)[4][4]
@ MCLIP_PROXY_RENDER_SIZE_FULL
@ TRACK_ALGORITHM_FLAG_USE_MASK
@ MARKER_TRACKED
@ MARKER_DISABLED
@ TRACKING_DISTORTION_MODEL_DIVISION
@ TRACKING_DISTORTION_MODEL_POLYNOMIAL
@ TRACKING_DISTORTION_MODEL_NUKE
@ TRACKING_DISTORTION_MODEL_BROWN
long input_mode
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
void IMB_float_from_rect(struct ImBuf *ibuf)
Definition: divers.c:805
bool IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy)
Definition: scaling.c:1644
struct ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
Definition: allocimbuf.c:500
struct ImBuf * IMB_dupImBuf(const struct ImBuf *ibuf1)
void IMB_rectcpy(struct ImBuf *dbuf, const struct ImBuf *sbuf, int destx, int desty, int srcx, int srcy, int width, int height)
Contains defines and structs used throughout the imbuf module.
@ IB_rectfloat
Read Guarded memory(de)allocation.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between camera
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
void * user_data
void libmv_FrameAccessorDestroy(libmv_FrameAccessor *frame_accessor)
void libmv_frameAccessorgetTransformRun(const libmv_FrameTransform *transform, const libmv_FloatImage *input_image, libmv_FloatImage *output_image)
libmv_FrameAccessor * libmv_FrameAccessorNew(libmv_FrameAccessorUserData *user_data, libmv_GetImageCallback get_image_callback, libmv_ReleaseImageCallback release_image_callback, libmv_GetMaskForTrackCallback get_mask_for_track_callback, libmv_ReleaseMaskCallback release_mask_callback)
void IMB_freeImBuf(ImBuf *UNUSED(ibuf))
@ LIBMV_DISTORTION_MODEL_POLYNOMIAL
@ LIBMV_DISTORTION_MODEL_NUKE
@ LIBMV_DISTORTION_MODEL_BROWN
@ LIBMV_DISTORTION_MODEL_DIVISION
struct libmv_FrameTransform libmv_FrameTransform
void * libmv_CacheKey
struct libmv_FrameAccessorUserData libmv_FrameAccessorUserData
@ LIBMV_IMAGE_MODE_RGBA
@ LIBMV_IMAGE_MODE_MONO
void libmv_floatImageDestroy(libmv_FloatImage *image)
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
static ulong * next
static unsigned a[3]
Definition: RandGen.cpp:78
SocketIndexByIdentifierMap * map
int channels
unsigned int * rect
float * rect_float
void * first
Definition: DNA_listBase.h:31
MovieTrackingMarker * markers
struct MovieTrackingTrack * next
struct MovieTrackingTrack * prev
MovieTrackingCamera camera
struct MovieTrackingTrack ** tracks
struct MovieClip * clips[MAX_ACCESSOR_CLIP]
struct libmv_FrameAccessor * libmv_accessor
float min[2]
Definition: intern/region.h:12
float max[2]
Definition: intern/region.h:13
float * tracking_track_get_mask_for_region(int frame_width, int frame_height, const float region_min[2], const float region_max[2], MovieTrackingTrack *track)
Definition: tracking.c:1203
ListBase tracks
Definition: tracking.c:60
#define MAX_ACCESSOR_CLIP
static void accessor_release_image_callback(libmv_CacheKey cache_key)
static void pixel_to_unified(int frame_width, int frame_height, const float pixel_coords[2], float unified_coords[2])
static ImBuf * float_image_to_ibuf(libmv_FloatImage *float_image)
static void unified_to_pixel(int frame_width, int frame_height, const float unified_coords[2], float pixel_coords[2])
static libmv_CacheKey accessor_get_mask_for_track_callback(libmv_FrameAccessorUserData *user_data, int clip_index, int frame, int track_index, const libmv_Region *region, float **r_destination, int *r_width, int *r_height)
void tracking_marker_insert_disabled(MovieTrackingTrack *track, const MovieTrackingMarker *ref_marker, bool before, bool overwrite)
static void search_pixel_to_marker_unified(int frame_width, int frame_height, const MovieTrackingMarker *marker, const float search_pixel[2], float marker_unified[2])
int tracks_map_get_size(TracksMap *map)
Definition: tracking_util.c:77
static ImBuf * accessor_get_preprocessed_ibuf(TrackingImageAccessor *accessor, int clip_index, int frame)
static void ibuf_to_float_image(const ImBuf *ibuf, libmv_FloatImage *float_image)
static libmv_CacheKey accessor_get_image_callback(struct libmv_FrameAccessorUserData *user_data, int clip_index, int frame, libmv_InputMode input_mode, int downscale, const libmv_Region *region, const libmv_FrameTransform *transform, float **destination, int *width, int *height, int *channels)
static void marker_unified_to_frame_pixel_coordinates(int frame_width, int frame_height, const MovieTrackingMarker *marker, const float marker_unified_coords[2], float frame_pixel_coords[2])
static void marker_unified_to_search_pixel(int frame_width, int frame_height, const MovieTrackingMarker *marker, const float marker_unified[2], float search_pixel[2])
static ImBuf * make_grayscale_ibuf_copy(ImBuf *ibuf)
void tracking_cameraIntrinscisOptionsFromTracking(MovieTracking *tracking, int calibration_width, int calibration_height, libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
void tracking_get_marker_coords_for_tracking(int frame_width, int frame_height, const MovieTrackingMarker *marker, double search_pixel_x[5], double search_pixel_y[5])
void tracks_map_get_indexed_element(TracksMap *map, int index, MovieTrackingTrack **track, void **customdata)
Definition: tracking_util.c:82
void tracks_map_free(TracksMap *map, void(*customdata_free)(void *customdata))
static void distortion_model_parameters_from_options(const libmv_CameraIntrinsicsOptions *camera_intrinsics_options, MovieTrackingCamera *camera)
MovieTrackingMarker * tracking_get_keyframed_marker(MovieTrackingTrack *track, int current_frame, bool backwards)
TrackingImageAccessor * tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR_CLIP], int num_clips, MovieTrackingTrack **tracks, int num_tracks)
static void marker_to_frame_unified(const MovieTrackingMarker *marker, const float marker_unified_coords[2], float frame_unified_coords[2])
#define CACHE_PRINTF(...)
Definition: tracking_util.c:44
void tracking_trackingCameraFromIntrinscisOptions(MovieTracking *tracking, const libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
static void distortion_model_parameters_from_tracking(const MovieTrackingCamera *camera, libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *customdata)
Definition: tracking_util.c:94
void tracking_image_accessor_destroy(TrackingImageAccessor *accessor)
TracksMap * tracks_map_new(const char *object_name, bool is_camera, int num_tracks, int customdata_size)
Definition: tracking_util.c:51
static void accessor_release_mask_callback(libmv_CacheKey cache_key)
void tracking_set_marker_coords_from_tracking(int frame_width, int frame_height, MovieTrackingMarker *marker, const double search_pixel_x[5], const double search_pixel_y[5])
static ImBuf * accessor_get_ibuf(TrackingImageAccessor *accessor, int clip_index, int frame, libmv_InputMode input_mode, int downscale, const libmv_Region *region, const libmv_FrameTransform *transform)
void tracking_get_search_origin_frame_pixel(int frame_width, int frame_height, const MovieTrackingMarker *marker, float frame_pixel[2])
void tracks_map_merge(TracksMap *map, MovieTracking *tracking)