Paparazzi UAS  v5.12_stable-4-g9b43e9b
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 {
77 
78  // if no pyramids, use the old code:
79  if (pyramid_level == 0) {
80  // use the old code in this case:
81  return opticFlowLK_flat(new_img, old_img, points, points_cnt, half_window_size, subpixel_factor, max_iterations, step_threshold, max_points);
82  }
83 
84  // Allocate some memory for returning the vectors
85  struct flow_t *vectors = malloc(sizeof(struct flow_t) * max_points);
86 
87  // Determine patch sizes and initialize neighborhoods
88  uint16_t patch_size = 2 * half_window_size + 1;
89  // TODO: Feature management shows that this threshold rejects corners maybe too often, maybe another formula could be chosen
90  uint32_t error_threshold = (25 * 25) * (patch_size * patch_size);
91  uint16_t padded_patch_size = patch_size + 2;
92  uint8_t border_size = padded_patch_size / 2 + 2; // amount of padding added to images
93 
94  // Allocate memory for image pyramids
95  struct image_t *pyramid_old = malloc(sizeof(struct image_t) * (pyramid_level + 1));
96  struct image_t *pyramid_new = malloc(sizeof(struct image_t) * (pyramid_level + 1));
97 
98  // Build pyramid levels
99  pyramid_build(old_img, pyramid_old, pyramid_level, border_size);
100  pyramid_build(new_img, pyramid_new, pyramid_level, border_size);
101 
102  // Create the window images
103  struct image_t window_I, window_J, window_DX, window_DY, window_diff;
104  image_create(&window_I, padded_patch_size, padded_patch_size, IMAGE_GRAYSCALE);
105  image_create(&window_J, patch_size, patch_size, IMAGE_GRAYSCALE);
106  image_create(&window_DX, patch_size, patch_size, IMAGE_GRADIENT);
107  image_create(&window_DY, patch_size, patch_size, IMAGE_GRADIENT);
108  image_create(&window_diff, patch_size, patch_size, IMAGE_GRADIENT);
109 
110  // Iterate through pyramid levels
111  for (int8_t LVL = pyramid_level; LVL != -1; LVL--) {
112  uint16_t points_orig = *points_cnt;
113  *points_cnt = 0;
114  uint16_t new_p = 0;
115 
116  // Calculate the amount of points to skip
117  float skip_points = (points_orig > max_points) ? (float)points_orig / max_points : 1;
118 
119  // Go through all points
120  for (uint16_t i = 0; i < max_points && i < points_orig; i++) {
121  uint16_t p = i * skip_points;
122 
123  if (LVL == pyramid_level) {
124  // Convert point position on original image to a subpixel coordinate on the top pyramid level
125  vectors[new_p].pos.x = (points[p].x * subpixel_factor) >> pyramid_level;
126  vectors[new_p].pos.y = (points[p].y * subpixel_factor) >> pyramid_level;
127  vectors[new_p].flow_x = 0;
128  vectors[new_p].flow_y = 0;
129 
130  } else {
131  // (5) use calculated flow as initial flow estimation for next level of pyramid
132  vectors[new_p].pos.x = vectors[p].pos.x << 1;
133  vectors[new_p].pos.y = vectors[p].pos.y << 1;
134  vectors[new_p].flow_x = vectors[p].flow_x << 1;
135  vectors[new_p].flow_y = vectors[p].flow_y << 1;
136  }
137 
138  // If the pixel is outside original image, do not track it
139  if ((((int32_t) vectors[new_p].pos.x + vectors[new_p].flow_x) < 0)
140  || ((vectors[new_p].pos.x + vectors[new_p].flow_x) > ((pyramid_new[LVL].w - 1 - 2 * border_size)* subpixel_factor))
141  || (((int32_t) vectors[new_p].pos.y + vectors[new_p].flow_y) < 0)
142  || ((vectors[new_p].pos.y + vectors[new_p].flow_y) > ((pyramid_new[LVL].h - 1 - 2 * border_size)* subpixel_factor))) {
143  continue;
144  }
145 
146 
147  // (1) determine the subpixel neighborhood in the old image
148  image_subpixel_window(&pyramid_old[LVL], &window_I, &vectors[new_p].pos, subpixel_factor, border_size);
149 
150  // (2) get the x- and y- gradients
151  image_gradients(&window_I, &window_DX, &window_DY);
152 
153  // (3) determine the 'G'-matrix [sum(Axx) sum(Axy); sum(Axy) sum(Ayy)], where sum is over the window
154  int32_t G[4];
155  image_calculate_g(&window_DX, &window_DY, G);
156 
157  // calculate G's determinant in subpixel units:
158  int32_t Det = (G[0] * G[3] - G[1] * G[2]);
159 
160  // Check if the determinant is bigger than 1
161  if (Det < 1) {
162  continue;
163  }
164 
165  // (4) iterate over taking steps in the image to minimize the error:
166  bool tracked = true;
167 
168  for (uint8_t it = max_iterations; it--;) {
169  struct point_t new_point = { vectors[new_p].pos.x + vectors[new_p].flow_x,
170  vectors[new_p].pos.y + vectors[new_p].flow_y
171  };
172 
173 
174  // If the pixel is outside original image, do not track it
175  if ((((int32_t)vectors[new_p].pos.x + vectors[new_p].flow_x) < 0)
176  || (new_point.x > ((pyramid_new[LVL].w - 1 - 2 * border_size)*subpixel_factor))
177  || (((int32_t)vectors[new_p].pos.y + vectors[new_p].flow_y) < 0)
178  || (new_point.y > ((pyramid_new[LVL].h - 1 - 2 * border_size)*subpixel_factor))) {
179  tracked = false;
180  break;
181  }
182 
183  // [a] get the subpixel neighborhood in the new image
184  image_subpixel_window(&pyramid_new[LVL], &window_J, &new_point, subpixel_factor, border_size);
185 
186  // [b] determine the image difference between the two neighborhoods
187  uint32_t error = image_difference(&window_I, &window_J, &window_diff);
188 
189  if (error > error_threshold && it < max_iterations / 2) {
190  tracked = false;
191  break;
192  }
193 
194  int32_t b_x = image_multiply(&window_diff, &window_DX, NULL) / 255;
195  int32_t b_y = image_multiply(&window_diff, &window_DY, NULL) / 255;
196 
197 
198  // [d] calculate the additional flow step and possibly terminate the iteration
199  int16_t step_x = (((int64_t) G[3] * b_x - G[1] * b_y) * subpixel_factor) / Det;
200  int16_t step_y = (((int64_t) G[0] * b_y - G[2] * b_x) * subpixel_factor) / Det;
201 
202  vectors[new_p].flow_x = vectors[new_p].flow_x + step_x;
203  vectors[new_p].flow_y = vectors[new_p].flow_y + step_y;
204 
205  // Check if we exceeded the treshold CHANGED made this better for 0.03
206  if ((abs(step_x) + abs(step_y)) < step_threshold) {
207  break;
208  }
209  } // lucas kanade step iteration
210 
211  // If we tracked the point we update the index and the count
212  if (tracked) {
213  new_p++;
214  (*points_cnt)++;
215  }
216  } // go through all points
217 
218  } // LVL of pyramid
219 
220  // Free the images
221  image_free(&window_I);
222  image_free(&window_J);
223  image_free(&window_DX);
224  image_free(&window_DY);
225  image_free(&window_diff);
226 
227  for (int8_t i = pyramid_level; i != -1; i--) {
228  image_free(&pyramid_old[i]);
229  image_free(&pyramid_new[i]);
230  }
231  pyramid_old = NULL;
232  pyramid_new = NULL;
233 
234  // Return the vectors
235  return vectors;
236 }
237 
253 struct flow_t *opticFlowLK_flat(struct image_t *new_img, struct image_t *old_img, struct point_t *points, uint16_t *points_cnt,
254  uint16_t half_window_size, uint16_t subpixel_factor, uint8_t max_iterations, uint8_t step_threshold, uint16_t max_points)
255 {
256  // A straightforward one-level implementation of Lucas-Kanade.
257  // For all points:
258  // (1) determine the subpixel neighborhood in the old image
259  // (2) get the x- and y- gradients
260  // (3) determine the 'G'-matrix [sum(Axx) sum(Axy); sum(Axy) sum(Ayy)], where sum is over the window
261  // (4) iterate over taking steps in the image to minimize the error:
262  // [a] get the subpixel neighborhood in the new image
263  // [b] determine the image difference between the two neighborhoods
264  // [c] calculate the 'b'-vector
265  // [d] calculate the additional flow step and possibly terminate the iteration
266 
267  // Allocate some memory for returning the vectors
268  struct flow_t *vectors = malloc(sizeof(struct flow_t) * max_points);
269  uint16_t new_p = 0;
270  uint16_t points_orig = *points_cnt;
271  *points_cnt = 0;
272 
273  // determine patch sizes and initialize neighborhoods
274  uint16_t patch_size = 2 * half_window_size;
275  uint32_t error_threshold = (25 * 25) * (patch_size * patch_size);
276  uint16_t padded_patch_size = patch_size + 2;
277 
278  // Create the window images
279  struct image_t window_I, window_J, window_DX, window_DY, window_diff;
280  image_create(&window_I, padded_patch_size, padded_patch_size, IMAGE_GRAYSCALE);
281  image_create(&window_J, patch_size, patch_size, IMAGE_GRAYSCALE);
282  image_create(&window_DX, patch_size, patch_size, IMAGE_GRADIENT);
283  image_create(&window_DY, patch_size, patch_size, IMAGE_GRADIENT);
284  image_create(&window_diff, patch_size, patch_size, IMAGE_GRADIENT);
285 
286  // Calculate the amount of points to skip
287  float skip_points = (points_orig > max_points) ? points_orig / max_points : 1;
288 
289  // Go trough all points
290  for (uint16_t i = 0; i < max_points && i < points_orig; i++) {
291  uint16_t p = i * skip_points;
292 
293  // If the pixel is outside ROI, do not track it
294  if (points[p].x < half_window_size || (old_img->w - points[p].x) < half_window_size
295  || points[p].y < half_window_size || (old_img->h - points[p].y) < half_window_size) {
296  continue;
297  }
298 
299  // Convert the point to a subpixel coordinate
300  vectors[new_p].pos.x = points[p].x * subpixel_factor;
301  vectors[new_p].pos.y = points[p].y * subpixel_factor;
302  vectors[new_p].flow_x = 0;
303  vectors[new_p].flow_y = 0;
304 
305  // (1) determine the subpixel neighborhood in the old image
306  image_subpixel_window(old_img, &window_I, &vectors[new_p].pos, subpixel_factor, 0);
307 
308  // (2) get the x- and y- gradients
309  image_gradients(&window_I, &window_DX, &window_DY);
310 
311  // (3) determine the 'G'-matrix [sum(Axx) sum(Axy); sum(Axy) sum(Ayy)], where sum is over the window
312  int32_t G[4];
313  image_calculate_g(&window_DX, &window_DY, G);
314 
315  // calculate G's determinant in subpixel units:
316  int32_t Det = (G[0] * G[3] - G[1] * G[2]) / subpixel_factor;
317 
318  // Check if the determinant is bigger than 1
319  if (Det < 1) {
320  continue;
321  }
322 
323  // a * (Ax - Bx) + (1-a) * (Ax+1 - Bx+1)
324  // a * Ax - a * Bx + (1-a) * Ax+1 - (1-a) * Bx+1
325  // (a * Ax + (1-a) * Ax+1) - (a * Bx + (1-a) * Bx+1)
326 
327  // (4) iterate over taking steps in the image to minimize the error:
328  bool tracked = TRUE;
329  for (uint8_t it = 0; it < max_iterations; it++) {
330  struct point_t new_point = {
331  vectors[new_p].pos.x + vectors[new_p].flow_x,
332  vectors[new_p].pos.y + vectors[new_p].flow_y
333  };
334  // If the pixel is outside ROI, do not track it
335  if (new_point.x / subpixel_factor < half_window_size || (old_img->w - new_point.x / subpixel_factor) <= half_window_size
336  || new_point.y / subpixel_factor < half_window_size || (old_img->h - new_point.y / subpixel_factor) <= half_window_size
337  || new_point.x / subpixel_factor > old_img->w || new_point.y / subpixel_factor > old_img->h) {
338  tracked = FALSE;
339  break;
340  }
341 
342  // [a] get the subpixel neighborhood in the new image
343  image_subpixel_window(new_img, &window_J, &new_point, subpixel_factor, 0);
344 
345  // [b] determine the image difference between the two neighborhoods
346  // TODO: also give this error back, so that it can be used for reliability
347  uint32_t error = image_difference(&window_I, &window_J, &window_diff);
348  if (error > error_threshold && it > max_iterations / 2) {
349  tracked = FALSE;
350  break;
351  }
352 
353  int32_t b_x = image_multiply(&window_diff, &window_DX, NULL) / 255;
354  int32_t b_y = image_multiply(&window_diff, &window_DY, NULL) / 255;
355 
356  // [d] calculate the additional flow step and possibly terminate the iteration
357  int16_t step_x = (G[3] * b_x - G[1] * b_y) / Det;
358  int16_t step_y = (G[0] * b_y - G[2] * b_x) / Det;
359  vectors[new_p].flow_x += step_x;
360  vectors[new_p].flow_y += step_y;
361 
362  // Check if we exceeded the treshold
363  if ((abs(step_x) + abs(step_y)) < step_threshold) {
364  break;
365  }
366  }
367 
368  // If we tracked the point we update the index and the count
369  if (tracked) {
370  new_p++;
371  (*points_cnt)++;
372  }
373  }
374 
375  // Free the images
376  image_free(&window_I);
377  image_free(&window_J);
378  image_free(&window_DX);
379  image_free(&window_DY);
380  image_free(&window_diff);
381 
382  // Return the vectors
383  return vectors;
384 }
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:422
void pyramid_build(struct image_t *input, struct image_t *output_array, uint8_t pyr_level, uint8_t border_size)
This function populates given array of image_t structs with wanted number of padded pyramids based on...
Definition: image.c:337
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:478
void image_free(struct image_t *img)
Free the image.
Definition: image.c:63
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)
Definition: lucas_kanade.c:73
void image_create(struct image_t *img, uint16_t width, uint16_t height, enum image_type type)
Create a new image.
Definition: image.c:38
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
#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
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)
Compute the optical flow of several points using the Lucas-Kanade algorithm by Yves Bouguet The initi...
Definition: lucas_kanade.c:253
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:446
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:516
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:364