Reverted to original ardrone2 makefile. Used astyle formating.

This commit is contained in:
hrvoje
2016-03-30 20:43:08 +02:00
parent c4892ad0f5
commit c33e454fdf
6 changed files with 220 additions and 224 deletions
+4 -24
View File
@@ -19,31 +19,11 @@
# <http://www.gnu.org/licenses/>.
#
include $(PAPARAZZI_SRC)/conf/Makefile.arm-linux-toolchain
#
# This Makefile uses the generic Makefile.arm-linux and adds upload rules for the ARDrone2
#
# Define OMAP A8 ARDrone2 specifc flags
FLOAT_ABI ?= -mfloat-abi=softfp
#FLOAT_ABI ?= -mfloat-abi=hard
# ARCH_CFLAGS ?= -O3 -marm -funsafe-math-optimizations -mcpu=cortex-a8 -mtune=cortex-a8 -march=armv7-a -mfpu=neon -ftree-vectorize -ftree-vectorizer-verbose=1 -ffast-math -fomit-frame-pointer -funroll-loops
ARCH_CFLAGS ?= -O3 -marm -mstructure-size-boundary=32 -funsafe-math-optimizations -mcpu=cortex-a8 -mtune=cortex-a8 -march=armv7-a -mfpu=neon -ftree-vectorize -ftree-vectorizer-verbose=1 -funroll-loops -ffast-math
# When -pg is used this cannot -fomit-frame-pointer
# -ffast-math is added in generic Makefile.linux later on..
# TODO: arm{?}strip -R .comment -R .note -R .note.ABI-tag ap.elf
# with armv7, unaligned data can still be read
CFLAGS += -DPPRZLINK_UNALIGNED_ACCESS=1
# add ARM specifc flags to CFLAGS, LDFLAGS
CFLAGS += $(FLOAT_ABI) $(ARCH_CFLAGS) -pg
LDFLAGS += $(FLOAT_ABI) -pg
CXXFLAGS += $(FLOAT_ABI) $(ARCH_CFLAGS) -pg
# include the common linux Makefile (common CFLAGS, actual targets)
include $(PAPARAZZI_SRC)/conf/Makefile.linux
include $(PAPARAZZI_SRC)/conf/Makefile.arm-linux
DRONE = $(PAPARAZZI_SRC)/sw/tools/parrot/ardrone2.py
@@ -240,36 +240,40 @@ void image_yuv422_downsample(struct image_t *input, struct image_t *output, uint
* @param[in] *input - input image (grayscale only)
* @param[out] *output - the output image
* @param[in] border_size - amount of padding around image. Padding is made by reflecting image elements at the edge
* Example: f e d c b a | a b c d e f | f e d c b a
* Example: f e d c b a | a b c d e f | f e d c b a
*/
void image_add_border(struct image_t *input, struct image_t *output, uint8_t border_size)
{
// Create padded image based on input
image_create(output, input->w + 2 * border_size, input->h + 2 * border_size, input->type);
// Create padded image based on input
image_create(output, input->w + 2 * border_size, input->h + 2 * border_size, input->type);
uint8_t *input_buf = (uint8_t *)input->buf;
uint8_t *output_buf = (uint8_t *)output->buf;
uint8_t *input_buf = (uint8_t *)input->buf;
uint8_t *output_buf = (uint8_t *)output->buf;
// Skip first `border_size` rows, iterate through next input->h rows
for (uint16_t i = border_size; i != (output->h - border_size); i++){
// Skip first `border_size` rows, iterate through next input->h rows
for (uint16_t i = border_size; i != (output->h - border_size); i++) {
// Mirror first `border_size` columns
for (uint8_t j = 0; j != border_size; j++)
output_buf[i * output->w + (border_size - 1 - j)] = input_buf[(i - border_size) * input->w + j];
// Mirror first `border_size` columns
for (uint8_t j = 0; j != border_size; j++) {
output_buf[i * output->w + (border_size - 1 - j)] = input_buf[(i - border_size) * input->w + j];
}
// Copy corresponding row values from input image
memcpy(&output_buf[i * output->w + border_size], &input_buf[(i - border_size) * input->w], sizeof(uint8_t) * input->w);
// Copy corresponding row values from input image
memcpy(&output_buf[i * output->w + border_size], &input_buf[(i - border_size) * input->w], sizeof(uint8_t) * input->w);
// Mirror last `border_size` columns
for (uint8_t j = 0; j != border_size; j++)
output_buf[i * output->w + output->w - border_size + j] = output_buf[i * output->w + output->w - border_size -1 - j];
}
// Mirror last `border_size` columns
for (uint8_t j = 0; j != border_size; j++) {
output_buf[i * output->w + output->w - border_size + j] = output_buf[i * output->w + output->w - border_size - 1 - j];
}
}
// Mirror first `border_size` and last `border_size` rows
for (uint8_t i = 0; i != border_size; i++){
memcpy(&output_buf[(border_size - 1) * output->w - i * output->w], &output_buf[border_size * output->w + i * output->w], sizeof(uint8_t) * output->w);
memcpy(&output_buf[(output->h - border_size) * output->w + i * output->w], &output_buf[(output->h - border_size - 1) * output->w - i * output->w], sizeof(uint8_t) * output->w);
}
// Mirror first `border_size` and last `border_size` rows
for (uint8_t i = 0; i != border_size; i++) {
memcpy(&output_buf[(border_size - 1) * output->w - i * output->w], &output_buf[border_size * output->w + i * output->w],
sizeof(uint8_t) * output->w);
memcpy(&output_buf[(output->h - border_size) * output->w + i * output->w],
&output_buf[(output->h - border_size - 1) * output->w - i * output->w], sizeof(uint8_t) * output->w);
}
}
/**
@@ -281,37 +285,43 @@ void image_add_border(struct image_t *input, struct image_t *output, uint8_t bor
* @param[in] *input - input image (grayscale only)
* @param[out] *output - the output image
* @param[in] border_size - amount of padding around image. Padding is made by reflecting image elements at the edge
* Example: f e d c b a | a b c d e f | f e d c b a
* Example: f e d c b a | a b c d e f | f e d c b a
*/
void pyramid_next_level(struct image_t *input, struct image_t *output, uint8_t border_size)
{
// Create output image, new image size is half the size of input image without padding (border)
image_create(output, (input->w + 1 - 2 * border_size) / 2, (input->h + 1 - 2 * border_size ) / 2, input->type);
// Create output image, new image size is half the size of input image without padding (border)
image_create(output, (input->w + 1 - 2 * border_size) / 2, (input->h + 1 - 2 * border_size) / 2, input->type);
uint8_t *input_buf = (uint8_t *)input->buf;
uint8_t *output_buf = (uint8_t *)output->buf;
uint8_t *input_buf = (uint8_t *)input->buf;
uint8_t *output_buf = (uint8_t *)output->buf;
uint16_t row, col; // coordinates of the central pixel; pixel being calculated in input matrix; center of filer matrix
uint16_t w = input->w;
int32_t sum = 0;
uint16_t row, col; // coordinates of the central pixel; pixel being calculated in input matrix; center of filer matrix
uint16_t w = input->w;
int32_t sum = 0;
for (uint16_t i = 0; i != output->h; i++){
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;
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 = 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)];
output_buf[i*output->w + j] = sum / 10000;
}
}
output_buf[i * output->w + j] = sum / 10000;
}
}
}
@@ -322,21 +332,21 @@ void pyramid_next_level(struct image_t *input, struct image_t *output, uint8_t b
* followed by `pyr_level` of pyramid.
* @param[in] pyr_level - number of pyramids to be built. If 0, original image is padded and outputed.
* @param[in] border_size - amount of padding around image. Padding is made by reflecting image elements at the edge
* Example: f e d c b a | a b c d e f | f e d c b a
* Example: f e d c b a | a b c d e f | f e d c b a
*/
void pyramid_build(struct image_t *input, struct image_t *output_array, uint8_t pyr_level, uint8_t border_size)
{
// Pad input image and save it as '0' pyramid level
image_add_border(input, &output_array[0], border_size);
// Pad input image and save it as '0' pyramid level
image_add_border(input, &output_array[0], border_size);
// Temporary holds 'i' level version of original image to be padded and saved as 'i' pyramid level
struct image_t temp;
// Temporary holds 'i' level version of original image to be padded and saved as 'i' pyramid level
struct image_t temp;
for (uint8_t i = 1; i != pyr_level + 1; i++){
pyramid_next_level(&output_array[i-1], &temp, border_size);
image_add_border(&temp, &output_array[i], border_size);
image_free(&temp);
}
for (uint8_t i = 1; i != pyr_level + 1; i++) {
pyramid_next_level(&output_array[i - 1], &temp, border_size);
image_add_border(&temp, &output_array[i], border_size);
image_free(&temp);
}
}
/**
@@ -348,9 +358,10 @@ void pyramid_build(struct image_t *input, struct image_t *output_array, uint8_t
* @param[in] *center Center point in subpixel coordinates
* @param[in] subpixel_factor The subpixel factor per pixel
* @param[in] border_size - amount of padding around image. Padding is made by reflecting image elements at the edge
* Example: f e d c b a | a b c d e f | f e d c b a
* Example: f e d c b a | a b c d e f | f e d c b a
*/
void image_subpixel_window(struct image_t *input, struct image_t *output, struct point_t *center, uint32_t subpixel_factor, uint8_t border_size)
void image_subpixel_window(struct image_t *input, struct image_t *output, struct point_t *center,
uint32_t subpixel_factor, uint8_t border_size)
{
uint8_t *input_buf = (uint8_t *)input->buf;
uint8_t *output_buf = (uint8_t *)output->buf;
@@ -418,7 +429,8 @@ void image_gradients(struct image_t *input, struct image_t *dx, struct image_t *
for (uint16_t x = 1; x < input->w - 1; x++) {
for (uint16_t y = 1; y < input->h - 1; y++) {
dx_buf[(y - 1)*dx->w + (x - 1)] = (int16_t)input_buf[y * input->w + x + 1] - (int16_t)input_buf[y * input->w + x - 1];
dy_buf[(y - 1)*dy->w + (x - 1)] = (int16_t)input_buf[(y + 1) * input->w + x] - (int16_t)input_buf[(y - 1) * input->w + x];
dy_buf[(y - 1)*dy->w + (x - 1)] = (int16_t)input_buf[(y + 1) * input->w + x] - (int16_t)
input_buf[(y - 1) * input->w + x];
}
}
}
@@ -617,7 +629,8 @@ void image_draw_line(struct image_t *img, struct point_t *from, struct point_t *
else { distance = delta_y * 20; }
/* draw the line */
for (uint16_t t = 0; /* starty >= 0 && */ starty < img->h && /* startx >= 0 && */ startx < img->w && t <= distance + 1; t++) {
for (uint16_t t = 0; /* starty >= 0 && */ starty < img->h && /* startx >= 0 && */ startx < img->w
&& t <= distance + 1; t++) {
img_buf[img->w * pixel_width * starty + startx * pixel_width] = (t <= 3) ? 0 : 255;
if (img->type == IMAGE_YUV422) {
@@ -70,9 +70,11 @@ void image_free(struct image_t *img);
void image_copy(struct image_t *input, struct image_t *output);
void image_switch(struct image_t *a, struct image_t *b);
void image_to_grayscale(struct image_t *input, struct image_t *output);
uint16_t image_yuv422_colorfilt(struct image_t *input, struct image_t *output, uint8_t y_m, uint8_t y_M, uint8_t u_m, uint8_t u_M, uint8_t v_m, uint8_t v_M);
uint16_t image_yuv422_colorfilt(struct image_t *input, struct image_t *output, uint8_t y_m, uint8_t y_M, uint8_t u_m,
uint8_t u_M, uint8_t v_m, uint8_t v_M);
void image_yuv422_downsample(struct image_t *input, struct image_t *output, uint16_t downsample);
void image_subpixel_window(struct image_t *input, struct image_t *output, struct point_t *center, uint32_t subpixel_factor, uint8_t border_size);
void image_subpixel_window(struct image_t *input, struct image_t *output, struct point_t *center,
uint32_t subpixel_factor, uint8_t border_size);
void image_gradients(struct image_t *input, struct image_t *dx, struct image_t *dy);
void image_calculate_g(struct image_t *dx, struct image_t *dy, int32_t *g);
uint32_t image_difference(struct image_t *img_a, struct image_t *img_b, struct image_t *diff);
@@ -60,177 +60,176 @@
* @param[in] pyramid_level Level of pyramid used in computation (0 == no pyramids used)
* @return The vectors from the original *points in subpixels
*/
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_lvl) {
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_lvl)
{
// Pyramidal implementation of Lucas-Kanade feature tracker.
// Uses input images to build pyramid of padded images.
// For every pyramid level:
// For all points:
// (1) determine the subpixel neighborhood in the old image
// (2) get the x- and y- gradients
// (3) determine the 'G'-matrix [sum(Axx) sum(Axy); sum(Axy) sum(Ayy)], where sum is over the window
// (4) iterate over taking steps in the image to minimize the error:
// [a] get the subpixel neighborhood in the new image
// [b] determine the image difference between the two neighborhoods
// [c] calculate the 'b'-vector
// [d] calculate the additional flow step and possibly terminate the iteration
// (5) use calculated flow as initial flow estimation for next level of pyramid
// Pyramidal implementation of Lucas-Kanade feature tracker.
// Uses input images to build pyramid of padded images.
// For every pyramid level:
// For all points:
// (1) determine the subpixel neighborhood in the old image
// (2) get the x- and y- gradients
// (3) determine the 'G'-matrix [sum(Axx) sum(Axy); sum(Axy) sum(Ayy)], where sum is over the window
// (4) iterate over taking steps in the image to minimize the error:
// [a] get the subpixel neighborhood in the new image
// [b] determine the image difference between the two neighborhoods
// [c] calculate the 'b'-vector
// [d] calculate the additional flow step and possibly terminate the iteration
// (5) use calculated flow as initial flow estimation for next level of pyramid
// Allocate some memory for returning the vectors
struct flow_t *vectors = malloc(sizeof(struct flow_t) * max_points);
// Allocate some memory for returning the vectors
struct flow_t *vectors = malloc(sizeof(struct flow_t) * max_points);
// Determine patch sizes and initialize neighborhoods
uint16_t patch_size = 2 * half_window_size + 1;
uint32_t error_threshold = (25 * 25) * (patch_size * patch_size);
uint16_t padded_patch_size = patch_size + 2;
uint8_t border_size = padded_patch_size / 2 + 2; // amount of padding added to images
step_threshold = step_threshold*(subpixel_factor/100);
// Determine patch sizes and initialize neighborhoods
uint16_t patch_size = 2 * half_window_size + 1;
uint32_t error_threshold = (25 * 25) * (patch_size * patch_size);
uint16_t padded_patch_size = patch_size + 2;
uint8_t border_size = padded_patch_size / 2 + 2; // amount of padding added to images
step_threshold = step_threshold * (subpixel_factor / 100);
// Allocate memory for image pyramids
struct image_t *pyramid_old = malloc(sizeof(struct image_t) * (pyramid_lvl + 1));
struct image_t *pyramid_new = malloc(sizeof(struct image_t) * (pyramid_lvl + 1));
// Allocate memory for image pyramids
struct image_t *pyramid_old = malloc(sizeof(struct image_t) * (pyramid_lvl + 1));
struct image_t *pyramid_new = malloc(sizeof(struct image_t) * (pyramid_lvl + 1));
// Build pyramid levels
pyramid_build(old_img, pyramid_old, pyramid_lvl, border_size);
pyramid_build(new_img, pyramid_new, pyramid_lvl, border_size);
// Build pyramid levels
pyramid_build(old_img, pyramid_old, pyramid_lvl, border_size);
pyramid_build(new_img, pyramid_new, pyramid_lvl, border_size);
// Create the window images
struct image_t window_I, window_J, window_DX, window_DY, window_diff;
image_create(&window_I, padded_patch_size, padded_patch_size, IMAGE_GRAYSCALE);
image_create(&window_J, patch_size, patch_size, IMAGE_GRAYSCALE);
image_create(&window_DX, patch_size, patch_size, IMAGE_GRADIENT);
image_create(&window_DY, patch_size, patch_size, IMAGE_GRADIENT);
image_create(&window_diff, patch_size, patch_size, IMAGE_GRADIENT);
// Create the window images
struct image_t window_I, window_J, window_DX, window_DY, window_diff;
image_create(&window_I, padded_patch_size, padded_patch_size, IMAGE_GRAYSCALE);
image_create(&window_J, patch_size, patch_size, IMAGE_GRAYSCALE);
image_create(&window_DX, patch_size, patch_size, IMAGE_GRADIENT);
image_create(&window_DY, patch_size, patch_size, IMAGE_GRADIENT);
image_create(&window_diff, patch_size, patch_size, IMAGE_GRADIENT);
// Iterate through pyramid levels
for (int8_t LVL = pyramid_lvl; LVL != -1; LVL--) {
uint16_t points_orig = *points_cnt;
*points_cnt = 0;
uint16_t new_p = 0;
// Iterate through pyramid levels
for (int8_t LVL = pyramid_lvl; LVL != -1; LVL--) {
uint16_t points_orig = *points_cnt;
*points_cnt = 0;
uint16_t new_p = 0;
// Calculate the amount of points to skip
float skip_points = (points_orig > max_points) ? (float)points_orig / max_points : 1;
// Calculate the amount of points to skip
float skip_points = (points_orig > max_points) ? (float)points_orig / max_points : 1;
// Go through all points
for (uint16_t i = 0; i < max_points && i < points_orig; i++)
{
uint16_t p = i * skip_points;
// Go through all points
for (uint16_t i = 0; i < max_points && i < points_orig; i++) {
uint16_t p = i * skip_points;
if (LVL == pyramid_lvl)
{
// Convert point position on original image to a subpixel coordinate on the top pyramid level
vectors[new_p].pos.x = (points[p].x * subpixel_factor) >> pyramid_lvl;
vectors[new_p].pos.y = (points[p].y * subpixel_factor) >> pyramid_lvl;
vectors[new_p].flow_x = 0;
vectors[new_p].flow_y = 0;
if (LVL == pyramid_lvl) {
// Convert point position on original image to a subpixel coordinate on the top pyramid level
vectors[new_p].pos.x = (points[p].x * subpixel_factor) >> pyramid_lvl;
vectors[new_p].pos.y = (points[p].y * subpixel_factor) >> pyramid_lvl;
vectors[new_p].flow_x = 0;
vectors[new_p].flow_y = 0;
} else {
// (5) use calculated flow as initial flow estimation for next level of pyramid
vectors[new_p].pos.x = vectors[p].pos.x << 1;
vectors[new_p].pos.y = vectors[p].pos.y << 1;
vectors[new_p].flow_x = vectors[p].flow_x << 1;
vectors[new_p].flow_y = vectors[p].flow_y << 1;
}
} else {
// (5) use calculated flow as initial flow estimation for next level of pyramid
vectors[new_p].pos.x = vectors[p].pos.x << 1;
vectors[new_p].pos.y = vectors[p].pos.y << 1;
vectors[new_p].flow_x = vectors[p].flow_x << 1;
vectors[new_p].flow_y = vectors[p].flow_y << 1;
}
// If the pixel is outside original image, do not track it
if ((((int32_t) vectors[new_p].pos.x + vectors[new_p].flow_x) < 0)
|| ((vectors[new_p].pos.x + vectors[new_p].flow_x) > ((pyramid_new[LVL].w - 1 - 2 * border_size)* subpixel_factor))
|| (((int32_t) vectors[new_p].pos.y + vectors[new_p].flow_y) < 0)
|| ((vectors[new_p].pos.y + vectors[new_p].flow_y) > ((pyramid_new[LVL].h - 1 - 2 * border_size)* subpixel_factor)))
{
continue;
}
// If the pixel is outside original image, do not track it
if ((((int32_t) vectors[new_p].pos.x + vectors[new_p].flow_x) < 0)
|| ((vectors[new_p].pos.x + vectors[new_p].flow_x) > ((pyramid_new[LVL].w - 1 - 2 * border_size)* subpixel_factor))
|| (((int32_t) vectors[new_p].pos.y + vectors[new_p].flow_y) < 0)
|| ((vectors[new_p].pos.y + vectors[new_p].flow_y) > ((pyramid_new[LVL].h - 1 - 2 * border_size)* subpixel_factor))) {
continue;
}
// (1) determine the subpixel neighborhood in the old image
image_subpixel_window(&pyramid_old[LVL], &window_I, &vectors[new_p].pos, subpixel_factor, border_size);
// (1) determine the subpixel neighborhood in the old image
image_subpixel_window(&pyramid_old[LVL], &window_I, &vectors[new_p].pos, subpixel_factor, border_size);
// (2) get the x- and y- gradients
image_gradients(&window_I, &window_DX, &window_DY);
// (2) get the x- and y- gradients
image_gradients(&window_I, &window_DX, &window_DY);
// (3) determine the 'G'-matrix [sum(Axx) sum(Axy); sum(Axy) sum(Ayy)], where sum is over the window
int32_t G[4];
image_calculate_g(&window_DX, &window_DY, G);
// (3) determine the 'G'-matrix [sum(Axx) sum(Axy); sum(Axy) sum(Ayy)], where sum is over the window
int32_t G[4];
image_calculate_g(&window_DX, &window_DY, G);
// calculate G's determinant in subpixel units:
int32_t Det = ( G[0] * G[3] - G[1] * G[2]);
// calculate G's determinant in subpixel units:
int32_t Det = (G[0] * G[3] - G[1] * G[2]);
// Check if the determinant is bigger than 1
if (Det < 1) {
continue;
}
// Check if the determinant is bigger than 1
if (Det < 1) {
continue;
}
// (4) iterate over taking steps in the image to minimize the error:
bool_t tracked = TRUE;
// (4) iterate over taking steps in the image to minimize the error:
bool_t tracked = TRUE;
for (uint8_t it = max_iterations; it--; ) {
struct point_t new_point = { vectors[new_p].pos.x + vectors[new_p].flow_x,
vectors[new_p].pos.y + vectors[new_p].flow_y };
for (uint8_t it = max_iterations; it--;) {
struct point_t new_point = { vectors[new_p].pos.x + vectors[new_p].flow_x,
vectors[new_p].pos.y + vectors[new_p].flow_y
};
// If the pixel is outside original image, do not track it
if ( (( (int32_t)vectors[new_p].pos.x + vectors[new_p].flow_x) < 0)
|| ( new_point.x > ((pyramid_new[LVL].w - 1 - 2*border_size)*subpixel_factor))
|| (((int32_t)vectors[new_p].pos.y + vectors[new_p].flow_y) < 0)
|| ( new_point.y > ((pyramid_new[LVL].h - 1 - 2*border_size)*subpixel_factor)) )
{
tracked = FALSE;
break;
}
// If the pixel is outside original image, do not track it
if ((((int32_t)vectors[new_p].pos.x + vectors[new_p].flow_x) < 0)
|| (new_point.x > ((pyramid_new[LVL].w - 1 - 2 * border_size)*subpixel_factor))
|| (((int32_t)vectors[new_p].pos.y + vectors[new_p].flow_y) < 0)
|| (new_point.y > ((pyramid_new[LVL].h - 1 - 2 * border_size)*subpixel_factor))) {
tracked = FALSE;
break;
}
// [a] get the subpixel neighborhood in the new image
image_subpixel_window(&pyramid_new[LVL], &window_J, &new_point, subpixel_factor, border_size);
// [a] get the subpixel neighborhood in the new image
image_subpixel_window(&pyramid_new[LVL], &window_J, &new_point, subpixel_factor, border_size);
// [b] determine the image difference between the two neighborhoods
uint32_t error = image_difference(&window_I, &window_J, &window_diff);
// [b] determine the image difference between the two neighborhoods
uint32_t error = image_difference(&window_I, &window_J, &window_diff);
if (error > error_threshold && it < max_iterations / 2) {
tracked = FALSE;
break;
}
if (error > error_threshold && it < max_iterations / 2) {
tracked = FALSE;
break;
}
int32_t b_x = image_multiply(&window_diff, &window_DX, NULL) / 255;
int32_t b_y = image_multiply(&window_diff, &window_DY, NULL) / 255;
int32_t b_x = image_multiply(&window_diff, &window_DX, NULL) / 255;
int32_t b_y = image_multiply(&window_diff, &window_DY, NULL) / 255;
// [d] calculate the additional flow step and possibly terminate the iteration
int16_t step_x = (( (int64_t) G[3] * b_x - G[1] * b_y) * subpixel_factor) / Det;
int16_t step_y = (( (int64_t) G[0] * b_y - G[2] * b_x) * subpixel_factor) / Det;
// [d] calculate the additional flow step and possibly terminate the iteration
int16_t step_x = (((int64_t) G[3] * b_x - G[1] * b_y) * subpixel_factor) / Det;
int16_t step_y = (((int64_t) G[0] * b_y - G[2] * b_x) * subpixel_factor) / Det;
vectors[new_p].flow_x = vectors[new_p].flow_x + step_x;
vectors[new_p].flow_y = vectors[new_p].flow_y + step_y;
vectors[new_p].flow_x = vectors[new_p].flow_x + step_x;
vectors[new_p].flow_y = vectors[new_p].flow_y + step_y;
// Check if we exceeded the treshold CHANGED made this better for 0.03
if ((abs(step_x) + abs(step_y)) < step_threshold) {
break;
}
} // lucas kanade step iteration
// Check if we exceeded the treshold CHANGED made this better for 0.03
if ((abs(step_x) + abs(step_y)) < step_threshold) {
break;
}
} // lucas kanade step iteration
// If we tracked the point we update the index and the count
if (tracked) {
new_p++;
(*points_cnt)++;
}
} // go through all points
// If we tracked the point we update the index and the count
if (tracked) {
new_p++;
(*points_cnt)++;
}
} // go through all points
} // LVL of pyramid
} // LVL of pyramid
// Free the images
image_free(&window_I);
image_free(&window_J);
image_free(&window_DX);
image_free(&window_DY);
image_free(&window_diff);
// Free the images
image_free(&window_I);
image_free(&window_J);
image_free(&window_DX);
image_free(&window_DY);
image_free(&window_diff);
for (int8_t i = pyramid_lvl; i!= -1; i--){
image_free(&pyramid_old[i]);
image_free(&pyramid_new[i]);
}
pyramid_old = NULL;
pyramid_new = NULL;
for (int8_t i = pyramid_lvl; i != -1; i--) {
image_free(&pyramid_old[i]);
image_free(&pyramid_new[i]);
}
pyramid_old = NULL;
pyramid_new = NULL;
// Return the vectors
return vectors;
// Return the vectors
return vectors;
}
@@ -34,7 +34,8 @@
#include "std.h"
#include "image.h"
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_lvl);
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_lvl);
#endif /* OPTIC_FLOW_INT_H */
@@ -51,7 +51,7 @@ struct opticflow_t {
uint16_t subpixel_factor; ///< The amount of subpixels per pixel
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_lvl; ///< Number of pyramid levels used in Lucas Kanade algorithm (0 == no pyramids used)
uint8_t pyramid_lvl; ///< Number of pyramid levels used in Lucas Kanade algorithm (0 == no pyramids used)
uint8_t max_track_corners; ///< Maximum amount of corners Lucas Kanade should track
bool_t fast9_adaptive; ///< Whether the FAST9 threshold should be adaptive
@@ -62,7 +62,8 @@ struct opticflow_t {
void opticflow_calc_init(struct opticflow_t *opticflow, uint16_t w, uint16_t h);
void opticflow_calc_frame(struct opticflow_t *opticflow, struct opticflow_state_t *state, struct image_t *img, struct opticflow_result_t *result);
void opticflow_calc_frame(struct opticflow_t *opticflow, struct opticflow_state_t *state, struct image_t *img,
struct opticflow_result_t *result);
void calc_fast9_lukas_kanade(struct opticflow_t *opticflow, struct opticflow_state_t *state, struct image_t *img,
struct opticflow_result_t *result);