65 if (img->
buf != NULL) {
86 output->
ts = input->
ts;
101 memcpy(&old_a, a,
sizeof(
struct image_t));
104 memcpy(a, b,
sizeof(
struct image_t));
107 memcpy(b, &old_a,
sizeof(
struct image_t));
123 output->
ts = input->
ts;
126 for (
int y = 0; y < output->
h; y++) {
127 for (
int x = 0; x < output->
w; x++) {
157 output->
ts = input->
ts;
160 for (
uint16_t y = 0; y < output->
h; y++) {
161 for (
uint16_t x = 0; x < output->
w; x += 2) {
179 char u = source[0] - 127;
217 uint16_t pixelskip = (downsample - 1) * 2;
220 output->
ts = input->
ts;
223 for (
uint16_t y = 0; y < output->
h; y++) {
224 for (
uint16_t x = 0; x < output->
w; x += 2) {
234 source += (downsample - 1) * input->
w * 2;
248 image_create(output, input->
w + 2 * border_size, input->
h + 2 * border_size, input->
type);
254 for (
uint16_t i = border_size; i != (output->
h - border_size); i++) {
257 for (
uint8_t j = 0; j != border_size; j++) {
258 output_buf[i * output->
w + (border_size - 1 - j)] = input_buf[(i - border_size) * input->
w + j];
262 memcpy(&output_buf[i * output->
w + border_size], &input_buf[(i - border_size) * input->
w],
sizeof(
uint8_t) * input->
w);
265 for (
uint8_t j = 0; j != border_size; j++) {
266 output_buf[i * output->
w + output->
w - border_size + j] = output_buf[i * output->
w + output->
w - border_size - 1 - j];
271 for (
uint8_t i = 0; i != border_size; i++) {
272 memcpy(&output_buf[(border_size - 1) * output->
w - i * output->
w], &output_buf[border_size * output->
w + i * output->
w],
274 memcpy(&output_buf[(output->
h - border_size) * output->
w + i * output->
w],
275 &output_buf[(output->
h - border_size - 1) * output->
w - i * output->
w],
sizeof(
uint8_t) * output->
w);
293 image_create(output, (input->
w + 1 - 2 * border_size) / 2, (input->
h + 1 - 2 * border_size) / 2, input->
type);
302 for (
uint16_t i = 0; i != output->
h; i++) {
304 for (
uint16_t j = 0; j != output->
w; j++) {
305 row = border_size + 2 * i;
306 col = border_size + 2 * j;
308 sum = 39 * (input_buf[(row - 2) * w + (col - 2)] + input_buf[(row - 2) * w + (col + 2)] +
309 input_buf[(row + 2) * w + (col - 2)] + input_buf[(row + 2) * w + (col + 2)]);
310 sum += 156 * (input_buf[(row - 2) * w + (col - 1)] + input_buf[(row - 2) * w + (col + 1)] +
311 input_buf[(row - 1) * w + (col + 2)] + input_buf[(row + 1) * w + (col - 2)]
312 + input_buf[(row + 1) * w + (col + 2)] + input_buf[(row + 2) * w + (col - 1)] + input_buf[(row + 2) * w + (col + 1)] +
313 input_buf[(row - 1) * w + (col - 2)]);
314 sum += 234 * (input_buf[(row - 2) * w + (col)] + input_buf[(row) * w + (col - 2)] +
315 input_buf[(row) * w + (col + 2)] + input_buf[(row + 2) * w + (col)]);
316 sum += 625 * (input_buf[(row - 1) * w + (col - 1)] + input_buf[(row - 1) * w + (col + 1)] +
317 input_buf[(row + 1) * w + (col - 1)] + input_buf[(row + 1) * w + (col + 1)]);
318 sum += 938 * (input_buf[(row - 1) * w + (col)] + input_buf[(row) * w + (col - 1)] +
319 input_buf[(row) * w + (col + 1)] + input_buf[(row + 1) * w + (col)]);
320 sum += 1406 * input_buf[(row) * w + (col)];
322 output_buf[i * output->
w + j] = sum / 10000;
345 for (
uint8_t i = 1; i != pyr_level + 1; i++) {
373 uint32_t subpixel_w = (input->
w -2) * subpixel_factor;
374 uint32_t subpixel_h = (input->
h -2) * subpixel_factor;
377 for (
uint16_t i = 0; i < output->
w; i++) {
378 for (
uint16_t j = 0; j < output->
h; j++) {
380 uint32_t x = center->
x + border_size * subpixel_factor + (i - half_window) * subpixel_factor;
381 uint32_t y = center->
y + border_size * subpixel_factor + (j - half_window) * subpixel_factor;
383 BoundUpper(x, subpixel_w);
384 BoundUpper(y, subpixel_h);
387 uint16_t orig_x = x / subpixel_factor;
388 uint16_t orig_y = y / subpixel_factor;
391 uint32_t tl_x = orig_x * subpixel_factor;
392 uint32_t tl_y = orig_y * subpixel_factor;
395 if (tl_x == x && tl_y == y) {
396 output_buf[output->
w * j + i] = input_buf[input->
w * orig_y + orig_x];
403 uint32_t blend = (subpixel_factor - alpha_x) * (subpixel_factor - alpha_y) * input_buf[input->
w * orig_y + orig_x];
404 blend += alpha_x * (subpixel_factor - alpha_y) * input_buf[input->
w * orig_y + (orig_x + 1)];
405 blend += (subpixel_factor - alpha_x) * alpha_y * input_buf[input->
w * (orig_y + 1) + orig_x];
406 blend += alpha_x * alpha_y * input_buf[input->
w * (orig_y + 1) + (orig_x + 1)];
409 output_buf[output->
w * j + i] = blend / (subpixel_factor * subpixel_factor);
430 for (
uint16_t x = 1; x < input->
w - 1; x++) {
431 for (
uint16_t y = 1; y < input->
h - 1; y++) {
432 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];
433 dy_buf[(y - 1)*dy->
w + (x - 1)] = (
int16_t)input_buf[(y + 1) * input->
w + x] - (
int16_t)
434 input_buf[(y - 1) * input->
w + x];
448 int32_t sum_dxx = 0, sum_dxy = 0, sum_dyy = 0;
457 sum_dxx += ((
int32_t)dx_buf[y * dx->
w + x] * dx_buf[y * dx->
w + x]);
458 sum_dxy += ((
int32_t)dx_buf[y * dx->
w + x] * dy_buf[y * dy->
w + x]);
459 sum_dyy += ((
int32_t)dy_buf[y * dy->
w + x] * dy_buf[y * dy->
w + x]);
464 g[0] = sum_dxx / 255;
465 g[1] = sum_dxy / 255;
467 g[3] = sum_dyy / 255;
493 for (
uint16_t x = 0; x < img_b->
w; x++) {
494 for (
uint16_t y = 0; y < img_b->
h; y++) {
495 int16_t diff_c = img_a_buf[(y + 1) * img_a->
w + (x + 1)] - img_b_buf[y * img_b->
w + x];
496 sum_diff2 += diff_c * diff_c;
499 if (diff_buf != NULL) {
500 diff_buf[y * diff->
w + x] = diff_c;
529 for (
uint16_t x = 0; x < img_a->
w; x++) {
530 for (
uint16_t y = 0; y < img_a->
h; y++) {
531 int32_t mult_c = img_a_buf[y * img_a->
w + x] * img_b_buf[y * img_b->
w + x];
535 if (mult_buf != NULL) {
536 mult_buf[y * mult->
w + x] = mult_c;
558 for (
int i = 0; i < points_cnt; i++) {
559 uint32_t idx = pixel_width * points[i].
y * img->
w + points[i].
x * pixel_width;
580 for (
uint16_t i = 0; i < points_cnt; i++) {
583 vectors[i].
pos.
x / subpixel_factor,
584 vectors[i].
pos.
y / subpixel_factor
587 (vectors[i].
pos.
x + vectors[i].
flow_x) / subpixel_factor,
588 (vectors[i].pos.y + vectors[i].
flow_y) / subpixel_factor
601 static uint8_t color[4] = {255, 255, 255, 255};
615 int xerr = 0, yerr = 0;
630 if (delta_x > 0) { incx = 1; }
631 else if (delta_x == 0) { incx = 0; }
634 if (delta_y > 0) { incy = 1; }
635 else if (delta_y == 0) { incy = 0; }
640 delta_x = abs(delta_x);
641 delta_y = abs(delta_y);
642 if (delta_x > delta_y) { distance = delta_x * 20; }
643 else { distance = delta_y * 20; }
646 for (
uint16_t t = 0; starty < img->
h && startx < img->
w
647 && t <= distance + 1; t++) {
648 uint32_t buf_loc = img->
w * pixel_width * starty + startx * pixel_width;
649 img_buf[buf_loc] = (t <= 3) ? 0 : color[0];
652 img_buf[buf_loc + 1] = color[1];
654 if (startx + 1 < img->
w) {
655 img_buf[buf_loc + 2] = (t <= 3) ? 0 : color[2];
656 img_buf[buf_loc + 3] = color[3];
662 if (xerr > distance) {
666 if (yerr > distance) {
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].
uint32_t buf_size
The buffer size.
void image_yuv422_downsample(struct image_t *input, struct image_t *output, uint16_t downsample)
Simplified high-speed low CPU downsample function without averaging downsample factor must be 1...
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_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...
void image_free(struct image_t *img)
Free the image.
void image_create(struct image_t *img, uint16_t width, uint16_t height, enum image_type type)
Create a new image.
void image_draw_line(struct image_t *img, struct point_t *from, struct point_t *to)
Draw a pink line on the image.
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.
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.
uint32_t x
The x coordinate of the point.
void image_show_flow(struct image_t *img, struct flow_t *vectors, uint16_t points_cnt, uint8_t subpixel_factor)
Shows the flow from a specific point to a new point This works on YUV422 and Grayscale images...
void pyramid_next_level(struct image_t *input, struct image_t *output, uint8_t border_size)
This function takes previous padded pyramid level and outputs next level of pyramid without padding...
Image helper functions like resizing, color filter, converters...
int16_t flow_x
The x direction flow in subpixels.
void image_add_border(struct image_t *input, struct image_t *output, uint8_t border_size)
This function adds padding to input image by mirroring the edge image elements.
void * buf
Image buffer (depending on the image_type)
struct point_t pos
The original position the flow comes from.
uint32_t y
The y coordinate of the point.
void image_to_grayscale(struct image_t *input, struct image_t *output)
Convert an image to grayscale.
void image_draw_line_color(struct image_t *img, struct point_t *from, struct point_t *to, uint8_t *color)
Draw a line on the image.
struct timeval ts
The timestamp of creation.
UYVY format (uint16 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)
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)
Filter colors in an YUV422 image.
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...
An JPEG encoded image (not per pixel encoded)
enum image_type type
The image type.