Paparazzi UAS  v5.10_stable-5-g83a0da5-dirty
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
opticflow_calculator.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Hann Woei Ho
3  * 2015 Freek van Tienen <freek.v.tienen@gmail.com>
4  * 2016 Kimberly McGuire <k.n.mcguire@tudelft.nl
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 
30 #include "std.h"
31 
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 
36 // Own Header
37 #include "opticflow_calculator.h"
38 
39 // Computer Vision
40 #include "lib/vision/image.h"
42 #include "lib/vision/fast_rosten.h"
43 #include "lib/vision/edge_flow.h"
44 #include "size_divergence.h"
45 #include "linear_flow_fit.h"
46 
47 // whether to show the flow and corners:
48 #define OPTICFLOW_SHOW_FLOW 0
49 #define OPTICFLOW_SHOW_CORNERS 0
50 
51 // What methods are run to determine divergence, lateral flow, etc.
52 // SIZE_DIV looks at line sizes and only calculates divergence
53 #define SIZE_DIV 1
54 // LINEAR_FIT makes a linear optical flow field fit and extracts a lot of information:
55 // relative velocities in x, y, z (divergence / time to contact), the slope of the surface, and the surface roughness.
56 #define LINEAR_FIT 1
57 
58 // Camera parameters (defaults are from an ARDrone 2)
59 #ifndef OPTICFLOW_FOV_W
60 #define OPTICFLOW_FOV_W 0.89360857702
61 #endif
62 PRINT_CONFIG_VAR(OPTICFLOW_FOV_W)
63 
64 #ifndef OPTICFLOW_FOV_H
65 #define OPTICFLOW_FOV_H 0.67020643276
66 #endif
67 PRINT_CONFIG_VAR(OPTICFLOW_FOV_H)
68 
69 #ifndef OPTICFLOW_FX
70 #define OPTICFLOW_FX 343.1211
71 #endif
72 PRINT_CONFIG_VAR(OPTICFLOW_FX)
73 
74 #ifndef OPTICFLOW_FY
75 #define OPTICFLOW_FY 348.5053
76 #endif
77 PRINT_CONFIG_VAR(OPTICFLOW_FY)
78 
79 /* Set the default values */
80 #ifndef OPTICFLOW_MAX_TRACK_CORNERS
81 #define OPTICFLOW_MAX_TRACK_CORNERS 25
82 #endif
83 PRINT_CONFIG_VAR(OPTICFLOW_MAX_TRACK_CORNERS)
84 
85 #ifndef OPTICFLOW_WINDOW_SIZE
86 #define OPTICFLOW_WINDOW_SIZE 10
87 #endif
88 PRINT_CONFIG_VAR(OPTICFLOW_WINDOW_SIZE)
89 
90 #ifndef OPTICFLOW_SEARCH_DISTANCE
91 #define OPTICFLOW_SEARCH_DISTANCE 20
92 #endif
93 PRINT_CONFIG_VAR(OPTICFLOW_MAX_SEARCH_DISTANCE)
94 
95 #ifndef OPTICFLOW_SUBPIXEL_FACTOR
96 #define OPTICFLOW_SUBPIXEL_FACTOR 10
97 #endif
98 PRINT_CONFIG_VAR(OPTICFLOW_SUBPIXEL_FACTOR)
99 
100 #ifndef OPTICFLOW_MAX_ITERATIONS
101 #define OPTICFLOW_MAX_ITERATIONS 10
102 #endif
103 PRINT_CONFIG_VAR(OPTICFLOW_MAX_ITERATIONS)
104 
105 #ifndef OPTICFLOW_THRESHOLD_VEC
106 #define OPTICFLOW_THRESHOLD_VEC 2
107 #endif
108 PRINT_CONFIG_VAR(OPTICFLOW_THRESHOLD_VEC)
109 
110 #ifndef OPTICFLOW_PYRAMID_LEVEL
111 #define OPTICFLOW_PYRAMID_LEVEL 0
112 #endif
113 PRINT_CONFIG_VAR(OPTICFLOW_PYRAMID_LEVEL)
114 
115 #ifndef OPTICFLOW_FAST9_ADAPTIVE
116 #define OPTICFLOW_FAST9_ADAPTIVE TRUE
117 #endif
118 PRINT_CONFIG_VAR(OPTICFLOW_FAST9_ADAPTIVE)
119 
120 #ifndef OPTICFLOW_FAST9_THRESHOLD
121 #define OPTICFLOW_FAST9_THRESHOLD 20
122 #endif
123 PRINT_CONFIG_VAR(OPTICFLOW_FAST9_THRESHOLD)
124 
125 #ifndef OPTICFLOW_FAST9_MIN_DISTANCE
126 #define OPTICFLOW_FAST9_MIN_DISTANCE 10
127 #endif
128 PRINT_CONFIG_VAR(OPTICFLOW_FAST9_MIN_DISTANCE)
129 
130 #ifndef OPTICFLOW_FAST9_PADDING
131 #define OPTICFLOW_FAST9_PADDING 20
132 #endif
133 PRINT_CONFIG_VAR(OPTICFLOW_FAST9_PADDING)
134 
135 // thresholds FAST9 that are currently not set from the GCS:
136 #define FAST9_LOW_THRESHOLD 5
137 #define FAST9_HIGH_THRESHOLD 60
138 
139 #ifndef OPTICFLOW_METHOD
140 #define OPTICFLOW_METHOD 0
141 #endif
142 PRINT_CONFIG_VAR(OPTICFLOW_METHOD)
143 
144 #if OPTICFLOW_METHOD > 1
145 #error WARNING: Both Lukas Kanade and EdgeFlow are NOT selected
146 #endif
147 
148 #ifndef OPTICFLOW_DEROTATION
149 #define OPTICFLOW_DEROTATION TRUE
150 #endif
151 PRINT_CONFIG_VAR(OPTICFLOW_DEROTATION)
152 
153 #ifndef OPTICFLOW_MEDIAN_FILTER
154 #define OPTICFLOW_MEDIAN_FILTER TRUE
155 #endif
156 PRINT_CONFIG_VAR(OPTICFLOW_MEDIAN_FILTER)
157 
158 //Include median filter
159 #include "filters/median_filter.h"
160 struct MedianFilterInt vel_x_filt, vel_y_filt;
161 
162 
163 /* Functions only used here */
164 static uint32_t timeval_diff(struct timeval *starttime, struct timeval *finishtime);
165 static int cmp_flow(const void *a, const void *b);
166 
167 
168 
176 {
177 
178  init_median_filter(&vel_x_filt);
180 
181  /* Create the image buffers */
182  image_create(&opticflow->img_gray, w, h, IMAGE_GRAYSCALE);
183  image_create(&opticflow->prev_img_gray, w, h, IMAGE_GRAYSCALE);
184 
185  /* Set the previous values */
186  opticflow->got_first_img = false;
187  FLOAT_RATES_ZERO(opticflow->prev_rates);
188 
189  /* Set the default values */
190  opticflow->method = OPTICFLOW_METHOD; //0 = LK_fast9, 1 = Edgeflow
191  opticflow->window_size = OPTICFLOW_WINDOW_SIZE;
193  opticflow->derotation = OPTICFLOW_DEROTATION; //0 = OFF, 1 = ON
194 
201 
202 
207  opticflow->fast9_rsize = 512;
208  opticflow->fast9_ret_corners = malloc(sizeof(struct point_t) * opticflow->fast9_rsize);
209 
210 }
219  struct opticflow_result_t *result)
220 {
221  if (opticflow->just_switched_method) {
222  opticflow_calc_init(opticflow, img->w, img->h);
223  }
224 
225  // variables for size_divergence:
226  float size_divergence; int n_samples;
227 
228  // variables for linear flow fit:
229  float error_threshold;
230  int n_iterations_RANSAC, n_samples_RANSAC, success_fit;
231  struct linear_flow_fit_info fit_info;
232 
233  // Update FPS for information
234  result->fps = 1 / (timeval_diff(&opticflow->prev_timestamp, &img->ts) / 1000.);
235  opticflow->prev_timestamp = img->ts;
236 
237  // Convert image to grayscale
238  image_to_grayscale(img, &opticflow->img_gray);
239 
240  // Copy to previous image if not set
241  if (!opticflow->got_first_img) {
242  image_copy(&opticflow->img_gray, &opticflow->prev_img_gray);
243  opticflow->got_first_img = true;
244  }
245 
246  // *************************************************************************************
247  // Corner detection
248  // *************************************************************************************
249 
250  // FAST corner detection
251  // TODO: There is something wrong with fast9_detect destabilizing FPS. This problem is reduced with putting min_distance
252  // to 0 (see defines), however a more permanent solution should be considered
253  fast9_detect(img, opticflow->fast9_threshold, opticflow->fast9_min_distance,
254  opticflow->fast9_padding, opticflow->fast9_padding, &result->corner_cnt,
255  &opticflow->fast9_rsize,
256  opticflow->fast9_ret_corners);
257 
258  // Adaptive threshold
259  if (opticflow->fast9_adaptive) {
260  // Decrease and increase the threshold based on previous values
261  if (result->corner_cnt < 40
262  && opticflow->fast9_threshold > FAST9_LOW_THRESHOLD) { // TODO: Replace 40 with OPTICFLOW_MAX_TRACK_CORNERS / 2
263  opticflow->fast9_threshold--;
264  } else if (result->corner_cnt > OPTICFLOW_MAX_TRACK_CORNERS * 2 && opticflow->fast9_threshold < FAST9_HIGH_THRESHOLD) {
265  opticflow->fast9_threshold++;
266  }
267  }
268 
269 #if OPTICFLOW_SHOW_CORNERS
270  image_show_points(img, opticflow->fast9_ret_corners, result->corner_cnt);
271 #endif
272 
273  // Check if we found some corners to track
274  if (result->corner_cnt < 1) {
275  image_copy(&opticflow->img_gray, &opticflow->prev_img_gray);
276  return;
277  }
278 
279  // *************************************************************************************
280  // Corner Tracking
281  // *************************************************************************************
282 
283  // Execute a Lucas Kanade optical flow
284  result->tracked_cnt = result->corner_cnt;
285  struct flow_t *vectors = opticFlowLK(&opticflow->img_gray, &opticflow->prev_img_gray, opticflow->fast9_ret_corners,
286  &result->tracked_cnt,
287  opticflow->window_size / 2, opticflow->subpixel_factor, opticflow->max_iterations,
288  opticflow->threshold_vec, opticflow->max_track_corners, opticflow->pyramid_level);
289 
290 #if OPTICFLOW_SHOW_FLOW
291  printf("show: n tracked = %d\n", result->tracked_cnt);
292  image_show_flow(img, vectors, result->tracked_cnt, opticflow->subpixel_factor);
293 #endif
294 
295  // Estimate size divergence:
296  if (SIZE_DIV) {
297  n_samples = 100;
298  size_divergence = get_size_divergence(vectors, result->tracked_cnt, n_samples);
299  result->div_size = size_divergence;
300  } else {
301  result->div_size = 0.0f;
302  }
303  if (LINEAR_FIT) {
304  // Linear flow fit (normally derotation should be performed before):
305  error_threshold = 10.0f;
306  n_iterations_RANSAC = 20;
307  n_samples_RANSAC = 5;
308  success_fit = analyze_linear_flow_field(vectors, result->tracked_cnt, error_threshold, n_iterations_RANSAC,
309  n_samples_RANSAC, img->w, img->h, &fit_info);
310 
311  if (!success_fit) {
312  fit_info.divergence = 0.0f;
313  fit_info.surface_roughness = 0.0f;
314  }
315 
316  result->divergence = fit_info.divergence;
317  result->surface_roughness = fit_info.surface_roughness;
318  } else {
319  result->divergence = 0.0f;
320  result->surface_roughness = 0.0f;
321  }
322 
323 
324  // Get the median flow
325  qsort(vectors, result->tracked_cnt, sizeof(struct flow_t), cmp_flow);
326  if (result->tracked_cnt == 0) {
327  // We got no flow
328  result->flow_x = 0;
329  result->flow_y = 0;
330  } else if (result->tracked_cnt > 3) {
331  // Take the average of the 3 median points
332  result->flow_x = vectors[result->tracked_cnt / 2 - 1].flow_x;
333  result->flow_y = vectors[result->tracked_cnt / 2 - 1].flow_y;
334  result->flow_x += vectors[result->tracked_cnt / 2].flow_x;
335  result->flow_y += vectors[result->tracked_cnt / 2].flow_y;
336  result->flow_x += vectors[result->tracked_cnt / 2 + 1].flow_x;
337  result->flow_y += vectors[result->tracked_cnt / 2 + 1].flow_y;
338  result->flow_x /= 3;
339  result->flow_y /= 3;
340  } else {
341  // Take the median point
342  result->flow_x = vectors[result->tracked_cnt / 2].flow_x;
343  result->flow_y = vectors[result->tracked_cnt / 2].flow_y;
344  }
345 
346  // Flow Derotation
347  float diff_flow_x = 0;
348  float diff_flow_y = 0;
349 
350  /*// Flow Derotation TODO:
351  float diff_flow_x = (state->phi - opticflow->prev_phi) * img->w / OPTICFLOW_FOV_W;
352  float diff_flow_y = (state->theta - opticflow->prev_theta) * img->h / OPTICFLOW_FOV_H;*/
353 
354  if (opticflow->derotation && result->tracked_cnt > 5) {
355  diff_flow_x = (state->rates.p + opticflow->prev_rates.p) / 2.0f / result->fps * img->w /
356  OPTICFLOW_FOV_W;// * img->w / OPTICFLOW_FOV_W;
357  diff_flow_y = (state->rates.q + opticflow->prev_rates.q) / 2.0f / result->fps * img->h /
358  OPTICFLOW_FOV_H;// * img->h / OPTICFLOW_FOV_H;
359  }
360 
361  result->flow_der_x = result->flow_x - diff_flow_x * opticflow->subpixel_factor;
362  result->flow_der_y = result->flow_y - diff_flow_y * opticflow->subpixel_factor;
363  opticflow->prev_rates = state->rates;
364 
365  // Velocity calculation
366  // Right now this formula is under assumption that the flow only exist in the center axis of the camera.
367  // TODO Calculate the velocity more sophisticated, taking into account the drone's angle and the slope of the ground plane.
368  float vel_x = result->flow_der_x * result->fps * state->agl / opticflow->subpixel_factor / OPTICFLOW_FX;
369  float vel_y = result->flow_der_y * result->fps * state->agl / opticflow->subpixel_factor / OPTICFLOW_FY;
370 
371  //Apply a median filter to the velocity if wanted
372  if (opticflow->median_filter == true) {
373  result->vel_x = (float)update_median_filter(&vel_x_filt, (int32_t)(vel_x * 1000)) / 1000;
374  result->vel_y = (float)update_median_filter(&vel_y_filt, (int32_t)(vel_y * 1000)) / 1000;
375  } else {
376  result->vel_x = vel_x;
377  result->vel_y = vel_y;
378  }
379  // Velocity calculation: uncomment if focal length of the camera is not known or incorrect.
380  // result->vel_x = - result->flow_der_x * result->fps * state->agl / opticflow->subpixel_factor * OPTICFLOW_FOV_W / img->w
381  // result->vel_y = result->flow_der_y * result->fps * state->agl / opticflow->subpixel_factor * OPTICFLOW_FOV_H / img->h
382 
383 
384  // Determine quality of noise measurement for state filter
385  //TODO develop a noise model based on groundtruth
386 
387  float noise_measurement_temp = (1 - ((float)result->tracked_cnt / ((float)opticflow->max_track_corners * 1.25)));
388  result->noise_measurement = noise_measurement_temp;
389 
390  // *************************************************************************************
391  // Next Loop Preparation
392  // *************************************************************************************
393  free(vectors);
394  image_switch(&opticflow->img_gray, &opticflow->prev_img_gray);
395 }
396 
405  struct opticflow_result_t *result)
406 {
407  // Define Static Variables
408  static struct edge_hist_t edge_hist[MAX_HORIZON];
409  static uint8_t current_frame_nr = 0;
410  struct edge_flow_t edgeflow;
411  static uint8_t previous_frame_offset[2] = {1, 1};
412 
413  // Define Normal variables
414  struct edgeflow_displacement_t displacement;
415  displacement.x = malloc(sizeof(int32_t) * img->w);
416  displacement.y = malloc(sizeof(int32_t) * img->h);
417 
418  // If the methods just switched to this one, reintialize the
419  // array of edge_hist structure.
420  if (opticflow->just_switched_method == 1) {
421  int i;
422  for (i = 0; i < MAX_HORIZON; i++) {
423  edge_hist[i].x = malloc(sizeof(int32_t) * img->w);
424  edge_hist[i].y = malloc(sizeof(int32_t) * img->h);
425  FLOAT_RATES_ZERO(edge_hist[i].rates);
426  }
427  }
428 
429  uint16_t disp_range;
430  if (opticflow->search_distance < DISP_RANGE_MAX) {
431  disp_range = opticflow->search_distance;
432  } else {
433  disp_range = DISP_RANGE_MAX;
434  }
435 
436  uint16_t window_size;
437 
438  if (opticflow->window_size < MAX_WINDOW_SIZE) {
439  window_size = opticflow->window_size;
440  } else {
441  window_size = MAX_WINDOW_SIZE;
442  }
443 
444  uint16_t RES = opticflow->subpixel_factor;
445 
446  //......................Calculating EdgeFlow..................... //
447 
448  // Calculate current frame's edge histogram
449  int32_t *edge_hist_x = edge_hist[current_frame_nr].x;
450  int32_t *edge_hist_y = edge_hist[current_frame_nr].y;
451  calculate_edge_histogram(img, edge_hist_x, 'x', 0);
452  calculate_edge_histogram(img, edge_hist_y, 'y', 0);
453 
454 
455  // Copy frame time and angles of image to calculated edge histogram
456  edge_hist[current_frame_nr].frame_time = img->ts;
457  edge_hist[current_frame_nr].rates = state->rates;
458 
459  // Calculate which previous edge_hist to compare with the current
460  uint8_t previous_frame_nr[2];
461  calc_previous_frame_nr(result, opticflow, current_frame_nr, previous_frame_offset, previous_frame_nr);
462 
463  //Select edge histogram from the previous frame nr
464  int32_t *prev_edge_histogram_x = edge_hist[previous_frame_nr[0]].x;
465  int32_t *prev_edge_histogram_y = edge_hist[previous_frame_nr[1]].y;
466 
467  //Calculate the corresponding derotation of the two frames
468  int16_t der_shift_x = 0;
469  int16_t der_shift_y = 0;
470 
471  if (opticflow->derotation) {
472  der_shift_x = (int16_t)((edge_hist[previous_frame_nr[0]].rates.p + edge_hist[current_frame_nr].rates.p) / 2.0f /
473  result->fps *
474  (float)img->w / (OPTICFLOW_FOV_W));
475  der_shift_y = (int16_t)((edge_hist[previous_frame_nr[1]].rates.q + edge_hist[current_frame_nr].rates.q) / 2.0f /
476  result->fps *
477  (float)img->h / (OPTICFLOW_FOV_H));
478  }
479 
480  // Estimate pixel wise displacement of the edge histograms for x and y direction
481  calculate_edge_displacement(edge_hist_x, prev_edge_histogram_x,
482  displacement.x, img->w,
483  window_size, disp_range, der_shift_x);
484  calculate_edge_displacement(edge_hist_y, prev_edge_histogram_y,
485  displacement.y, img->h,
486  window_size, disp_range, der_shift_y);
487 
488  // Fit a line on the pixel displacement to estimate
489  // the global pixel flow and divergence (RES is resolution)
490  line_fit(displacement.x, &edgeflow.div_x,
491  &edgeflow.flow_x, img->w,
492  window_size + disp_range, RES);
493  line_fit(displacement.y, &edgeflow.div_y,
494  &edgeflow.flow_y, img->h,
495  window_size + disp_range, RES);
496 
497  /* Save Resulting flow in results
498  * Warning: The flow detected here is different in sign
499  * and size, therefore this will be multiplied with
500  * the same subpixel factor and -1 to make it on par with
501  * the LK algorithm of t opticalflow_calculator.c
502  * */
503  edgeflow.flow_x = -1 * edgeflow.flow_x;
504  edgeflow.flow_y = -1 * edgeflow.flow_y;
505 
506  result->flow_x = (int16_t)edgeflow.flow_x / previous_frame_offset[0];
507  result->flow_y = (int16_t)edgeflow.flow_y / previous_frame_offset[1];
508 
509  //Fill up the results optic flow to be on par with LK_fast9
510  result->flow_der_x = result->flow_x;
511  result->flow_der_y = result->flow_y;
512  result->corner_cnt = getAmountPeaks(edge_hist_x, 500 , img->w);
513  result->tracked_cnt = getAmountPeaks(edge_hist_x, 500 , img->w);
514  result->divergence = (float)edgeflow.flow_x / RES;
515  result->div_size = 0.0f;
516  result->noise_measurement = 0.0f;
517  result->surface_roughness = 0.0f;
518 
519  //......................Calculating VELOCITY ..................... //
520 
521  /*Estimate fps per direction
522  * This is the fps with adaptive horizon for subpixel flow, which is not similar
523  * to the loop speed of the algorithm. The faster the quadcopter flies
524  * the higher it becomes
525  */
526  float fps_x = 0;
527  float fps_y = 0;
528  float time_diff_x = (float)(timeval_diff(&edge_hist[previous_frame_nr[0]].frame_time, &img->ts)) / 1000.;
529  float time_diff_y = (float)(timeval_diff(&edge_hist[previous_frame_nr[1]].frame_time, &img->ts)) / 1000.;
530  fps_x = 1 / (time_diff_x);
531  fps_y = 1 / (time_diff_y);
532 
533  result->fps = fps_x;
534 
535  // Calculate velocity
536  float vel_x = edgeflow.flow_x * fps_x * state->agl * OPTICFLOW_FOV_W / (img->w * RES);
537  float vel_y = edgeflow.flow_y * fps_y * state->agl * OPTICFLOW_FOV_H / (img->h * RES);
538 
539  //Apply a median filter to the velocity if wanted
540  if (opticflow->median_filter == true) {
541  result->vel_x = (float)update_median_filter(&vel_x_filt, (int32_t)(vel_x * 1000)) / 1000;
542  result->vel_y = (float)update_median_filter(&vel_y_filt, (int32_t)(vel_y * 1000)) / 1000;
543  } else {
544  result->vel_x = vel_x;
545  result->vel_y = vel_y;
546  }
547 
548  result->noise_measurement = 0.2;
549 
550 
551 
552 #if OPTICFLOW_SHOW_FLOW
553  draw_edgeflow_img(img, edgeflow, prev_edge_histogram_x, edge_hist_x);
554 #endif
555  // Increment and wrap current time frame
556  current_frame_nr = (current_frame_nr + 1) % MAX_HORIZON;
557 }
558 
559 
568  struct opticflow_result_t *result)
569 {
570 
571  // A switch counter that checks in the loop if the current method is similar,
572  // to the previous (for reinitializing structs)
573  static int8_t switch_counter = -1;
574  if (switch_counter != opticflow->method) {
575  opticflow->just_switched_method = true;
576  switch_counter = opticflow->method;
577  } else {
578  opticflow->just_switched_method = false;
579  }
580 
581  // Switch between methods (0 = fast9/lukas-kanade, 1 = EdgeFlow)
582  if (opticflow->method == 0) {
583  calc_fast9_lukas_kanade(opticflow, state, img, result);
584  } else if (opticflow->method == 1) {
585  calc_edgeflow_tot(opticflow, state, img, result);
586  }
587 
588 }
589 
596 static uint32_t timeval_diff(struct timeval *starttime, struct timeval *finishtime)
597 {
598  uint32_t msec;
599  msec = (finishtime->tv_sec - starttime->tv_sec) * 1000;
600  msec += (finishtime->tv_usec - starttime->tv_usec) / 1000;
601  return msec;
602 }
603 
611 static int cmp_flow(const void *a, const void *b)
612 {
613  const struct flow_t *a_p = (const struct flow_t *)a;
614  const struct flow_t *b_p = (const struct flow_t *)b;
615  return (a_p->flow_x * a_p->flow_x + a_p->flow_y * a_p->flow_y) - (b_p->flow_x * b_p->flow_x + b_p->flow_y *
616  b_p->flow_y);
617 }
618 
619 
unsigned short uint16_t
Definition: types.h:16
int16_t flow_y
Flow in y direction from the camera (in subpixels)
uint16_t fast9_min_distance
Minimum distance in pixels between corners.
void calculate_edge_displacement(int32_t *edge_histogram, int32_t *edge_histogram_prev, int32_t *displacement, uint16_t size, uint8_t window, uint8_t disp_range, int32_t der_shift)
Calculate_displacement calculates the displacement between two histograms.
Definition: edge_flow.c:168
int16_t flow_der_y
The derotated flow calculation in the y direction (in subpixels)
#define FAST9_HIGH_THRESHOLD
int32_t flow_x
Definition: edge_flow.h:77
float div_size
Divergence as determined with the size_divergence script.
uint8_t max_iterations
The maximum amount of iterations the Lucas Kanade algorithm should do.
#define MAX_WINDOW_SIZE
Definition: edge_flow.h:55
struct opticflow_t opticflow
Opticflow calculations.
uint16_t window_size
Window size for the blockmatching algorithm (general value for all methods)
struct FloatRates rates
Body rates.
calculate optical flow with EdgeFlow
void image_switch(struct image_t *a, struct image_t *b)
This will switch image *a and *b This is faster as image_copy because it doesn't copy the whole image...
Definition: image.c:97
void calc_edgeflow_tot(struct opticflow_t *opticflow, struct opticflow_state_t *state, struct image_t *img, struct opticflow_result_t *result)
Run the optical flow with EDGEFLOW on a new image frame.
uint16_t fast9_rsize
Amount of corners allocated.
void opticflow_calc_init(struct opticflow_t *opticflow, uint16_t w, uint16_t h)
Initialize the opticflow calculator.
#define OPTICFLOW_PYRAMID_LEVEL
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
Calculate velocity from optic flow.
bool median_filter
Decides to use a median filter on the velocity.
#define OPTICFLOW_MEDIAN_FILTER
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:42
#define FLOAT_RATES_ZERO(_r)
int32_t div_x
Definition: edge_flow.h:78
void draw_edgeflow_img(struct image_t *img, struct edge_flow_t edgeflow, int32_t *edge_hist_x_prev, int32_t *edge_hist_x)
Draws edgehistogram, displacement and linefit directly on the image for debugging (only for edgeflow ...
Definition: edge_flow.c:301
Definition: image.h:61
int32_t * y
Definition: edge_flow.h:66
int32_t flow_y
Definition: edge_flow.h:79
#define OPTICFLOW_THRESHOLD_VEC
#define OPTICFLOW_FAST9_MIN_DISTANCE
void image_copy(struct image_t *input, struct image_t *output)
Copy an image from inut to output This will only work if the formats are the same.
Definition: image.c:77
#define OPTICFLOW_FAST9_ADAPTIVE
void image_show_points(struct image_t *img, struct point_t *points, uint16_t points_cnt)
Show points in an image by coloring them through giving the pixels the maximum value.
Definition: image.c:551
static int cmp_flow(const void *a, const void *b)
Compare two flow vectors based on flow distance Used for sorting.
#define RES
Definition: detect_window.c:27
Calculate divergence from flow vectors by looking at line sizes beteween the points.
float q
in rad/s
float p
in rad/s
uint8_t threshold_vec
The threshold in x, y subpixels which the algorithm should stop.
void image_show_flow(struct image_t *img, struct flow_t *vectors, uint16_t points_cnt, uint8_t subpixel_factor)
Shows the flow from a specific point to a new point This works on YUV422 and Grayscale images...
Definition: image.c:576
void calculate_edge_histogram(struct image_t *img, int32_t edge_histogram[], char direction, uint16_t edge_threshold)
Calculate a edge/gradient histogram for each dimension of the image.
Definition: edge_flow.c:88
bool derotation
Derotation switched on or off (depended on the quality of the gyroscope measurement) ...
uint8_t method
Method to use to calculate the optical flow.
uint8_t max_track_corners
Maximum amount of corners Lucas Kanade should track.
float agl
height above ground [m]
struct MedianFilterInt vel_x_filt vel_y_filt
float get_size_divergence(struct flow_t *vectors, int count, int n_samples)
Get divergence from optical flow vectors based on line sizes between corners.
void opticflow_calc_frame(struct opticflow_t *opticflow, struct opticflow_state_t *state, struct image_t *img, struct opticflow_result_t *result)
Run the optical flow on a new image frame.
Image helper functions like resizing, color filter, converters...
void fast9_detect(struct image_t *img, uint8_t threshold, uint16_t min_dist, uint16_t x_padding, uint16_t y_padding, uint16_t *num_corners, uint16_t *ret_corners_length, struct point_t *ret_corners)
Do a FAST9 corner detection.
Definition: fast_rosten.c:51
#define MAX_HORIZON
Definition: edge_flow.h:45
uint16_t tracked_cnt
The amount of tracked corners.
uint16_t subpixel_factor
The amount of subpixels per pixel.
#define OPTICFLOW_FAST9_PADDING
int16_t flow_x
The x direction flow in subpixels.
Definition: image.h:63
struct point_t * fast9_ret_corners
Corners.
struct timeval prev_timestamp
Timestamp of the previous frame, used for FPS calculation.
uint16_t w
Image width.
Definition: image.h:44
int32_t update_median_filter(struct MedianFilterInt *filter, int32_t new_data)
Definition: median_filter.h:51
unsigned long uint32_t
Definition: types.h:18
#define OPTICFLOW_FAST9_THRESHOLD
#define OPTICFLOW_FOV_W
uint16_t h
Image height.
Definition: image.h:45
struct image_t prev_img_gray
Previous gray image frame.
signed short int16_t
Definition: types.h:17
#define OPTICFLOW_METHOD
uint8_t fast9_threshold
FAST9 corner detection threshold.
#define OPTICFLOW_FX
#define OPTICFLOW_WINDOW_SIZE
void image_to_grayscale(struct image_t *input, struct image_t *output)
Convert an image to grayscale.
Definition: image.c:116
Definition: image.h:55
#define OPTICFLOW_FOV_H
signed long int32_t
Definition: types.h:19
struct FloatRates rates
Definition: edge_flow.h:68
struct image_t img_gray
Current gray image frame.
float vel_x
The velocity in the x direction (image coordinates)
#define SIZE_DIV
uint16_t corner_cnt
The amount of coners found by FAST9.
float vel_y
The velocity in the y direction (image coordinates)
#define OPTICFLOW_FY
unsigned char uint8_t
Definition: types.h:14
float fps
Frames per second of the optical flow calculation.
efficient fixed-point optical-flow calculation
int analyze_linear_flow_field(struct flow_t *vectors, int count, float error_threshold, int n_iterations, int n_samples, int im_width, int im_height, struct linear_flow_fit_info *info)
Analyze a linear flow field, retrieving information such as divergence, surface roughness, focus of expansion, etc.
#define OPTICFLOW_DEROTATION
struct timeval ts
The timestamp of creation.
Definition: image.h:46
bool got_first_img
If we got a image to work with.
float divergence
Basically, relative_velocity_z. Actual divergence of a 2D flow field is 2 * relative_velocity_z.
#define OPTICFLOW_SEARCH_DISTANCE
#define LINEAR_FIT
int32_t div_y
Definition: edge_flow.h:80
uint16_t fast9_padding
Padding used in FAST9 detector.
float surface_roughness
The error of the linear fit is a measure of surface roughness.
bool fast9_adaptive
Whether the FAST9 threshold should be adaptive.
void calc_fast9_lukas_kanade(struct opticflow_t *opticflow, struct opticflow_state_t *state, struct image_t *img, struct opticflow_result_t *result)
Run the optical flow with fast9 and lukaskanade on a new image frame.
Grayscale image with only the Y part (uint8 per pixel)
Definition: image.h:36
static uint32_t timeval_diff(struct timeval *starttime, struct timeval *finishtime)
Calculate the difference from start till finish.
void line_fit(int32_t *displacement, int32_t *divergence, int32_t *flow, uint32_t size, uint32_t border, uint16_t RES)
Fits a linear model to an array with pixel displacements with least squares.
Definition: edge_flow.c:251
#define OPTICFLOW_MAX_TRACK_CORNERS
struct FloatRates prev_rates
Gyro Rates from the previous image frame.
void calc_previous_frame_nr(struct opticflow_result_t *result, struct opticflow_t *opticflow, uint8_t current_frame_nr, uint8_t *previous_frame_offset, uint8_t *previous_frame_nr)
Calc_previous_frame_nr; adaptive Time Horizon.
Definition: edge_flow.c:39
#define OPTICFLOW_SUBPIXEL_FACTOR
int16_t flow_x
Flow in x direction from the camera (in subpixels)
#define OPTICFLOW_MAX_ITERATIONS
uint32_t getAmountPeaks(int32_t *edgehist, uint32_t thres, int32_t size)
getAmountPeaks, calculates the amount of peaks in a edge histogram
Definition: edge_flow.c:341
#define DISP_RANGE_MAX
Definition: edge_flow.h:52
signed char int8_t
Definition: types.h:15
uint8_t pyramid_level
Number of pyramid levels used in Lucas Kanade algorithm (0 == no pyramids used)
void init_median_filter(struct MedianFilterInt *filter)
Definition: median_filter.h:41
float noise_measurement
noise of measurement, for state filter
#define FAST9_LOW_THRESHOLD
int16_t flow_y
The y direction flow in subpixels.
Definition: image.h:64
uint16_t search_distance
Search distance for blockmatching alg.
float divergence
Divergence as determined with a linear flow fit.
float surface_roughness
Surface roughness as determined with a linear optical flow fit.
struct timeval frame_time
Definition: edge_flow.h:67
int32_t * x
Definition: edge_flow.h:65
struct State state
Definition: state.c:36
int16_t flow_der_x
The derotated flow calculation in the x direction (in subpixels)