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
139 #ifndef OPTICFLOW_METHOD
140 #define OPTICFLOW_METHOD 0
144 #if OPTICFLOW_METHOD > 1
145 #error WARNING: Both Lukas Kanade and EdgeFlow are NOT selected
148 #ifndef OPTICFLOW_DEROTATION
149 #define OPTICFLOW_DEROTATION TRUE
153 #ifndef OPTICFLOW_DEROTATION_CORRECTION_FACTOR_X
154 #define OPTICFLOW_DEROTATION_CORRECTION_FACTOR_X 1.0
158 #ifndef OPTICFLOW_DEROTATION_CORRECTION_FACTOR_Y
159 #define OPTICFLOW_DEROTATION_CORRECTION_FACTOR_Y 1.0
163 #ifndef OPTICFLOW_MEDIAN_FILTER
164 #define OPTICFLOW_MEDIAN_FILTER FALSE
168 #ifndef OPTICFLOW_FEATURE_MANAGEMENT
169 #define OPTICFLOW_FEATURE_MANAGEMENT 0
173 #ifndef OPTICFLOW_FAST9_REGION_DETECT
174 #define OPTICFLOW_FAST9_REGION_DETECT 1
178 #ifndef OPTICFLOW_FAST9_NUM_REGIONS
179 #define OPTICFLOW_FAST9_NUM_REGIONS 9
183 #ifndef OPTICFLOW_ACTFAST_LONG_STEP
184 #define OPTICFLOW_ACTFAST_LONG_STEP 10
188 #ifndef OPTICFLOW_ACTFAST_SHORT_STEP
189 #define OPTICFLOW_ACTFAST_SHORT_STEP 2
193 #ifndef OPTICFLOW_ACTFAST_GRADIENT_METHOD
194 #define OPTICFLOW_ACTFAST_GRADIENT_METHOD 1
198 #ifndef OPTICFLOW_ACTFAST_MIN_GRADIENT
199 #define OPTICFLOW_ACTFAST_MIN_GRADIENT 10
204 #ifndef OPTICFLOW_BODY_TO_CAM_PHI
205 #define OPTICFLOW_BODY_TO_CAM_PHI 0
207 #ifndef OPTICFLOW_BODY_TO_CAM_THETA
208 #define OPTICFLOW_BODY_TO_CAM_THETA 0
210 #ifndef OPTICFLOW_BODY_TO_CAM_PSI
211 #define OPTICFLOW_BODY_TO_CAM_PSI -M_PI_2
216 #ifndef OPTICFLOW_TRACK_BACK
217 #define OPTICFLOW_TRACK_BACK FALSE
223 #ifndef OPTICFLOW_SHOW_FLOW
224 #define OPTICFLOW_SHOW_FLOW FALSE
231 #include "filters/median_filter.h"
237 static int cmp_flow(
const void *a,
const void *b);
238 static int cmp_array(
const void *a,
const void *b);
323 float error_threshold;
324 int n_iterations_RANSAC, n_samples_RANSAC, success_fit;
330 result->
fps = 1000.f / dt;
394 #if OPTICFLOW_SHOW_CORNERS
443 int32_t back_x, back_y, diff_x, diff_y, dist_squared;
444 int32_t back_track_threshold = 200;
450 diff_x = back_x - vectors[i].
pos.
x;
451 diff_y = back_y - vectors[i].
pos.
y;
452 dist_squared = diff_x * diff_x + diff_y * diff_y;
454 if (dist_squared > back_track_threshold) {
466 uint8_t color[4] = {0, 0, 0, 0};
467 uint8_t bad_color[4] = {0, 0, 0, 0};
481 error_threshold = 10.0f;
482 n_iterations_RANSAC = 20;
483 n_samples_RANSAC = 5;
485 n_samples_RANSAC, img->
w, img->
h, &fit_info);
525 float diff_flow_x = 0.f;
526 float diff_flow_y = 0.f;
530 float rotation_threshold = M_PI / 180.0f;
545 if (strcmp(OPTICFLOW_CAMERA.dev_name,
bottom_camera.dev_name) == 0) {
547 diff_flow_x = phi_diff * OPTICFLOW_CAMERA.camera_intrinsics.focal_x;
548 diff_flow_y = theta_diff * OPTICFLOW_CAMERA.camera_intrinsics.focal_y;
556 psi_diff, opticflow);
558 uint8_t color[4] = {255, 255, 255, 255};
559 uint8_t bad_color[4] = {255, 255, 255, 255};
590 (opticflow->
subpixel_factor * OPTICFLOW_CAMERA.camera_intrinsics.focal_x);
592 (opticflow->
subpixel_factor * OPTICFLOW_CAMERA.camera_intrinsics.focal_y);
635 struct flow_t *predicted_flow_vectors = malloc(
sizeof(
struct flow_t) * n_points);
637 float K[9] = {OPTICFLOW_CAMERA.camera_intrinsics.focal_x, 0.0f, OPTICFLOW_CAMERA.camera_intrinsics.center_x,
638 0.0f, OPTICFLOW_CAMERA.camera_intrinsics.focal_y, OPTICFLOW_CAMERA.camera_intrinsics.center_y,
642 float k = OPTICFLOW_CAMERA.camera_intrinsics.Dhane_k;
646 if (strcmp(OPTICFLOW_CAMERA.dev_name,
front_camera.dev_name) == 0) {
658 float x_n_new, y_n_new, x_pix_new, y_pix_new;
659 float predicted_flow_x, predicted_flow_y;
660 for (
uint16_t i = 0; i < n_points; i++) {
662 predicted_flow_vectors[i].
pos.
x = flow_vectors[i].
pos.
x;
663 predicted_flow_vectors[i].
pos.
y = flow_vectors[i].
pos.
y;
669 predicted_flow_x = A * x_n * y_n - B * x_n * x_n - B + C * y_n;
670 predicted_flow_y = -C * x_n + A + A * y_n * y_n - B * x_n * y_n;
672 x_n_new = x_n + predicted_flow_x;
673 y_n_new = y_n + predicted_flow_y;
680 predicted_flow_vectors[i].
error = 0;
682 predicted_flow_vectors[i].
flow_x = 0;
683 predicted_flow_vectors[i].
flow_y = 0;
687 predicted_flow_vectors[i].
flow_x = 0;
688 predicted_flow_vectors[i].
flow_y = 0;
692 return predicted_flow_vectors;
727 if (!exists) { c1++; }
741 region_count[i] = calloc(2,
sizeof(
uint16_t));
742 region_count[i][0] = 0;
743 region_count[i][1] = i;
751 region_count[region_index][0]++;
761 roi[0] = (region_count[i][1] % root_regions) * (img->
w / root_regions);
762 roi[1] = (region_count[i][1] / root_regions) * (img->
h / root_regions);
763 roi[2] = roi[0] + (img->
w / root_regions);
764 roi[3] = roi[1] + (img->
h / root_regions);
774 for (
uint16_t j = 0; j < new_count; j++) {
801 free(region_count[i]);
820 static uint8_t current_frame_nr = 0;
822 static uint8_t previous_frame_offset[2] = {1, 1};
826 displacement.
x = calloc(img->
w,
sizeof(
int32_t));
827 displacement.
y = calloc(img->
h,
sizeof(
int32_t));
834 edge_hist[i].
x = calloc(img->
w,
sizeof(
int32_t));
835 edge_hist[i].
y = calloc(img->
h,
sizeof(
int32_t));
860 int32_t *edge_hist_x = edge_hist[current_frame_nr].
x;
861 int32_t *edge_hist_y = edge_hist[current_frame_nr].
y;
875 int32_t *prev_edge_histogram_x = edge_hist[previous_frame_nr[0]].
x;
876 int32_t *prev_edge_histogram_y = edge_hist[previous_frame_nr[1]].
y;
883 der_shift_x = (
int16_t)((edge_hist[current_frame_nr].eulers.phi - edge_hist[previous_frame_nr[0]].
eulers.
phi) *
885 der_shift_y = (
int16_t)((edge_hist[current_frame_nr].eulers.theta - edge_hist[previous_frame_nr[1]].
eulers.
theta) *
891 displacement.
x, img->
w,
892 window_size, disp_range, der_shift_x);
894 displacement.
y, img->
h,
895 window_size, disp_range, der_shift_y);
901 window_size + disp_range, RES);
904 window_size + disp_range, RES);
941 float time_diff_x = (
float)(
timeval_diff(&edge_hist[previous_frame_nr[0]].frame_time, &img->
ts)) / 1000.;
942 float time_diff_y = (float)(
timeval_diff(&edge_hist[previous_frame_nr[1]].frame_time, &img->
ts)) / 1000.;
943 fps_x = 1 / (time_diff_x);
944 fps_y = 1 / (time_diff_y);
964 #if OPTICFLOW_SHOW_FLOW
968 current_frame_nr = (current_frame_nr + 1) % MAX_HORIZON;
971 free(displacement.
x);
972 free(displacement.
y);
988 bool flow_successful =
false;
991 static int8_t switch_counter = -1;
992 if (switch_counter != opticflow->
method) {
994 switch_counter = opticflow->
method;
1002 if (opticflow->
method == 0) {
1004 }
else if (opticflow->
method == 1) {
1015 return flow_successful;
1027 msec = (finishtime->tv_sec - starttime->tv_sec) * 1000;
1028 msec += (finishtime->tv_usec - starttime->tv_usec) / 1000;
1058 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
int32_t flow_y
The y direction flow in subpixels.
#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
uint16_t max_track_corners
Maximum amount of corners Lucas Kanade should track.
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 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.
#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 in subpixels.
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 in subpixels.
#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...
#define FAST9_MAX_CORNERS
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
int32_t flow_x
The x direction flow in subpixels.
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.
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.