Opticflow pyramid build FPS improvements (#2825)

* Speeds up convolution and updates airframe settings

* Reduces PYRAMID_LEVEL to 0 for both cameras

* Updates comments and airframe settings
This commit is contained in:
Matteo Barbera
2022-02-17 10:11:33 +01:00
committed by GitHub
parent 742600628e
commit 3c2b64a5fd
2 changed files with 49 additions and 36 deletions
@@ -24,25 +24,32 @@
<configure name="USE_MAGNETOMETER" value="FALSE"/>
</module>
<module name="ins" type="hff_extended"/>
<define name="USE_SONAR"/>
<module name="pose_history"/>
<module name="bebop_cam"/>
<module name="bebop_cam">
<!-- IMPORTANT to limit these or FPS drops significantly -->
<define name="MT9F002_TARGET_FPS" value="30"/> <!-- Front cam -->
<define name="MT9V117_TARGET_FPS" value="60"/> <!-- Bottom cam -->
</module>
<module name="cv_opticflow">
<define name="OPTICFLOW_CAMERA" value="bottom_camera"/>
<define name="OPTICFLOW_DEROTATION_CORRECTION_FACTOR_X" value="0.8"/> <!--Obtained from a linefit-->
<define name="OPTICFLOW_DEROTATION_CORRECTION_FACTOR_Y" value="0.85"/> <!--Obtained from a linefit-->
<define name="OPTICFLOW_MAX_TRACK_CORNERS" value="10"/>
<configure name="OPTICFLOW_MAX_TRACK_CORNERS" value="20"/>
<define name="OPTICFLOW_FEATURE_MANAGEMENT" value="0"/>
<define name="OPTICFLOW_FPS" value="5"/>
<define name="OPTICFLOW_SHOW_FLOW" value="1"/>
<define name="OPTICFLOW_FPS" value="60"/>
<define name="OPTICFLOW_PYRAMID_LEVEL" value="0"/>
<define name="OPTICFLOW_SHOW_FLOW" value="0"/>
<define name="OPTICFLOW_CAMERA2" value="front_camera"/>
<define name="OPTICFLOW_DEROTATION_CORRECTION_FACTOR_X_CAMERA2" value="0.8"/> <!--Obtained from a linefit-->
<define name="OPTICFLOW_DEROTATION_CORRECTION_FACTOR_Y_CAMERA2" value="0.85"/> <!--Obtained from a linefit-->
<define name="OPTICFLOW_MAX_TRACK_CORNERS_CAMERA2" value="10"/>
<configure name="OPTICFLOW_MAX_TRACK_CORNERS_CAMERA2" value="30"/>
<define name="OPTICFLOW_FEATURE_MANAGEMENT_CAMERA2" value="0"/>
<define name="OPTICFLOW_FPS_CAMERA2" value="5"/>
<define name="OPTICFLOW_SHOW_FLOW_CAMERA2" value="1"/>
<define name="OPTICFLOW_FPS_CAMERA2" value="20"/>
<define name="OPTICFLOW_PYRAMID_LEVEL_CAMERA2" value="0"/>
<define name="OPTICFLOW_SHOW_FLOW_CAMERA2" value="0"/>
</module>
<module name="video_capture">
@@ -199,9 +206,4 @@
<define name="MAX_BAT_LEVEL" value="12.4" unit="V"/>
</section>
<section name="OPTICFLOW" prefix="OPTICFLOW_">
<define name="CORNER_METHOD" value="0"/>
<define name="MAX_TRACK_CORNERS" value="10"/>
</section>
</airframe>
@@ -140,13 +140,20 @@ void image_to_grayscale(struct image_t *input, struct image_t *output)
output->pprz_ts = input->pprz_ts;
// Copy the pixels
for (int y = 0; y < output->h; y++) {
for (int x = 0; x < output->w; x++) {
if (output->type == IMAGE_YUV422) {
int height = output->h;
int width = output->w;
if (output->type == IMAGE_YUV422) {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
*dest++ = 127; // U / V
*dest++ = *source; // Y
source += 2;
}
*dest++ = *source; // Y
source += 2;
}
} else {
for (int y = 0; y < height * width; y++) {
*dest++ = *source++; // Y
source++;
}
}
}
@@ -394,9 +401,10 @@ void image_add_border(struct image_t *input, struct image_t *output, uint8_t bor
/**
* This function takes previous padded pyramid level and outputs next level of pyramid without padding.
* For calculating new pixel value 5x5 filter matrix suggested by Bouguet is used:
* [1/16 1/8 3/4 1/8 1/16]' x [1/16 1/8 3/4 1/8 1/16]
* To avoid decimal numbers, all coefficients are multiplied by 10000.
* For calculating new pixel value 3x3 Gaussian filter matrix is used:
* [1/4 1/2 1/4]' x [1/4 1/2 1/4]
* Blur and downsample is performed with two 1D convolutions (horizontal then vertical)
* instead of a single 2D convolution, to increase performance
*
* @param[in] *input - input image (grayscale only)
* @param[out] *output - the output image
@@ -415,27 +423,30 @@ void pyramid_next_level(struct image_t *input, struct image_t *output, uint8_t b
uint16_t w = input->w;
int32_t sum = 0;
// Horizontal convolution
for (uint16_t i = 0; i != output->h; i++) {
for (uint16_t j = 0; j != output->w; j++) {
row = border_size + 2 * i; // First skip border, then every second pixel
col = border_size + 2 * j;
sum = 39 * (input_buf[(row - 2) * w + (col - 2)] + input_buf[(row - 2) * w + (col + 2)] +
input_buf[(row + 2) * w + (col - 2)] + input_buf[(row + 2) * w + (col + 2)]);
sum += 156 * (input_buf[(row - 2) * w + (col - 1)] + input_buf[(row - 2) * w + (col + 1)] +
input_buf[(row - 1) * w + (col + 2)] + input_buf[(row + 1) * w + (col - 2)]
+ input_buf[(row + 1) * w + (col + 2)] + input_buf[(row + 2) * w + (col - 1)] + input_buf[(row + 2) * w + (col + 1)] +
input_buf[(row - 1) * w + (col - 2)]);
sum += 234 * (input_buf[(row - 2) * w + (col)] + input_buf[(row) * w + (col - 2)] +
input_buf[(row) * w + (col + 2)] + input_buf[(row + 2) * w + (col)]);
sum += 625 * (input_buf[(row - 1) * w + (col - 1)] + input_buf[(row - 1) * w + (col + 1)] +
input_buf[(row + 1) * w + (col - 1)] + input_buf[(row + 1) * w + (col + 1)]);
sum += 938 * (input_buf[(row - 1) * w + (col)] + input_buf[(row) * w + (col - 1)] +
input_buf[(row) * w + (col + 1)] + input_buf[(row + 1) * w + (col)]);
sum += 1406 * input_buf[(row) * w + (col)];
sum = (input_buf[row * w + col]) >> 1;
sum += (input_buf[row * w + col + 1] + input_buf[row * w + col - 1]) >> 2;
output_buf[i * output->w + j] = sum / 10000;
output_buf[i * output->w + j] = sum;
}
}
// Vertical convolution
w = output->w;
for (uint16_t i = 0; i != output->h - border_size; i++) {
for (uint16_t j = 0; j != output->w - border_size; j++) {
// Wrong to add border_size again, but offset of a few px acceptable inaccuracy
row = border_size + i;
col = border_size + j;
sum = (output_buf[row * w + col]) >> 1;
sum += (output_buf[(row + 1) * w + col] + output_buf[(row - 1) * w + col]) >> 2;
output_buf[i * output->w + j] = sum;
}
}
}