Paparazzi UAS  v5.14.0_stable-0-g3f680d1
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
lucas_kanade.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 G. de Croon
3  * 2015 Freek van Tienen <freek.v.tienen@gmail.com>
4  * 2016 Hrvoje Brezak <hrvoje.brezak@gmail.com>
5  *
6  * This file is part of Paparazzi.
7  *
8  * Paparazzi is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2, or (at your option)
11  * any later version.
12  *
13  * Paparazzi is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Paparazzi; see the file COPYING. If not, see
20  * <http://www.gnu.org/licenses/>.
21  */
22 
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <math.h>
35 #include <string.h>
36 #include "lucas_kanade.h"
37 
38 
73 struct flow_t *opticFlowLK(struct image_t *new_img, struct image_t *old_img, struct point_t *points,
74  uint16_t *points_cnt, uint16_t half_window_size,
75  uint16_t subpixel_factor, uint8_t max_iterations, uint8_t step_threshold, uint8_t max_points, uint8_t pyramid_level,
76  uint8_t keep_bad_points)
77 {
78 
79  // if no pyramids, use the old code:
80  if (pyramid_level == 0) {
81  // use the old code in this case:
82  return opticFlowLK_flat(new_img, old_img, points, points_cnt, half_window_size, subpixel_factor, max_iterations,
83  step_threshold, max_points, keep_bad_points);
84  }
85 
86  // Allocate some memory for returning the vectors
87  struct flow_t *vectors = malloc(sizeof(struct flow_t) * max_points);
88 
89  // Determine patch sizes and initialize neighborhoods
90  uint16_t patch_size = 2 * half_window_size + 1;
91  // TODO: Feature management shows that this threshold rejects corners maybe too often, maybe another formula could be chosen
92  uint32_t error_threshold = (25 * 25) * (patch_size * patch_size);
93  uint16_t padded_patch_size = patch_size + 2;
94  uint16_t border_size = padded_patch_size / 2 + 2; // amount of padding added to images
95 
96  // Allocate memory for image pyramids
97  struct image_t *pyramid_old = malloc(sizeof(struct image_t) * (pyramid_level + 1));
98  struct image_t *pyramid_new = malloc(sizeof(struct image_t) * (pyramid_level + 1));
99 
100  // Build pyramid levels
101  pyramid_build(old_img, pyramid_old, pyramid_level, border_size);
102  pyramid_build(new_img, pyramid_new, pyramid_level, border_size);
103 
104  // Create the window images
105  struct image_t window_I, window_J, window_DX, window_DY, window_diff;
106  image_create(&window_I, padded_patch_size, padded_patch_size, IMAGE_GRAYSCALE);
107  image_create(&window_J, patch_size, patch_size, IMAGE_GRAYSCALE);
108  image_create(&window_DX, patch_size, patch_size, IMAGE_GRADIENT);
109  image_create(&window_DY, patch_size, patch_size, IMAGE_GRADIENT);
110  image_create(&window_diff, patch_size, patch_size, IMAGE_GRADIENT);
111 
112  // Iterate through pyramid levels
113  for (int8_t LVL = pyramid_level; LVL != -1; LVL--) {
114  uint16_t points_orig = *points_cnt;
115  *points_cnt = 0;
116  uint16_t new_p = 0;
117 
118  // Calculate the amount of points to skip
119  float skip_points = (points_orig > max_points) ? (float)points_orig / max_points : 1;
120 
121  // Go through all points
122  for (uint16_t i = 0; i < max_points && i < points_orig; i++) {
123  uint16_t p = i * skip_points;
124 
125  if (LVL == pyramid_level) {
126  // Convert point position on original image to a subpixel coordinate on the top pyramid level
127  vectors[new_p].pos.x = (points[p].x * subpixel_factor) >> pyramid_level;
128  vectors[new_p].pos.y = (points[p].y * subpixel_factor) >> pyramid_level;
129  vectors[new_p].flow_x = 0;
130  vectors[new_p].flow_y = 0;
131 
132  } else {
133  // (5) use calculated flow as initial flow estimation for next level of pyramid
134  vectors[new_p].pos.x = vectors[p].pos.x << 1;
135  vectors[new_p].pos.y = vectors[p].pos.y << 1;
136  vectors[new_p].flow_x = vectors[p].flow_x << 1;
137  vectors[new_p].flow_y = vectors[p].flow_y << 1;
138  }
139 
140  // If the pixel is outside original image, do not track it
141  if ((((int32_t) vectors[new_p].pos.x + vectors[new_p].flow_x) < 0)
142  || ((vectors[new_p].pos.x + vectors[new_p].flow_x) > (uint32_t)((pyramid_new[LVL].w - 1 - 2 * border_size)*
143  subpixel_factor))
144  || (((int32_t) vectors[new_p].pos.y + vectors[new_p].flow_y) < 0)
145  || ((vectors[new_p].pos.y + vectors[new_p].flow_y) > (uint32_t)((pyramid_new[LVL].h - 1 - 2 * border_size)*
146  subpixel_factor))) {
147  continue;
148  }
149 
150 
151  // (1) determine the subpixel neighborhood in the old image
152  image_subpixel_window(&pyramid_old[LVL], &window_I, &vectors[new_p].pos, subpixel_factor, border_size);
153 
154  // (2) get the x- and y- gradients
155  image_gradients(&window_I, &window_DX, &window_DY);
156 
157  // (3) determine the 'G'-matrix [sum(Axx) sum(Axy); sum(Axy) sum(Ayy)], where sum is over the window
158  int32_t G[4];
159  image_calculate_g(&window_DX, &window_DY, G);
160 
161  // calculate G's determinant in subpixel units:
162  int32_t Det = (G[0] * G[3] - G[1] * G[2]);
163 
164  // Check if the determinant is bigger than 1
165  if (Det < 1) {
166  continue;
167  }
168 
169  // (4) iterate over taking steps in the image to minimize the error:
170  bool tracked = true;
171 
172  for (uint8_t it = max_iterations; it--;) {
173  struct point_t new_point = { vectors[new_p].pos.x + vectors[new_p].flow_x,
174  vectors[new_p].pos.y + vectors[new_p].flow_y,
175  0, 0, 0
176  };
177 
178  // If the pixel is outside original image, do not track it
179  if ((((int32_t)vectors[new_p].pos.x + vectors[new_p].flow_x) < 0)
180  || (new_point.x > (uint32_t)((pyramid_new[LVL].w - 1 - 2 * border_size)*subpixel_factor))
181  || (((int32_t)vectors[new_p].pos.y + vectors[new_p].flow_y) < 0)
182  || (new_point.y > (uint32_t)((pyramid_new[LVL].h - 1 - 2 * border_size)*subpixel_factor))) {
183  tracked = false;
184  break;
185  }
186 
187  // [a] get the subpixel neighborhood in the new image
188  image_subpixel_window(&pyramid_new[LVL], &window_J, &new_point, subpixel_factor, border_size);
189 
190  // [b] determine the image difference between the two neighborhoods
191  uint32_t error = image_difference(&window_I, &window_J, &window_diff);
192 
193  if (error > error_threshold && it < max_iterations / 2) {
194  tracked = false;
195  break;
196  }
197 
198  int32_t b_x = image_multiply(&window_diff, &window_DX, NULL) / 255;
199  int32_t b_y = image_multiply(&window_diff, &window_DY, NULL) / 255;
200 
201 
202  // [d] calculate the additional flow step and possibly terminate the iteration
203  int16_t step_x = (((int64_t) G[3] * b_x - G[1] * b_y) * subpixel_factor) / Det;
204  int16_t step_y = (((int64_t) G[0] * b_y - G[2] * b_x) * subpixel_factor) / Det;
205 
206  vectors[new_p].flow_x = vectors[new_p].flow_x + step_x;
207  vectors[new_p].flow_y = vectors[new_p].flow_y + step_y;
208  vectors[new_p].error = error;
209 
210  // Check if we exceeded the treshold CHANGED made this better for 0.03
211  if ((abs(step_x) + abs(step_y)) < step_threshold) {
212  break;
213  }
214  } // lucas kanade step iteration
215 
216  // If we tracked the point we update the index and the count
217  if (tracked) {
218  new_p++;
219  (*points_cnt)++;
220  } else if (keep_bad_points) {
221  vectors[new_p].pos.x = 0;
222  vectors[new_p].pos.y = 0;
223  vectors[new_p].flow_x = 0;
224  vectors[new_p].flow_y = 0;
225  vectors[new_p].error = LARGE_FLOW_ERROR;
226  new_p++;
227  (*points_cnt)++;
228  }
229  } // go through all points
230 
231  } // LVL of pyramid
232 
233  // Free the images
234  image_free(&window_I);
235  image_free(&window_J);
236  image_free(&window_DX);
237  image_free(&window_DY);
238  image_free(&window_diff);
239 
240  for (int8_t i = pyramid_level; i != -1; i--) {
241  image_free(&pyramid_old[i]);
242  image_free(&pyramid_new[i]);
243  }
244  pyramid_old = NULL;
245  pyramid_new = NULL;
246 
247  // Return the vectors
248  return vectors;
249 }
250 
266 struct flow_t *opticFlowLK_flat(struct image_t *new_img, struct image_t *old_img, struct point_t *points,
267  uint16_t *points_cnt,
268  uint16_t half_window_size, uint16_t subpixel_factor, uint8_t max_iterations, uint8_t step_threshold,
269  uint16_t max_points, uint8_t keep_bad_points)
270 {
271  // A straightforward one-level implementation of Lucas-Kanade.
272  // For all points:
273  // (1) determine the subpixel neighborhood in the old image
274  // (2) get the x- and y- gradients
275  // (3) determine the 'G'-matrix [sum(Axx) sum(Axy); sum(Axy) sum(Ayy)], where sum is over the window
276  // (4) iterate over taking steps in the image to minimize the error:
277  // [a] get the subpixel neighborhood in the new image
278  // [b] determine the image difference between the two neighborhoods
279  // [c] calculate the 'b'-vector
280  // [d] calculate the additional flow step and possibly terminate the iteration
281 
282  // Allocate some memory for returning the vectors
283  struct flow_t *vectors = malloc(sizeof(struct flow_t) * max_points);
284  uint16_t new_p = 0;
285  uint16_t points_orig = *points_cnt;
286  *points_cnt = 0;
287 
288  // determine patch sizes and initialize neighborhoods
289  uint16_t patch_size = 2 * half_window_size;
290  uint32_t error_threshold = (25 * 25) * (patch_size * patch_size);
291  uint16_t padded_patch_size = patch_size + 2;
292 
293  // Create the window images
294  struct image_t window_I, window_J, window_DX, window_DY, window_diff;
295  image_create(&window_I, padded_patch_size, padded_patch_size, IMAGE_GRAYSCALE);
296  image_create(&window_J, patch_size, patch_size, IMAGE_GRAYSCALE);
297  image_create(&window_DX, patch_size, patch_size, IMAGE_GRADIENT);
298  image_create(&window_DY, patch_size, patch_size, IMAGE_GRADIENT);
299  image_create(&window_diff, patch_size, patch_size, IMAGE_GRADIENT);
300 
301  // Calculate the amount of points to skip
302  float skip_points = (points_orig > max_points) ? points_orig / max_points : 1;
303 
304  // Go through all points
305  for (uint16_t i = 0; i < max_points && i < points_orig; i++) {
306  uint16_t p = i * skip_points;
307 
308  // If the pixel is outside ROI, do not track it
309  if (points[p].x < half_window_size || (old_img->w - points[p].x) < half_window_size
310  || points[p].y < half_window_size || (old_img->h - points[p].y) < half_window_size) {
311  continue;
312  }
313 
314  // Convert the point to a subpixel coordinate
315  vectors[new_p].pos.x = points[p].x * subpixel_factor;
316  vectors[new_p].pos.y = points[p].y * subpixel_factor;
317  vectors[new_p].flow_x = 0;
318  vectors[new_p].flow_y = 0;
319 
320  // (1) determine the subpixel neighborhood in the old image
321  image_subpixel_window(old_img, &window_I, &vectors[new_p].pos, subpixel_factor, 0);
322 
323  // (2) get the x- and y- gradients
324  image_gradients(&window_I, &window_DX, &window_DY);
325 
326  // (3) determine the 'G'-matrix [sum(Axx) sum(Axy); sum(Axy) sum(Ayy)], where sum is over the window
327  int32_t G[4];
328  image_calculate_g(&window_DX, &window_DY, G);
329 
330  // calculate G's determinant in subpixel units:
331  int32_t Det = (G[0] * G[3] - G[1] * G[2]) / subpixel_factor;
332 
333  // Check if the determinant is bigger than 1
334  if (Det < 1) {
335  continue;
336  }
337 
338  // a * (Ax - Bx) + (1-a) * (Ax+1 - Bx+1)
339  // a * Ax - a * Bx + (1-a) * Ax+1 - (1-a) * Bx+1
340  // (a * Ax + (1-a) * Ax+1) - (a * Bx + (1-a) * Bx+1)
341 
342  // (4) iterate over taking steps in the image to minimize the error:
343  bool tracked = TRUE;
344  for (uint8_t it = 0; it < max_iterations; it++) {
345  struct point_t new_point = {
346  vectors[new_p].pos.x + vectors[new_p].flow_x,
347  vectors[new_p].pos.y + vectors[new_p].flow_y,
348  0, 0, 0
349  };
350  // If the pixel is outside ROI, do not track it
351  if (new_point.x / subpixel_factor < half_window_size || (old_img->w - new_point.x / subpixel_factor) <= half_window_size
352  || new_point.y / subpixel_factor < half_window_size || (old_img->h - new_point.y / subpixel_factor) <= half_window_size
353  || new_point.x / subpixel_factor > old_img->w || new_point.y / subpixel_factor > old_img->h) {
354  tracked = FALSE;
355  break;
356  }
357 
358  // [a] get the subpixel neighborhood in the new image
359  image_subpixel_window(new_img, &window_J, &new_point, subpixel_factor, 0);
360 
361  // [b] determine the image difference between the two neighborhoods
362  // TODO: also give this error back, so that it can be used for reliability
363  uint32_t error = image_difference(&window_I, &window_J, &window_diff);
364  if (error > error_threshold && it > max_iterations / 2) {
365  tracked = FALSE;
366  break;
367  }
368 
369  int32_t b_x = image_multiply(&window_diff, &window_DX, NULL) / 255;
370  int32_t b_y = image_multiply(&window_diff, &window_DY, NULL) / 255;
371 
372  // [d] calculate the additional flow step and possibly terminate the iteration
373  int16_t step_x = (G[3] * b_x - G[1] * b_y) / Det;
374  int16_t step_y = (G[0] * b_y - G[2] * b_x) / Det;
375  vectors[new_p].flow_x += step_x;
376  vectors[new_p].flow_y += step_y;
377  vectors[new_p].error = error;
378 
379  // Check if we exceeded the treshold
380  if ((abs(step_x) + abs(step_y)) < step_threshold) {
381  break;
382  }
383  }
384 
385  // If we tracked the point we update the index and the count
386  if (tracked) {
387  new_p++;
388  (*points_cnt)++;
389  } else if (keep_bad_points) {
390  vectors[new_p].pos.x = 0;
391  vectors[new_p].pos.y = 0;
392  vectors[new_p].flow_x = 0;
393  vectors[new_p].flow_y = 0;
394  vectors[new_p].error = LARGE_FLOW_ERROR;
395  new_p++;
396  (*points_cnt)++;
397  }
398  }
399 
400  // Free the images
401  image_free(&window_I);
402  image_free(&window_J);
403  image_free(&window_DX);
404  image_free(&window_DY);
405  image_free(&window_diff);
406 
407  // Return the vectors
408  return vectors;
409 }
unsigned short uint16_t
Definition: types.h:16
void image_gradients(struct image_t *input, struct image_t *dx, struct image_t *dy)
Calculate the gradients using the following matrix: [0 -1 0; -1 0 1; 0 1 0].
Definition: image.c:508
uint32_t image_difference(struct image_t *img_a, struct image_t *img_b, struct image_t *diff)
Calculate the difference between two images and return the error This will only work with grayscale i...
Definition: image.c:564
void image_free(struct image_t *img)
Free the image.
Definition: image.c:64
#define LARGE_FLOW_ERROR
Definition: lucas_kanade.h:37
void image_create(struct image_t *img, uint16_t width, uint16_t height, enum image_type type)
Create a new image.
Definition: image.c:39
Definition: image.h:43
Definition: image.h:66
uint8_t patch_size
Definition: textons.c:97
signed long long int64_t
Definition: types.h:21
uint32_t x
The x coordinate of the point.
Definition: image.h:58
#define FALSE
Definition: std.h:5
void pyramid_build(struct image_t *input, struct image_t *output_array, uint8_t pyr_level, uint16_t border_size)
This function populates given array of image_t structs with wanted number of padded pyramids based on...
Definition: image.c:423
#define TRUE
Definition: std.h:4
int16_t flow_x
The x direction flow in subpixels.
Definition: image.h:68
uint16_t w
Image width.
Definition: image.h:45
unsigned long uint32_t
Definition: types.h:18
uint16_t h
Image height.
Definition: image.h:46
signed short int16_t
Definition: types.h:17
struct point_t pos
The original position the flow comes from.
Definition: image.h:67
uint32_t y
The y coordinate of the point.
Definition: image.h:59
Definition: image.h:57
signed long int32_t
Definition: types.h:19
uint32_t error
The matching error in the tracking process.
Definition: image.h:70
struct flow_t * opticFlowLK_flat(struct image_t *new_img, struct image_t *old_img, struct point_t *points, uint16_t *points_cnt, uint16_t half_window_size, uint16_t subpixel_factor, uint8_t max_iterations, uint8_t step_threshold, uint16_t max_points, uint8_t keep_bad_points)
Compute the optical flow of several points using the Lucas-Kanade algorithm by Yves Bouguet The initi...
Definition: lucas_kanade.c:266
unsigned char uint8_t
Definition: types.h:14
efficient fixed-point optical-flow calculation
static float p[2][2]
Grayscale image with only the Y part (uint8 per pixel)
Definition: image.h:37
void image_calculate_g(struct image_t *dx, struct image_t *dy, int32_t *g)
Calculate the G vector of an image gradient This is used for optical flow calculation.
Definition: image.c:532
signed char int8_t
Definition: types.h:15
An image gradient (int16 per pixel)
Definition: image.h:39
int16_t flow_y
The y direction flow in subpixels.
Definition: image.h:69
int32_t image_multiply(struct image_t *img_a, struct image_t *img_b, struct image_t *mult)
Calculate the multiplication between two images and return the error This will only work with image g...
Definition: image.c:602
void image_subpixel_window(struct image_t *input, struct image_t *output, struct point_t *center, uint32_t subpixel_factor, uint8_t border_size)
This outputs a subpixel window image in grayscale Currently only works with Grayscale images as input...
Definition: image.c:450
struct flow_t * opticFlowLK(struct image_t *new_img, struct image_t *old_img, struct point_t *points, uint16_t *points_cnt, uint16_t half_window_size, uint16_t subpixel_factor, uint8_t max_iterations, uint8_t step_threshold, uint8_t max_points, uint8_t pyramid_level, uint8_t keep_bad_points)
Definition: lucas_kanade.c:73