From 432b39bc1711915971b31ee8e6517037fe11d1b8 Mon Sep 17 00:00:00 2001 From: "Kwabena W. Agyeman" Date: Wed, 17 Jan 2018 02:13:55 -0500 Subject: [PATCH] Add min()/max() for frame differencing. These have cool ghost image like affects and are useful for frame differencing. --- src/omv/img/imlib.c | 52 ++++++++++++++++++++++++++++++++++++++++ src/omv/img/imlib.h | 2 ++ src/omv/py/py_image.c | 42 ++++++++++++++++++++++++++++++++ src/omv/py/qstrdefsomv.h | 6 +++++ 4 files changed, 102 insertions(+) diff --git a/src/omv/img/imlib.c b/src/omv/img/imlib.c index 8458ab933..27d6a8b30 100644 --- a/src/omv/img/imlib.c +++ b/src/omv/img/imlib.c @@ -1022,6 +1022,58 @@ void imlib_blend(image_t *img, const char *path, image_t *other, int alpha) imlib_image_operation(img, path, other, imlib_blend_line_op, (void *) __PKHBT((256-alpha), alpha, 16)); } +static void imlib_max_line_op(image_t *img, int line, uint8_t *other, void *data) +{ + data = data; + + if (IM_IS_GS(img)) { + uint8_t *pixels = img->pixels + (img->w * line); + for (int i=0; iw; i++) { + pixels[i] = IM_MAX(pixels[i], other[i]); + } + } else { + uint16_t *pixels = ((uint16_t *) img->pixels) + (img->w * line); + for (int i=0; iw; i++) { + const int pixel = pixels[i], other_pixel = ((uint16_t *) other)[i]; + const int r = IM_MAX(IM_R565(pixel), IM_R565(other_pixel)); + const int g = IM_MAX(IM_G565(pixel), IM_G565(other_pixel)); + const int b = IM_MAX(IM_B565(pixel), IM_B565(other_pixel)); + pixels[i] = IM_RGB565(r, g, b); + } + } +} + +void imlib_max(image_t *img, const char *path, image_t *other) +{ + imlib_image_operation(img, path, other, imlib_max_line_op, NULL); +} + +static void imlib_min_line_op(image_t *img, int line, uint8_t *other, void *data) +{ + data = data; + + if (IM_IS_GS(img)) { + uint8_t *pixels = img->pixels + (img->w * line); + for (int i=0; iw; i++) { + pixels[i] = IM_MIN(pixels[i], other[i]); + } + } else { + uint16_t *pixels = ((uint16_t *) img->pixels) + (img->w * line); + for (int i=0; iw; i++) { + const int pixel = pixels[i], other_pixel = ((uint16_t *) other)[i]; + const int r = IM_MIN(IM_R565(pixel), IM_R565(other_pixel)); + const int g = IM_MIN(IM_G565(pixel), IM_G565(other_pixel)); + const int b = IM_MIN(IM_B565(pixel), IM_B565(other_pixel)); + pixels[i] = IM_RGB565(r, g, b); + } + } +} + +void imlib_min(image_t *img, const char *path, image_t *other) +{ + imlib_image_operation(img, path, other, imlib_min_line_op, NULL); +} + //////////////////////////////////////////////////////////////////////////////// void imlib_chrominvar(image_t *img) diff --git a/src/omv/img/imlib.h b/src/omv/img/imlib.h index bfb982e17..3f357e9c2 100644 --- a/src/omv/img/imlib.h +++ b/src/omv/img/imlib.h @@ -1118,6 +1118,8 @@ void imlib_negate(image_t *img); void imlib_difference(image_t *img, const char *path, image_t *other); void imlib_replace(image_t *img, const char *path, image_t *other); void imlib_blend(image_t *img, const char *path, image_t *other, int alpha); +void imlib_max(image_t *img, const char *path, image_t *other); +void imlib_min(image_t *img, const char *path, image_t *other); /* Image Morphing */ void imlib_morph(image_t *img, const int ksize, const int8_t *krn, const float m, const int b); diff --git a/src/omv/py/py_image.c b/src/omv/py/py_image.c index 239708ccc..f18d8ac77 100644 --- a/src/omv/py/py_image.c +++ b/src/omv/py/py_image.c @@ -1288,6 +1288,44 @@ static mp_obj_t py_image_gaussian(uint n_args, const mp_obj_t *args, mp_map_t *k return args[0]; } +static mp_obj_t py_image_max(mp_obj_t img_obj, mp_obj_t other_obj) +{ + image_t *arg_img = py_image_cobj(img_obj); + PY_ASSERT_TRUE_MSG(IM_IS_MUTABLE(arg_img), "Image format is not supported."); + + if (MP_OBJ_IS_STR(other_obj)) { + fb_alloc_mark(); + imlib_max(arg_img, mp_obj_str_get_str(other_obj), NULL); + fb_alloc_mark(); + } else { + image_t *arg_other = py_image_cobj(other_obj); + fb_alloc_mark(); + imlib_max(arg_img, NULL, arg_other); + fb_alloc_free_till_mark(); + } + + return img_obj; +} + +static mp_obj_t py_image_min(mp_obj_t img_obj, mp_obj_t other_obj) +{ + image_t *arg_img = py_image_cobj(img_obj); + PY_ASSERT_TRUE_MSG(IM_IS_MUTABLE(arg_img), "Image format is not supported."); + + if (MP_OBJ_IS_STR(other_obj)) { + fb_alloc_mark(); + imlib_min(arg_img, mp_obj_str_get_str(other_obj), NULL); + fb_alloc_mark(); + } else { + image_t *arg_other = py_image_cobj(other_obj); + fb_alloc_mark(); + imlib_min(arg_img, NULL, arg_other); + fb_alloc_free_till_mark(); + } + + return img_obj; +} + static mp_obj_t py_image_linpolar(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { image_t *arg_img = py_image_cobj(args[0]); @@ -4143,6 +4181,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_negate_obj, py_image_negate); STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_difference_obj, py_image_difference); STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_replace_obj, py_image_replace); STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_blend_obj, 2, py_image_blend); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_max_obj, py_image_max); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_min_obj, py_image_min); /* Image Morphing */ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_morph_obj, 3, py_image_morph); /* Image Filtering */ @@ -4257,6 +4297,8 @@ static const mp_map_elem_t locals_dict_table[] = { {MP_OBJ_NEW_QSTR(MP_QSTR_difference), (mp_obj_t)&py_image_difference_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_replace), (mp_obj_t)&py_image_replace_obj}, {MP_OBJ_NEW_QSTR(MP_QSTR_blend), (mp_obj_t)&py_image_blend_obj}, + {MP_OBJ_NEW_QSTR(MP_QSTR_max), (mp_obj_t)&py_image_max_obj}, + {MP_OBJ_NEW_QSTR(MP_QSTR_min), (mp_obj_t)&py_image_min_obj}, /* Image Morphing */ {MP_OBJ_NEW_QSTR(MP_QSTR_morph), (mp_obj_t)&py_image_morph_obj}, /* Image Filtering */ diff --git a/src/omv/py/qstrdefsomv.h b/src/omv/py/qstrdefsomv.h index 1cbc4a8c8..6c27783f5 100644 --- a/src/omv/py/qstrdefsomv.h +++ b/src/omv/py/qstrdefsomv.h @@ -349,6 +349,12 @@ Q(CPUFREQ_216MHZ) Q(get_frequency) Q(set_frequency) +// Max +// duplicate Q(max) + +// Min +// duplicate Q(min) + // Log Polar Q(linpolar) Q(reverse)