79 if (pyramid_level == 0) {
81 return opticFlowLK_flat(new_img, old_img, points, points_cnt, half_window_size, subpixel_factor, max_iterations, step_threshold, max_points);
85 struct flow_t *vectors = malloc(
sizeof(
struct flow_t) * max_points);
90 uint32_t error_threshold = (25 * 25) * (patch_size * patch_size);
91 uint16_t padded_patch_size = patch_size + 2;
92 uint8_t border_size = padded_patch_size / 2 + 2;
95 struct image_t *pyramid_old = malloc(
sizeof(
struct image_t) * (pyramid_level + 1));
96 struct image_t *pyramid_new = malloc(
sizeof(
struct image_t) * (pyramid_level + 1));
99 pyramid_build(old_img, pyramid_old, pyramid_level, border_size);
100 pyramid_build(new_img, pyramid_new, pyramid_level, border_size);
103 struct image_t window_I, window_J, window_DX, window_DY, window_diff;
111 for (
int8_t LVL = pyramid_level; LVL != -1; LVL--) {
117 float skip_points = (points_orig > max_points) ? (
float)points_orig / max_points : 1;
120 for (
uint16_t i = 0; i < max_points && i < points_orig; i++) {
123 if (LVL == pyramid_level) {
125 vectors[new_p].
pos.
x = (points[
p].
x * subpixel_factor) >> pyramid_level;
126 vectors[new_p].
pos.
y = (points[
p].
y * subpixel_factor) >> pyramid_level;
127 vectors[new_p].
flow_x = 0;
128 vectors[new_p].
flow_y = 0;
132 vectors[new_p].
pos.
x = vectors[
p].
pos.
x << 1;
133 vectors[new_p].
pos.
y = vectors[
p].
pos.
y << 1;
140 || ((vectors[new_p].
pos.
x + vectors[new_p].
flow_x) > ((pyramid_new[LVL].
w - 1 - 2 * border_size)* subpixel_factor))
141 || (((
int32_t) vectors[new_p].pos.y + vectors[new_p].
flow_y) < 0)
142 || ((vectors[new_p].pos.y + vectors[new_p].
flow_y) > ((pyramid_new[LVL].
h - 1 - 2 * border_size)* subpixel_factor))) {
148 image_subpixel_window(&pyramid_old[LVL], &window_I, &vectors[new_p].pos, subpixel_factor, border_size);
158 int32_t Det = (G[0] * G[3] - G[1] * G[2]);
168 for (
uint8_t it = max_iterations; it--;) {
175 if ((((
int32_t)vectors[new_p].pos.x + vectors[new_p].
flow_x) < 0)
176 || (new_point.
x > ((pyramid_new[LVL].
w - 1 - 2 * border_size)*subpixel_factor))
178 || (new_point.
y > ((pyramid_new[LVL].
h - 1 - 2 * border_size)*subpixel_factor))) {
189 if (error > error_threshold && it < max_iterations / 2) {
199 int16_t step_x = (((
int64_t) G[3] * b_x - G[1] * b_y) * subpixel_factor) / Det;
200 int16_t step_y = (((
int64_t) G[0] * b_y - G[2] * b_x) * subpixel_factor) / Det;
206 if ((abs(step_x) + abs(step_y)) < step_threshold) {
227 for (
int8_t i = pyramid_level; i != -1; i--) {
268 struct flow_t *vectors = malloc(
sizeof(
struct flow_t) * max_points);
275 uint32_t error_threshold = (25 * 25) * (patch_size * patch_size);
276 uint16_t padded_patch_size = patch_size + 2;
279 struct image_t window_I, window_J, window_DX, window_DY, window_diff;
287 float skip_points = (points_orig > max_points) ? points_orig / max_points : 1;
290 for (
uint16_t i = 0; i < max_points && i < points_orig; i++) {
294 if (points[p].x < half_window_size || (old_img->
w - points[p].
x) < half_window_size
295 || points[
p].
y < half_window_size || (old_img->
h - points[
p].
y) < half_window_size) {
300 vectors[new_p].
pos.
x = points[
p].
x * subpixel_factor;
301 vectors[new_p].
pos.
y = points[
p].
y * subpixel_factor;
302 vectors[new_p].
flow_x = 0;
303 vectors[new_p].
flow_y = 0;
316 int32_t Det = (G[0] * G[3] - G[1] * G[2]) / subpixel_factor;
329 for (
uint8_t it = 0; it < max_iterations; it++) {
335 if (new_point.
x / subpixel_factor < half_window_size || (old_img->
w - new_point.
x / subpixel_factor) <= half_window_size
336 || new_point.
y / subpixel_factor < half_window_size || (old_img->
h - new_point.
y / subpixel_factor) <= half_window_size
337 || new_point.
x / subpixel_factor > old_img->
w || new_point.
y / subpixel_factor > old_img->
h) {
348 if (error > error_threshold && it > max_iterations / 2) {
357 int16_t step_x = (G[3] * b_x - G[1] * b_y) / Det;
358 int16_t step_y = (G[0] * b_y - G[2] * b_x) / Det;
359 vectors[new_p].
flow_x += step_x;
360 vectors[new_p].
flow_y += step_y;
363 if ((abs(step_x) + abs(step_y)) < step_threshold) {
void image_gradients(struct image_t *input, struct image_t *dx, struct image_t *dy)
Calculate the gradients using the following matrix: [0 -1 0; -1 0 1; 0 1 0].
void pyramid_build(struct image_t *input, struct image_t *output_array, uint8_t pyr_level, uint8_t border_size)
This function populates given array of image_t structs with wanted number of padded pyramids based on...
uint32_t image_difference(struct image_t *img_a, struct image_t *img_b, struct image_t *diff)
Calculate the difference between two images and return the error This will only work with grayscale i...
void image_free(struct image_t *img)
Free the image.
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)
void image_create(struct image_t *img, uint16_t width, uint16_t height, enum image_type type)
Create a new image.
uint32_t x
The x coordinate of the point.
int16_t flow_x
The x direction flow in subpixels.
struct point_t pos
The original position the flow comes from.
uint32_t y
The y coordinate of the point.
struct flow_t * opticFlowLK_flat(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, uint16_t max_points)
Compute the optical flow of several points using the Lucas-Kanade algorithm by Yves Bouguet The initi...
efficient fixed-point optical-flow calculation
Grayscale image with only the Y part (uint8 per pixel)
void image_calculate_g(struct image_t *dx, struct image_t *dy, int32_t *g)
Calculate the G vector of an image gradient This is used for optical flow calculation.
An image gradient (int16 per pixel)
int16_t flow_y
The y direction flow in subpixels.
int32_t image_multiply(struct image_t *img_a, struct image_t *img_b, struct image_t *mult)
Calculate the multiplication between two images and return the error This will only work with image g...
void image_subpixel_window(struct image_t *input, struct image_t *output, struct point_t *center, uint32_t subpixel_factor, uint8_t border_size)
This outputs a subpixel window image in grayscale Currently only works with Grayscale images as input...