Blender V4.3
tracking_region_tracker.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
12#include "MEM_guardedalloc.h"
13
14#include "DNA_defaults.h"
15#include "DNA_movieclip_types.h"
16
17#include "BLI_threads.h"
18#include "BLI_utildefines.h"
19
20#include "BKE_movieclip.h"
21#include "BKE_tracking.h"
22
23#include "IMB_imbuf.hh"
24#include "IMB_imbuf_types.hh"
25
26#include "libmv-capi.h"
27#include "tracking_private.h"
28
29/* **** utility functions for tracking **** */
30
32static void float_rgba_to_gray(const float *rgba,
33 float *gray,
34 int num_pixels,
35 float weight_red,
36 float weight_green,
37 float weight_blue)
38{
39 for (int i = 0; i < num_pixels; i++) {
40 const float *pixel = rgba + 4 * i;
41
42 gray[i] = weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2];
43 }
44}
45
46static void uint8_rgba_to_float_gray(const uchar *rgba,
47 float *gray,
48 int num_pixels,
49 float weight_red,
50 float weight_green,
51 float weight_blue)
52{
53 for (int i = 0; i < num_pixels; i++) {
54 const uchar *pixel = rgba + i * 4;
55
56 gray[i] = (weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]) / 255.0f;
57 }
58}
59
61static float *track_get_search_floatbuf(ImBuf *ibuf,
62 MovieTrackingTrack *track,
63 MovieTrackingMarker *marker,
64 int *r_width,
65 int *r_height)
66{
67 ImBuf *searchibuf;
68 float *gray_pixels;
69 int width, height;
70
71 searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, false, true);
72
73 if (!searchibuf) {
74 *r_width = 0;
75 *r_height = 0;
76 return nullptr;
77 }
78
79 width = searchibuf->x;
80 height = searchibuf->y;
81
82 gray_pixels = MEM_cnew_array<float>(width * height, "tracking floatBuf");
83
84 if (searchibuf->float_buffer.data) {
86 searchibuf->float_buffer.data, gray_pixels, width * height, 0.2126f, 0.7152f, 0.0722f);
87 }
88 else {
90 searchibuf->byte_buffer.data, gray_pixels, width * height, 0.2126f, 0.7152f, 0.0722f);
91 }
92
93 IMB_freeImBuf(searchibuf);
94
95 *r_width = width;
96 *r_height = height;
97
98 return gray_pixels;
99}
100
101/* Get image buffer for a given frame
102 *
103 * Frame is in clip space.
104 */
106 MovieClipUser *user,
107 int clip_flag,
108 int framenr)
109{
110 ImBuf *ibuf;
111 MovieClipUser new_user = *user;
112
113 new_user.framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, framenr);
114
115 ibuf = BKE_movieclip_get_ibuf_flag(clip, &new_user, clip_flag, MOVIECLIP_CACHE_SKIP);
116
117 return ibuf;
118}
119
120/* Get image buffer for previous marker's keyframe. */
122 MovieClipUser *user,
123 int clip_flag,
124 MovieTrackingTrack *track,
125 int curfra,
126 bool backwards,
127 MovieTrackingMarker **r_marker_keyed)
128{
129 MovieTrackingMarker *marker_keyed;
130 int keyed_framenr;
131
132 marker_keyed = tracking_get_keyframed_marker(track, curfra, backwards);
133 if (marker_keyed == nullptr) {
134 return nullptr;
135 }
136
137 keyed_framenr = marker_keyed->framenr;
138
139 *r_marker_keyed = marker_keyed;
140
141 return tracking_context_get_frame_ibuf(clip, user, clip_flag, keyed_framenr);
142}
143
144/* Get image buffer which is used as reference for track. */
146 MovieClipUser *user,
147 int clip_flag,
148 MovieTrackingTrack *track,
149 int curfra,
150 bool backwards,
151 MovieTrackingMarker **reference_marker)
152{
153 ImBuf *ibuf = nullptr;
154
155 if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
157 clip, user, clip_flag, track, curfra, backwards, reference_marker);
158 }
159 else {
160 ibuf = tracking_context_get_frame_ibuf(clip, user, clip_flag, curfra);
161
162 /* use current marker as keyframed position */
163 *reference_marker = BKE_tracking_marker_get(track, curfra);
164 }
165
166 return ibuf;
167}
168
170 float *mask,
171 const bool is_backwards,
173{
175
176 /* TODO(sergey): Use explicit conversion, so that options are decoupled between the Libmv library
177 * and enumerator values in DNA. */
178 options->motion_model = track->motion_model;
179
180 options->use_brute = ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_BRUTE) != 0);
181
182 options->use_normalization = ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_NORMALIZATION) !=
183 0);
184
185 options->num_iterations = 50;
186 options->minimum_correlation = track->minimum_correlation;
187 options->sigma = 0.9;
188
189 if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0) {
190 options->image1_mask = mask;
191 }
192 else {
193 options->image1_mask = nullptr;
194 }
195}
196
197/* Perform tracking from a reference_marker to destination_ibuf.
198 * Uses marker as an initial position guess.
199 *
200 * Returns truth if tracker returned success, puts result
201 * to dst_pixel_x and dst_pixel_y.
202 */
203static bool configure_and_run_tracker(ImBuf *destination_ibuf,
204 MovieTrackingTrack *track,
205 MovieTrackingMarker *reference_marker,
206 MovieTrackingMarker *marker,
207 float *reference_search_area,
208 int reference_search_area_width,
209 int reference_search_area_height,
210 float *mask,
211 const bool is_backward,
212 double dst_pixel_x[5],
213 double dst_pixel_y[5])
214{
215 /* To convert to the x/y split array format for libmv. */
216 double src_pixel_x[5], src_pixel_y[5];
217
218 /* Settings for the tracker */
221
222 float *patch_new;
223
224 int new_search_area_width, new_search_area_height;
225 int frame_width, frame_height;
226
227 bool tracked;
228
229 frame_width = destination_ibuf->x;
230 frame_height = destination_ibuf->y;
231
232 /* for now track to the same search area dimension as marker has got for current frame
233 * will make all tracked markers in currently tracked segment have the same search area
234 * size, but it's quite close to what is actually needed
235 */
236 patch_new = track_get_search_floatbuf(
237 destination_ibuf, track, marker, &new_search_area_width, &new_search_area_height);
238
239 /* configure the tracker */
240 tracking_configure_tracker(track, mask, is_backward, &options);
241
242 /* Convert the marker corners and center into pixel coordinates in the
243 * search/destination images. */
245 frame_width, frame_height, reference_marker, src_pixel_x, src_pixel_y);
247 frame_width, frame_height, marker, dst_pixel_x, dst_pixel_y);
248
249 if (patch_new == nullptr || reference_search_area == nullptr) {
250 return false;
251 }
252
253 /* run the tracker! */
254 tracked = libmv_trackRegion(&options,
255 reference_search_area,
256 reference_search_area_width,
257 reference_search_area_height,
258 patch_new,
259 new_search_area_width,
260 new_search_area_height,
261 src_pixel_x,
262 src_pixel_y,
263 &result,
264 dst_pixel_x,
265 dst_pixel_y);
266
267 MEM_freeN(patch_new);
268
269 return tracked;
270}
271
273 MovieTrackingMarker *marker,
274 bool backwards,
275 int *reference_framenr)
276{
277 const MovieTrackingMarker *first_marker = track->markers;
278 const MovieTrackingMarker *last_marker = track->markers + track->markersnr - 1;
279 MovieTrackingMarker *reference = backwards ? marker + 1 : marker - 1;
280
281 while (reference >= first_marker && reference <= last_marker &&
282 (reference->flag & MARKER_DISABLED) != 0)
283 {
284 if (backwards) {
285 reference++;
286 }
287 else {
288 reference--;
289 }
290 }
291
292 if (reference < first_marker || reference > last_marker) {
293 return false;
294 }
295
296 *reference_framenr = reference->framenr;
297 return (reference->flag & MARKER_DISABLED) == 0;
298}
299
301 MovieTrackingTrack *track,
302 MovieTrackingMarker *marker,
303 bool backwards)
304{
305 MovieTrackingMarker *reference_marker = nullptr;
306 ImBuf *reference_ibuf, *destination_ibuf;
307 float *search_area, *mask = nullptr;
308 int frame_width, frame_height;
309 int search_area_height, search_area_width;
310 int clip_flag = clip->flag & MCLIP_TIMECODE_FLAGS;
311 int reference_framenr;
313 double dst_pixel_x[5], dst_pixel_y[5];
314 bool tracked;
315
316 /* Construct a temporary clip used, used to acquire image buffers. */
318
319 BKE_movieclip_get_size(clip, &user, &frame_width, &frame_height);
320
321 /* Get an image buffer for reference frame, also gets reference marker. */
322 if (!refine_marker_reference_frame_get(track, marker, backwards, &reference_framenr)) {
323 return;
324 }
325
327 clip, &user, clip_flag, track, reference_framenr, backwards, &reference_marker);
328 if (reference_ibuf == nullptr) {
329 return;
330 }
331
332 /* Could not refine with self. */
333 if (reference_marker == marker) {
334 return;
335 }
336
337 /* Destination image buffer has got frame number corresponding to refining marker. */
338 destination_ibuf = BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag, MOVIECLIP_CACHE_SKIP);
339 if (destination_ibuf == nullptr) {
340 IMB_freeImBuf(reference_ibuf);
341 return;
342 }
343
344 /* Get search area from reference image. */
345 search_area = track_get_search_floatbuf(
346 reference_ibuf, track, reference_marker, &search_area_width, &search_area_height);
347
348 /* If needed, compute track's mask. */
349 if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0) {
350 mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker);
351 }
352
353 /* Run the tracker from reference frame to current one. */
354 tracked = configure_and_run_tracker(destination_ibuf,
355 track,
356 reference_marker,
357 marker,
358 search_area,
359 search_area_width,
360 search_area_height,
361 mask,
362 backwards,
363 dst_pixel_x,
364 dst_pixel_y);
365
366 /* Refine current marker's position if track was successful. */
367 if (tracked) {
369 frame_width, frame_height, marker, dst_pixel_x, dst_pixel_y);
370 marker->flag |= MARKER_TRACKED;
371 }
372
373 /* Free memory used for refining */
374 MEM_freeN(search_area);
375 if (mask) {
376 MEM_freeN(mask);
377 }
378 IMB_freeImBuf(reference_ibuf);
379 IMB_freeImBuf(destination_ibuf);
380}
#define MOVIECLIP_CACHE_SKIP
void BKE_movieclip_get_size(struct MovieClip *clip, const struct MovieClipUser *user, int *r_width, int *r_height)
float BKE_movieclip_remap_clip_to_scene_frame(const struct MovieClip *clip, float framenr)
struct ImBuf * BKE_movieclip_get_ibuf_flag(struct MovieClip *clip, const struct MovieClipUser *user, int flag, int cache_flag)
struct MovieTrackingMarker * BKE_tracking_marker_get(struct MovieTrackingTrack *track, int framenr)
Definition tracking.cc:1358
struct ImBuf * BKE_tracking_get_search_imbuf(const struct ImBuf *ibuf, const struct MovieTrackingTrack *track, const struct MovieTrackingMarker *marker, bool anchored, bool disable_channels)
float * BKE_tracking_track_get_mask(int frame_width, int frame_height, const struct MovieTrackingTrack *track, const struct MovieTrackingMarker *marker)
unsigned char uchar
#define DNA_struct_default_get(struct_name)
@ MCLIP_TIMECODE_FLAGS
@ TRACK_ALGORITHM_FLAG_USE_NORMALIZATION
@ TRACK_ALGORITHM_FLAG_USE_BRUTE
@ TRACK_ALGORITHM_FLAG_USE_MASK
@ MARKER_TRACKED
@ MARKER_DISABLED
@ TRACK_MATCH_KEYFRAME
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
CCL_NAMESPACE_BEGIN struct Options options
void IMB_freeImBuf(ImBuf *)
@ LIBMV_TRACK_REGION_FORWARD
@ LIBMV_TRACK_REGION_BACKWARD
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
ccl_device_inline float4 mask(const int4 mask, const float4 a)
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
MovieTrackingMarker * markers
int libmv_trackRegion(const libmv_TrackRegionOptions *, const float *, int, int, const float *, int, int, const double *x1, const double *y1, libmv_TrackRegionResult *result, double *x2, double *y2)
Definition stub.cc:24
void BKE_tracking_refine_marker(MovieClip *clip, MovieTrackingTrack *track, MovieTrackingMarker *marker, bool backwards)
static bool refine_marker_reference_frame_get(MovieTrackingTrack *track, MovieTrackingMarker *marker, bool backwards, int *reference_framenr)
static ImBuf * tracking_context_get_keyframed_ibuf(MovieClip *clip, MovieClipUser *user, int clip_flag, MovieTrackingTrack *track, int curfra, bool backwards, MovieTrackingMarker **r_marker_keyed)
static void float_rgba_to_gray(const float *rgba, float *gray, int num_pixels, float weight_red, float weight_green, float weight_blue)
static void uint8_rgba_to_float_gray(const uchar *rgba, float *gray, int num_pixels, float weight_red, float weight_green, float weight_blue)
static ImBuf * tracking_context_get_reference_ibuf(MovieClip *clip, MovieClipUser *user, int clip_flag, MovieTrackingTrack *track, int curfra, bool backwards, MovieTrackingMarker **reference_marker)
static bool configure_and_run_tracker(ImBuf *destination_ibuf, MovieTrackingTrack *track, MovieTrackingMarker *reference_marker, MovieTrackingMarker *marker, float *reference_search_area, int reference_search_area_width, int reference_search_area_height, float *mask, const bool is_backward, double dst_pixel_x[5], double dst_pixel_y[5])
static float * track_get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, int *r_width, int *r_height)
void tracking_configure_tracker(const MovieTrackingTrack *track, float *mask, const bool is_backwards, libmv_TrackRegionOptions *options)
static ImBuf * tracking_context_get_frame_ibuf(MovieClip *clip, MovieClipUser *user, int clip_flag, int framenr)
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])
MovieTrackingMarker * tracking_get_keyframed_marker(MovieTrackingTrack *track, int current_frame, bool backwards)
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])