diff --git a/conf/airframes/TUDELFT/tudelft_ardrone2_opticflow_indi.xml b/conf/airframes/TUDELFT/tudelft_ardrone2_opticflow_indi.xml
new file mode 100644
index 0000000000..da98cf1f98
--- /dev/null
+++ b/conf/airframes/TUDELFT/tudelft_ardrone2_opticflow_indi.xml
@@ -0,0 +1,224 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/modules/cv_opticflow.xml b/conf/modules/cv_opticflow.xml
index d8273e1fbc..b3b7e07c22 100644
--- a/conf/modules/cv_opticflow.xml
+++ b/conf/modules/cv_opticflow.xml
@@ -31,6 +31,7 @@
+
@@ -58,6 +59,7 @@
+
diff --git a/sw/airborne/modules/computer_vision/lib/vision/edge_flow.c b/sw/airborne/modules/computer_vision/lib/vision/edge_flow.c
index db5304603d..270b49be0e 100644
--- a/sw/airborne/modules/computer_vision/lib/vision/edge_flow.c
+++ b/sw/airborne/modules/computer_vision/lib/vision/edge_flow.c
@@ -121,10 +121,10 @@ void calculate_edge_histogram(struct image_t *img, int32_t edge_histogram[],
for (y = 0; y < image_height; y++) {
sobel_sum = 0;
- for (c = -1; c <= 1; c++) {
- idx = interlace * (image_width * y + (x + c)); // 2 for interlace
+ for (c = -1; c <= 1; c+=2) {
+ idx = interlace * (image_width * y + (x + c));
- sobel_sum += Sobel[c + 1] * (int32_t)img_buf[idx + 1];
+ sobel_sum += Sobel[c + 1] * (int32_t)img_buf[idx];
}
sobel_sum = abs(sobel_sum);
if (sobel_sum > edge_threshold) {
@@ -140,10 +140,10 @@ void calculate_edge_histogram(struct image_t *img, int32_t edge_histogram[],
for (x = 0; x < image_width; x++) {
sobel_sum = 0;
- for (c = -1; c <= 1; c++) {
- idx = interlace * (image_width * (y + c) + x); // 2 for interlace
+ for (c = -1; c <= 1; c+=2) {
+ idx = interlace * (image_width * (y + c) + x);
- sobel_sum += Sobel[c + 1] * (int32_t)img_buf[idx + 1];
+ sobel_sum += Sobel[c + 1] * (int32_t)img_buf[idx];
}
sobel_sum = abs(sobel_sum);
if (sobel_sum > edge_threshold) {
@@ -159,7 +159,7 @@ void calculate_edge_histogram(struct image_t *img, int32_t edge_histogram[],
* Calculate_displacement calculates the displacement between two histograms
* @param[in] *edge_histogram The edge histogram from the current frame_step
* @param[in] *edge_histogram_prev The edge histogram from the previous frame_step
- * @param[in] *displacement array with pixel displacement of the sequential edge histograms
+ * @param[out] *displacement array with pixel displacement of the sequential edge histograms
* @param[in] size Indicating the size of the displacement array
* @param[in] window Indicating the search window size
* @param[in] disp_range Indicating the maximum disparity range for the block matching
@@ -196,10 +196,8 @@ void calculate_edge_displacement(int32_t *edge_histogram, int32_t *edge_histogra
if (border[0] >= border[1] || abs(der_shift) >= 10) {
SHIFT_TOO_FAR = 1;
}
- {
// TODO: replace with arm offset subtract
for (x = border[0]; x < border[1]; x++) {
- displacement[x] = 0;
if (!SHIFT_TOO_FAR) {
for (c = -D; c <= D; c++) {
SAD_temp[c + D] = 0;
@@ -211,8 +209,6 @@ void calculate_edge_displacement(int32_t *edge_histogram, int32_t *edge_histogra
} else {
}
}
- }
-
}
/**
@@ -271,7 +267,7 @@ void line_fit(int32_t *displacement, int32_t *divergence, int32_t *flow, uint32_
// compute fixed sums
int32_t xend = size_int - border_int - 1;
sumX = xend * (xend + 1) / 2 - border_int * (border_int + 1) / 2 + border_int;
- sumX2 = xend * (xend + 1) * (2 * xend + 1) / 6;
+ sumX2 = xend * (xend + 1) * (2 * xend + 1) / 6 - border_int * (border_int + 1) * (2 * border_int + 1) / 6 + border_int*border_int;
xMean = (size_int - 1) / 2;
count = size_int - 2 * border_int;
diff --git a/sw/airborne/modules/computer_vision/lib/vision/image.c b/sw/airborne/modules/computer_vision/lib/vision/image.c
index 4f91923975..1c8b01919e 100644
--- a/sw/airborne/modules/computer_vision/lib/vision/image.c
+++ b/sw/airborne/modules/computer_vision/lib/vision/image.c
@@ -353,6 +353,7 @@ void pyramid_build(struct image_t *input, struct image_t *output_array, uint8_t
* This outputs a subpixel window image in grayscale
* Currently only works with Grayscale images as input but could be upgraded to
* also support YUV422 images.
+ * You can and should only ask a subpixel window of a center point that is w/2 pixels away from the edges
* @param[in] *input Input image (grayscale only)
* @param[out] *output Window output (width and height is used to calculate the window size)
* @param[in] *center Center point in subpixel coordinates
@@ -369,18 +370,18 @@ void image_subpixel_window(struct image_t *input, struct image_t *output, struct
// Calculate the window size
uint16_t half_window = output->w / 2;
- uint32_t subpixel_w = input->w * subpixel_factor;
- uint32_t subpixel_h = input->h * subpixel_factor;
+ uint32_t subpixel_w = (input->w -2) * subpixel_factor;
+ uint32_t subpixel_h = (input->h -2) * subpixel_factor;
// Go through the whole window size in normal coordinates
for (uint16_t i = 0; i < output->w; i++) {
for (uint16_t j = 0; j < output->h; j++) {
// Calculate the subpixel coordinate
- uint32_t x = center->x + border_size * subpixel_factor + (i - half_window) * subpixel_factor ;
- uint32_t y = center->y + border_size * subpixel_factor + (j - half_window) * subpixel_factor ;
+ uint32_t x = center->x + border_size * subpixel_factor + (i - half_window) * subpixel_factor;
+ uint32_t y = center->y + border_size * subpixel_factor + (j - half_window) * subpixel_factor;
- BoundUpper(x, subpixel_w - 1);
- BoundUpper(y, subpixel_h - 1);
+ BoundUpper(x, subpixel_w);
+ BoundUpper(y, subpixel_h);
// Calculate the original pixel coordinate
uint16_t orig_x = x / subpixel_factor;
diff --git a/sw/airborne/modules/computer_vision/lib/vision/lucas_kanade.c b/sw/airborne/modules/computer_vision/lib/vision/lucas_kanade.c
index 7c03cc7150..25659cb0a1 100644
--- a/sw/airborne/modules/computer_vision/lib/vision/lucas_kanade.c
+++ b/sw/airborne/modules/computer_vision/lib/vision/lucas_kanade.c
@@ -331,8 +331,9 @@ struct flow_t *opticFlowLK_flat(struct image_t *new_img, struct image_t *old_img
vectors[new_p].pos.y + vectors[new_p].flow_y
};
// If the pixel is outside ROI, do not track it
- if (new_point.x / subpixel_factor < half_window_size || (old_img->w - new_point.x / subpixel_factor) < half_window_size
- || new_point.y / subpixel_factor < half_window_size || (old_img->h - new_point.y / subpixel_factor) < half_window_size) {
+ if (new_point.x / subpixel_factor < half_window_size || (old_img->w - new_point.x / subpixel_factor) <= half_window_size
+ || new_point.y / subpixel_factor < half_window_size || (old_img->h - new_point.y / subpixel_factor) <= half_window_size
+ || new_point.x / subpixel_factor > old_img->w || new_point.y / subpixel_factor > old_img->h) {
tracked = FALSE;
break;
}
diff --git a/sw/airborne/modules/computer_vision/opticflow/opticflow_calculator.c b/sw/airborne/modules/computer_vision/opticflow/opticflow_calculator.c
index 67c3a6b788..34ef440c5d 100644
--- a/sw/airborne/modules/computer_vision/opticflow/opticflow_calculator.c
+++ b/sw/airborne/modules/computer_vision/opticflow/opticflow_calculator.c
@@ -95,13 +95,18 @@ PRINT_CONFIG_VAR(OPTICFLOW_WINDOW_SIZE)
#ifndef OPTICFLOW_SEARCH_DISTANCE
#define OPTICFLOW_SEARCH_DISTANCE 20
#endif
-PRINT_CONFIG_VAR(OPTICFLOW_MAX_SEARCH_DISTANCE)
+PRINT_CONFIG_VAR(OPTICFLOW_SEARCH_DISTANCE)
#ifndef OPTICFLOW_SUBPIXEL_FACTOR
#define OPTICFLOW_SUBPIXEL_FACTOR 10
#endif
PRINT_CONFIG_VAR(OPTICFLOW_SUBPIXEL_FACTOR)
+#ifndef OPTICFLOW_RESOLUTION_FACTOR
+#define OPTICFLOW_RESOLUTION_FACTOR 100
+#endif
+PRINT_CONFIG_VAR(OPTICFLOW_RESOLUTION_FACTOR)
+
#ifndef OPTICFLOW_MAX_ITERATIONS
#define OPTICFLOW_MAX_ITERATIONS 10
#endif
@@ -194,23 +199,9 @@ static int cmp_flow(const void *a, const void *b);
/**
* Initialize the opticflow calculator
* @param[out] *opticflow The new optical flow calculator
- * @param[in] *w The image width
- * @param[in] *h The image height
*/
-void opticflow_calc_init(struct opticflow_t *opticflow, uint16_t w, uint16_t h)
+void opticflow_calc_init(struct opticflow_t *opticflow)
{
-
- init_median_filter(&vel_x_filt);
- init_median_filter(&vel_y_filt);
-
- /* Create the image buffers */
- image_create(&opticflow->img_gray, w, h, IMAGE_GRAYSCALE);
- image_create(&opticflow->prev_img_gray, w, h, IMAGE_GRAYSCALE);
-
- /* Set the previous values */
- opticflow->got_first_img = false;
- FLOAT_RATES_ZERO(opticflow->prev_rates);
-
/* Set the default values */
opticflow->method = OPTICFLOW_METHOD; //0 = LK_fast9, 1 = Edgeflow
opticflow->window_size = OPTICFLOW_WINDOW_SIZE;
@@ -221,6 +212,7 @@ void opticflow_calc_init(struct opticflow_t *opticflow, uint16_t w, uint16_t h)
opticflow->max_track_corners = OPTICFLOW_MAX_TRACK_CORNERS;
opticflow->subpixel_factor = OPTICFLOW_SUBPIXEL_FACTOR;
+ opticflow->resolution_factor = OPTICFLOW_RESOLUTION_FACTOR;
opticflow->max_iterations = OPTICFLOW_MAX_ITERATIONS;
opticflow->threshold_vec = OPTICFLOW_THRESHOLD_VEC;
opticflow->pyramid_level = OPTICFLOW_PYRAMID_LEVEL;
@@ -234,7 +226,6 @@ void opticflow_calc_init(struct opticflow_t *opticflow, uint16_t w, uint16_t h)
opticflow->fast9_padding = OPTICFLOW_FAST9_PADDING;
opticflow->fast9_rsize = 512;
opticflow->fast9_ret_corners = malloc(sizeof(struct point_t) * opticflow->fast9_rsize);
-
}
/**
* Run the optical flow with fast9 and lukaskanade on a new image frame
@@ -247,7 +238,17 @@ void calc_fast9_lukas_kanade(struct opticflow_t *opticflow, struct opticflow_sta
struct opticflow_result_t *result)
{
if (opticflow->just_switched_method) {
- opticflow_calc_init(opticflow, img->w, img->h);
+ // Create the image buffers
+ image_create(&opticflow->img_gray, img->w, img->h, IMAGE_GRAYSCALE);
+ image_create(&opticflow->prev_img_gray, img->w, img->h, IMAGE_GRAYSCALE);
+
+ // Set the previous values
+ opticflow->got_first_img = false;
+ FLOAT_RATES_ZERO(opticflow->prev_rates);
+
+ // Init median filters with zeros
+ init_median_filter(&vel_x_filt);
+ init_median_filter(&vel_y_filt);
}
// variables for size_divergence:
@@ -471,7 +472,7 @@ void calc_edgeflow_tot(struct opticflow_t *opticflow, struct opticflow_state_t *
window_size = MAX_WINDOW_SIZE;
}
- uint16_t RES = opticflow->subpixel_factor;
+ uint16_t RES = opticflow->resolution_factor;
//......................Calculating EdgeFlow..................... //
@@ -526,7 +527,7 @@ void calc_edgeflow_tot(struct opticflow_t *opticflow, struct opticflow_state_t *
/* Save Resulting flow in results
* Warning: The flow detected here is different in sign
- * and size, therefore this will be multiplied with
+ * and size, therefore this will be divided with
* the same subpixel factor and -1 to make it on par with
* the LK algorithm of t opticalflow_calculator.c
* */
@@ -536,12 +537,15 @@ void calc_edgeflow_tot(struct opticflow_t *opticflow, struct opticflow_state_t *
result->flow_x = (int16_t)edgeflow.flow_x / previous_frame_offset[0];
result->flow_y = (int16_t)edgeflow.flow_y / previous_frame_offset[1];
+ result->flow_x = (int16_t)edgeflow.flow_x / RES;
+ result->flow_y = (int16_t)edgeflow.flow_y / RES;
+
//Fill up the results optic flow to be on par with LK_fast9
result->flow_der_x = result->flow_x;
result->flow_der_y = result->flow_y;
result->corner_cnt = getAmountPeaks(edge_hist_x, 500 , img->w);
result->tracked_cnt = getAmountPeaks(edge_hist_x, 500 , img->w);
- result->divergence = (float)edgeflow.flow_x / RES;
+ result->divergence = (float)edgeflow.div_x / RES;
result->div_size = 0.0f;
result->noise_measurement = 0.0f;
result->surface_roughness = 0.0f;
@@ -584,6 +588,10 @@ void calc_edgeflow_tot(struct opticflow_t *opticflow, struct opticflow_state_t *
#endif
// Increment and wrap current time frame
current_frame_nr = (current_frame_nr + 1) % MAX_HORIZON;
+
+ // Free malloc'd variables
+ free(displacement.x);
+ free(displacement.y);
}
diff --git a/sw/airborne/modules/computer_vision/opticflow/opticflow_calculator.h b/sw/airborne/modules/computer_vision/opticflow/opticflow_calculator.h
index 10a6805670..1fa444c642 100644
--- a/sw/airborne/modules/computer_vision/opticflow/opticflow_calculator.h
+++ b/sw/airborne/modules/computer_vision/opticflow/opticflow_calculator.h
@@ -57,6 +57,7 @@ struct opticflow_t {
float derotation_correction_factor_y; ///< Correction factor for derotation in Y axis, determined from a fit from the gyros and flow rotation. (wrong FOV, camera not in center)
uint16_t subpixel_factor; ///< The amount of subpixels per pixel
+ uint16_t resolution_factor; ///< The resolution in EdgeFlow to determine the Divergence
uint8_t max_iterations; ///< The maximum amount of iterations the Lucas Kanade algorithm should do
uint8_t threshold_vec; ///< The threshold in x, y subpixels which the algorithm should stop
uint8_t pyramid_level; ///< Number of pyramid levels used in Lucas Kanade algorithm (0 == no pyramids used)
@@ -72,7 +73,7 @@ struct opticflow_t {
};
-void opticflow_calc_init(struct opticflow_t *opticflow, uint16_t w, uint16_t h);
+void opticflow_calc_init(struct opticflow_t *opticflow);
void opticflow_calc_frame(struct opticflow_t *opticflow, struct opticflow_state_t *state, struct image_t *img,
struct opticflow_result_t *result);
diff --git a/sw/airborne/modules/computer_vision/opticflow_module.c b/sw/airborne/modules/computer_vision/opticflow_module.c
index dcfa16d6cd..4bb6b6c90b 100644
--- a/sw/airborne/modules/computer_vision/opticflow_module.c
+++ b/sw/airborne/modules/computer_vision/opticflow_module.c
@@ -124,6 +124,7 @@ void opticflow_module_init(void)
// Initialize the opticflow calculation
opticflow_got_result = false;
+ opticflow_calc_init(&opticflow);
cv_add_to_device(&OPTICFLOW_CAMERA, opticflow_module_calc);