53 #define OPTICFLOW_SHOW_CORNERS 0
55 #define EXHAUSTIVE_FAST 0
68 #ifndef OPTICFLOW_CORNER_METHOD
69 #define OPTICFLOW_CORNER_METHOD ACT_FAST
74 #ifndef OPTICFLOW_MAX_TRACK_CORNERS
75 #define OPTICFLOW_MAX_TRACK_CORNERS 25
79 #ifndef OPTICFLOW_WINDOW_SIZE
80 #define OPTICFLOW_WINDOW_SIZE 10
84 #ifndef OPTICFLOW_SEARCH_DISTANCE
85 #define OPTICFLOW_SEARCH_DISTANCE 20
89 #ifndef OPTICFLOW_SUBPIXEL_FACTOR
90 #define OPTICFLOW_SUBPIXEL_FACTOR 10
94 #ifndef OPTICFLOW_RESOLUTION_FACTOR
95 #define OPTICFLOW_RESOLUTION_FACTOR 100
99 #ifndef OPTICFLOW_MAX_ITERATIONS
100 #define OPTICFLOW_MAX_ITERATIONS 10
104 #ifndef OPTICFLOW_THRESHOLD_VEC
105 #define OPTICFLOW_THRESHOLD_VEC 2
109 #ifndef OPTICFLOW_PYRAMID_LEVEL
110 #define OPTICFLOW_PYRAMID_LEVEL 2
114 #ifndef OPTICFLOW_FAST9_ADAPTIVE
115 #define OPTICFLOW_FAST9_ADAPTIVE TRUE
119 #ifndef OPTICFLOW_FAST9_THRESHOLD
120 #define OPTICFLOW_FAST9_THRESHOLD 20
124 #ifndef OPTICFLOW_FAST9_MIN_DISTANCE
125 #define OPTICFLOW_FAST9_MIN_DISTANCE 10
129 #ifndef OPTICFLOW_FAST9_PADDING
130 #define OPTICFLOW_FAST9_PADDING 20
135 #define FAST9_LOW_THRESHOLD 5
136 #define FAST9_HIGH_THRESHOLD 60
138 #ifndef OPTICFLOW_METHOD
139 #define OPTICFLOW_METHOD 0
143 #if OPTICFLOW_METHOD > 1
144 #error WARNING: Both Lukas Kanade and EdgeFlow are NOT selected
147 #ifndef OPTICFLOW_DEROTATION
148 #define OPTICFLOW_DEROTATION TRUE
152 #ifndef OPTICFLOW_DEROTATION_CORRECTION_FACTOR_X
153 #define OPTICFLOW_DEROTATION_CORRECTION_FACTOR_X 1.0
157 #ifndef OPTICFLOW_DEROTATION_CORRECTION_FACTOR_Y
158 #define OPTICFLOW_DEROTATION_CORRECTION_FACTOR_Y 1.0
162 #ifndef OPTICFLOW_MEDIAN_FILTER
163 #define OPTICFLOW_MEDIAN_FILTER FALSE
167 #ifndef OPTICFLOW_FEATURE_MANAGEMENT
168 #define OPTICFLOW_FEATURE_MANAGEMENT 0
172 #ifndef OPTICFLOW_FAST9_REGION_DETECT
173 #define OPTICFLOW_FAST9_REGION_DETECT 1
177 #ifndef OPTICFLOW_FAST9_NUM_REGIONS
178 #define OPTICFLOW_FAST9_NUM_REGIONS 9
182 #ifndef OPTICFLOW_ACTFAST_LONG_STEP
183 #define OPTICFLOW_ACTFAST_LONG_STEP 10
187 #ifndef OPTICFLOW_ACTFAST_SHORT_STEP
188 #define OPTICFLOW_ACTFAST_SHORT_STEP 2
192 #ifndef OPTICFLOW_ACTFAST_GRADIENT_METHOD
193 #define OPTICFLOW_ACTFAST_GRADIENT_METHOD 1
197 #ifndef OPTICFLOW_ACTFAST_MIN_GRADIENT
198 #define OPTICFLOW_ACTFAST_MIN_GRADIENT 10
203 #ifndef OPTICFLOW_BODY_TO_CAM_PHI
204 #define OPTICFLOW_BODY_TO_CAM_PHI 0
206 #ifndef OPTICFLOW_BODY_TO_CAM_THETA
207 #define OPTICFLOW_BODY_TO_CAM_THETA 0
209 #ifndef OPTICFLOW_BODY_TO_CAM_PSI
210 #define OPTICFLOW_BODY_TO_CAM_PSI -M_PI_2
215 #ifndef OPTICFLOW_TRACK_BACK
216 #define OPTICFLOW_TRACK_BACK FALSE
222 #ifndef OPTICFLOW_SHOW_FLOW
223 #define OPTICFLOW_SHOW_FLOW FALSE
230 #include "filters/median_filter.h"
236 static int cmp_flow(
const void *a,
const void *b);
237 static int cmp_array(
const void *a,
const void *b);
322 float error_threshold;
323 int n_iterations_RANSAC, n_samples_RANSAC, success_fit;
329 result->
fps = 1000.f / dt;
389 #if OPTICFLOW_SHOW_CORNERS
438 int32_t back_x, back_y, diff_x, diff_y, dist_squared;
439 int32_t back_track_threshold = 200;
445 diff_x = back_x - vectors[i].
pos.
x;
446 diff_y = back_y - vectors[i].
pos.
y;
447 dist_squared = diff_x * diff_x + diff_y * diff_y;
449 if (dist_squared > back_track_threshold) {
461 uint8_t color[4] = {0, 0, 0, 0};
462 uint8_t bad_color[4] = {0, 0, 0, 0};
476 error_threshold = 10.0f;
477 n_iterations_RANSAC = 20;
478 n_samples_RANSAC = 5;
480 n_samples_RANSAC, img->
w, img->
h, &fit_info);
520 float diff_flow_x = 0.f;
521 float diff_flow_y = 0.f;
525 float rotation_threshold = M_PI / 180.0f;
540 if (strcmp(OPTICFLOW_CAMERA.dev_name,
"/dev/video0") == 0) {
543 diff_flow_x = phi_diff * OPTICFLOW_CAMERA.camera_intrinsics.focal_x;
544 diff_flow_y = theta_diff * OPTICFLOW_CAMERA.camera_intrinsics.focal_y;
553 psi_diff, opticflow);
555 uint8_t color[4] = {255, 255, 255, 255};
556 uint8_t bad_color[4] = {255, 255, 255, 255};
587 (opticflow->
subpixel_factor * OPTICFLOW_CAMERA.camera_intrinsics.focal_x);
589 (opticflow->
subpixel_factor * OPTICFLOW_CAMERA.camera_intrinsics.focal_y);
632 struct flow_t *predicted_flow_vectors = malloc(
sizeof(
struct flow_t) * n_points);
634 float K[9] = {OPTICFLOW_CAMERA.camera_intrinsics.focal_x, 0.0f, OPTICFLOW_CAMERA.camera_intrinsics.center_x,
635 0.0f, OPTICFLOW_CAMERA.camera_intrinsics.focal_y, OPTICFLOW_CAMERA.camera_intrinsics.center_y,
639 float k = OPTICFLOW_CAMERA.camera_intrinsics.Dhane_k;
643 if (strcmp(OPTICFLOW_CAMERA.dev_name,
"/dev/video1") == 0) {
655 float x_n_new, y_n_new, x_pix_new, y_pix_new;
656 float predicted_flow_x, predicted_flow_y;
657 for (
uint16_t i = 0; i < n_points; i++) {
659 predicted_flow_vectors[i].
pos.
x = flow_vectors[i].
pos.
x;
660 predicted_flow_vectors[i].
pos.
y = flow_vectors[i].
pos.
y;
666 predicted_flow_x = A * x_n * y_n - B * x_n * x_n - B + C * y_n;
667 predicted_flow_y = -C * x_n + A + A * y_n * y_n - B * x_n * y_n;
669 x_n_new = x_n + predicted_flow_x;
670 y_n_new = y_n + predicted_flow_y;
677 predicted_flow_vectors[i].
error = 0;
679 predicted_flow_vectors[i].
flow_x = 0;
680 predicted_flow_vectors[i].
flow_y = 0;
684 predicted_flow_vectors[i].
flow_x = 0;
685 predicted_flow_vectors[i].
flow_y = 0;
689 return predicted_flow_vectors;
724 if (!exists) { c1++; }
738 region_count[i] = calloc(2,
sizeof(
uint16_t));
739 region_count[i][0] = 0;
740 region_count[i][1] = i;
748 region_count[region_index][0]++;
758 roi[0] = (region_count[i][1] % root_regions) * (img->
w / root_regions);
759 roi[1] = (region_count[i][1] / root_regions) * (img->
h / root_regions);
760 roi[2] = roi[0] + (img->
w / root_regions);
761 roi[3] = roi[1] + (img->
h / root_regions);
771 for (
uint16_t j = 0; j < new_count; j++) {
798 free(region_count[i]);
817 static uint8_t current_frame_nr = 0;
819 static uint8_t previous_frame_offset[2] = {1, 1};
823 displacement.
x = calloc(img->
w,
sizeof(
int32_t));
824 displacement.
y = calloc(img->
h,
sizeof(
int32_t));
831 edge_hist[i].
x = calloc(img->
w,
sizeof(
int32_t));
832 edge_hist[i].
y = calloc(img->
h,
sizeof(
int32_t));
857 int32_t *edge_hist_x = edge_hist[current_frame_nr].
x;
858 int32_t *edge_hist_y = edge_hist[current_frame_nr].
y;
872 int32_t *prev_edge_histogram_x = edge_hist[previous_frame_nr[0]].
x;
873 int32_t *prev_edge_histogram_y = edge_hist[previous_frame_nr[1]].
y;
880 der_shift_x = (
int16_t)((edge_hist[current_frame_nr].eulers.phi - edge_hist[previous_frame_nr[0]].
eulers.
phi) *
882 der_shift_y = (
int16_t)((edge_hist[current_frame_nr].eulers.theta - edge_hist[previous_frame_nr[1]].
eulers.
theta) *
888 displacement.
x, img->
w,
889 window_size, disp_range, der_shift_x);
891 displacement.
y, img->
h,
892 window_size, disp_range, der_shift_y);
898 window_size + disp_range, RES);
901 window_size + disp_range, RES);
938 float time_diff_x = (
float)(
timeval_diff(&edge_hist[previous_frame_nr[0]].frame_time, &img->
ts)) / 1000.;
939 float time_diff_y = (float)(
timeval_diff(&edge_hist[previous_frame_nr[1]].frame_time, &img->
ts)) / 1000.;
940 fps_x = 1 / (time_diff_x);
941 fps_y = 1 / (time_diff_y);
961 #if OPTICFLOW_SHOW_FLOW
965 current_frame_nr = (current_frame_nr + 1) % MAX_HORIZON;
968 free(displacement.
x);
969 free(displacement.
y);
985 bool flow_successful =
false;
988 static int8_t switch_counter = -1;
989 if (switch_counter != opticflow->
method) {
991 switch_counter = opticflow->
method;
999 if (opticflow->
method == 0) {
1001 }
else if (opticflow->
method == 1) {
1012 return flow_successful;
1024 msec = (finishtime->tv_sec - starttime->tv_sec) * 1000;
1025 msec += (finishtime->tv_usec - starttime->tv_usec) / 1000;
1055 return pa[0] - pb[0];
bool track_back
Whether to track flow vectors back to the previous image, in order to check if the back-tracked flow ...
int actfast_gradient_method
Whether to use a simple or Sobel filter.
int16_t flow_y
Flow in y direction from the camera (in subpixels) with Y positive to the bottom. ...
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.
int16_t flow_der_y
The derotated flow calculation in the y direction (in subpixels)
#define FAST9_HIGH_THRESHOLD
bool calc_fast9_lukas_kanade(struct opticflow_t *opticflow, struct image_t *img, struct opticflow_result_t *result)
Run the optical flow with fast9 and lukaskanade on a new image frame.
struct FloatRMat body_to_cam
float div_size
Divergence as determined with the size_divergence script.
bool feature_management
Decides whether to keep track corners in memory for the next frame instead of re-detecting every time...
uint8_t max_iterations
The maximum amount of iterations the Lucas Kanade algorithm should do.
#define float_rmat_of_eulers
bool opticflow_calc_frame(struct opticflow_t *opticflow, struct image_t *img, struct opticflow_result_t *result)
Run the optical flow on a new image frame.
#define OPTICFLOW_TRACK_BACK
struct opticflow_t opticflow
Opticflow calculations.
struct MedianFilter3Float vel_filt
#define OPTICFLOW_ACTFAST_MIN_GRADIENT
uint16_t window_size
Window size for the blockmatching algorithm (general value for all methods)
#define OPTICFLOW_ACTFAST_SHORT_STEP
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...
#define OPTICFLOW_SHOW_FLOW
#define FLOAT_EULERS_ZERO(_e)
uint16_t fast9_rsize
Amount of corners allocated.
#define OPTICFLOW_PYRAMID_LEVEL
Calculate velocity from optic flow.
bool median_filter
Decides to use a median filter on the velocity.
#define VECT3_ASSIGN(_a, _x, _y, _z)
uint32_t getAmountPeaks(int32_t *edgehist, int32_t thres, int32_t size)
getAmountPeaks, calculates the amount of peaks in a edge histogram
#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.
#define OPTICFLOW_BODY_TO_CAM_PHI
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 ...
void image_show_flow_color(struct image_t *img, struct flow_t *vectors, uint16_t points_cnt, uint8_t subpixel_factor, const uint8_t *color, const uint8_t *bad_color)
Shows the flow from a specific point to a new point This works on YUV422 and Grayscale images...
#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.
#define OPTICFLOW_FAST9_ADAPTIVE
bool calc_edgeflow_tot(struct opticflow_t *opticflow, struct image_t *img, struct opticflow_result_t *result)
Run the optical flow with EDGEFLOW on a new image frame.
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.
static int cmp_flow(const void *a, const void *b)
Compare two flow vectors based on flow distance Used for sorting.
Calculate divergence from flow vectors by looking at line sizes beteween the points.
struct FloatVect3 vel_body
The velocity in body frame (m/s) with X positive to the front of the aircraft, Y positive to the righ...
uint32_t x
The x coordinate of the point.
#define OPTICFLOW_ACTFAST_LONG_STEP
uint16_t resolution_factor
The resolution in EdgeFlow to determine the Divergence.
static struct flow_t * predict_flow_vectors(struct flow_t *flow_vectors, uint16_t n_points, float phi_diff, float theta_diff, float psi_diff, struct opticflow_t *opticflow)
uint8_t threshold_vec
The threshold in x, y subpixels which the algorithm should stop.
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.
bool derotation
Derotation switched on or off (depended on the quality of the gyroscope measurement) ...
Finds corners in an image by actively scanning the image.
uint16_t y_sub
The y subpixel coordinate of the point.
uint8_t method
Method to use to calculate the optical flow.
uint8_t max_track_corners
Maximum amount of corners Lucas Kanade should track.
uint8_t fast9_num_regions
The number of regions of interest the image is split into.
void opticflow_calc_init(struct opticflow_t *opticflow)
Initialize the opticflow calculator.
#define OPTICFLOW_DEROTATION_CORRECTION_FACTOR_Y
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.
Image helper functions like resizing, color filter, converters...
uint16_t tracked_cnt
The amount of tracked corners.
void float_rmat_transp_vmult(struct FloatVect3 *vb, struct FloatRMat *m_b2a, struct FloatVect3 *va)
rotate 3D vector by transposed rotation matrix.
#define OPTICFLOW_RESOLUTION_FACTOR
#define OPTICFLOW_FEATURE_MANAGEMENT
bool normalized_coords_to_distorted_pixels(float x_n, float y_n, float *x_pd, float *y_pd, float k, const float *K)
Transform normalized coordinates to distorted pixel coordinates.
uint16_t subpixel_factor
The amount of subpixels per pixel.
#define OPTICFLOW_FAST9_PADDING
bool 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.
int16_t flow_x
The x direction flow in subpixels.
#define OPTICFLOW_CORNER_METHOD
struct point_t * fast9_ret_corners
Corners.
#define OPTICFLOW_FAST9_THRESHOLD
struct image_t prev_img_gray
Previous gray image frame.
struct FloatVect3 vel_cam
The velocity in camera frame (m/s)
#define OPTICFLOW_BODY_TO_CAM_PSI
uint8_t fast9_threshold
FAST9 corner detection threshold.
bool just_switched_method
Boolean to check if methods has been switched (for reinitialization)
#define OPTICFLOW_FAST9_REGION_DETECT
void act_fast(struct image_t *img, uint8_t fast_threshold, uint16_t *num_corners, struct point_t **ret_corners, uint16_t n_agents, uint16_t n_time_steps, float long_step, float short_step, int min_gradient, int gradient_method)
Do an ACT-FAST corner detection.
Bind to agl ABI message and provide a filtered value to be used in flight plans.
struct point_t pos
The original position the flow comes from.
uint32_t y
The y coordinate of the point.
#define OPTICFLOW_WINDOW_SIZE
void image_to_grayscale(struct image_t *input, struct image_t *output)
Convert an image to grayscale.
uint16_t x_sub
The x subpixel coordinate of the point.
Functions for undistorting camera images.
struct image_t img_gray
Current gray image frame.
static int cmp_array(const void *a, const void *b)
Compare the rows of an integer (uint16_t) 2D array based on the first column.
uint32_t error
The matching error in the tracking process.
#define OPTICFLOW_FAST9_NUM_REGIONS
uint16_t corner_cnt
The amount of coners found by FAST9.
float fps
Frames per second of the optical flow calculation.
efficient fixed-point optical-flow calculation
#define OPTICFLOW_DEROTATION
bool show_flow
Whether to draw the flow vectors on the image. Watch out! This changes the image as will be received ...
struct timeval ts
The timestamp of creation.
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.
struct FloatEulers eulers
#define OPTICFLOW_SEARCH_DISTANCE
bool fast9_region_detect
Decides whether to detect fast9 corners in specific regions of interest or the whole image (only for ...
#define OPTICFLOW_DEROTATION_CORRECTION_FACTOR_X
uint16_t count
Number of times the point has been tracked successfully.
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.
bool distorted_pixels_to_normalized_coords(float x_pd, float y_pd, float *x_n, float *y_n, float k, const float *K)
Transform distorted pixel coordinates to normalized coordinates.
#define OPTICFLOW_ACTFAST_GRADIENT_METHOD
#define OPTICFLOW_BODY_TO_CAM_THETA
float derotation_correction_factor_x
Correction factor for derotation in x axis, determined from a fit from the gyros and flow rotation...
static void manage_flow_features(struct image_t *img, struct opticflow_t *opticflow, struct opticflow_result_t *result)
Grayscale image with only the Y part (uint8 per pixel)
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.
#define OPTICFLOW_MAX_TRACK_CORNERS
uint8_t corner_method
Method to use for determining where the corners are.
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.
#define OPTICFLOW_SUBPIXEL_FACTOR
int16_t flow_x
Flow in x direction from the camera (in subpixels) with X positive to the right.
#define OPTICFLOW_MAX_ITERATIONS
uint8_t pyramid_level
Number of pyramid levels used in Lucas Kanade algorithm (0 == no pyramids used)
struct FloatEulers eulers
Euler Angles at time of image.
float noise_measurement
noise of measurement, for state filter
float actfast_short_step
Step size to take when there is an edge to be followed.
#define FAST9_LOW_THRESHOLD
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, uint16_t *roi)
Do a FAST9 corner detection.
int16_t flow_y
The y direction flow in subpixels.
float actfast_long_step
Step size to take when there is no texture.
uint16_t search_distance
Search distance for blockmatching alg.
float divergence
Divergence as determined with a linear flow fit.
float derotation_correction_factor_y
Correction factor for derotation in Y axis, determined from a fit from the gyros and flow rotation...
float surface_roughness
Surface roughness as determined with a linear optical flow fit.
struct timeval frame_time
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)
float agl_dist_value_filtered
int16_t flow_der_x
The derotated flow calculation in the x direction (in subpixels)
int actfast_min_gradient
Threshold that decides when there is sufficient texture for edge following.