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