From f52360271959417b298635a457a96b00bc680c5d Mon Sep 17 00:00:00 2001 From: "Kwabena W. Agyeman" Date: Mon, 12 Feb 2024 20:43:46 -0800 Subject: [PATCH] modules/py_image: Use mp_arg_pasrse_all for erode/dilate. --- src/omv/imlib/binary.c | 14 ++--- src/omv/imlib/imlib.h | 1 + src/omv/modules/py_image.c | 119 +++++++++++++------------------------ 3 files changed, 49 insertions(+), 85 deletions(-) diff --git a/src/omv/imlib/binary.c b/src/omv/imlib/binary.c index 3916e0811..61805a282 100644 --- a/src/omv/imlib/binary.c +++ b/src/omv/imlib/binary.c @@ -888,12 +888,12 @@ static void imlib_erode_dilate(image_t *img, int ksize, int threshold, int e_or_ } void imlib_erode(image_t *img, int ksize, int threshold, image_t *mask) { - // Threshold should be equal to (((ksize*2)+1)*((ksize*2)+1))-1 - // for normal operation. E.g. for ksize==3 -> threshold==8 + // Threshold should be equal to 0 + // for normal operation. E.g. for ksize==3 -> threshold==0 // Basically you're adjusting the number of data that // must be set in the kernel (besides the center) for the output to be 1. // Erode normally requires all data to be 1. - imlib_erode_dilate(img, ksize, threshold, 0, mask); + imlib_erode_dilate(img, ksize, imlib_ksize_to_n(ksize) - 1 - threshold, 0, mask); } void imlib_dilate(image_t *img, int ksize, int threshold, image_t *mask) { @@ -906,13 +906,13 @@ void imlib_dilate(image_t *img, int ksize, int threshold, image_t *mask) { } void imlib_open(image_t *img, int ksize, int threshold, image_t *mask) { - imlib_erode(img, ksize, imlib_ksize_to_n(ksize) - 1 - threshold, mask); - imlib_dilate(img, ksize, 0 + threshold, mask); + imlib_erode(img, ksize, threshold, mask); + imlib_dilate(img, ksize, threshold, mask); } void imlib_close(image_t *img, int ksize, int threshold, image_t *mask) { - imlib_dilate(img, ksize, 0 + threshold, mask); - imlib_erode(img, ksize, imlib_ksize_to_n(ksize) - 1 - threshold, mask); + imlib_dilate(img, ksize, threshold, mask); + imlib_erode(img, ksize, threshold, mask); } void imlib_top_hat(image_t *img, int ksize, int threshold, image_t *mask) { diff --git a/src/omv/imlib/imlib.h b/src/omv/imlib/imlib.h index 7d809c070..1533828f6 100644 --- a/src/omv/imlib/imlib.h +++ b/src/omv/imlib/imlib.h @@ -943,6 +943,7 @@ typedef struct img_read_settings { save_image_format_t format; } img_read_settings_t; +typedef void (*binary_morph_op_t) (image_t *, int, int, image_t *); typedef void (*line_op_t) (image_t *, int, void *, void *, bool); typedef void (*flood_fill_call_back_t) (image_t *, int, int, int, void *); diff --git a/src/omv/modules/py_image.c b/src/omv/modules/py_image.c index 18e0cec3b..3cf74739c 100644 --- a/src/omv/modules/py_image.c +++ b/src/omv/modules/py_image.c @@ -2118,67 +2118,50 @@ STATIC mp_obj_t py_image_b_xnor(uint n_args, const mp_obj_t *args, mp_map_t *kw_ } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_b_xnor_obj, 2, py_image_b_xnor); -STATIC mp_obj_t py_image_erode(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { - int arg_ksize = - py_helper_arg_to_ksize(args[1]); - int arg_threshold = - py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold), - imlib_ksize_to_n(arg_ksize) - 1); - image_t *arg_msk = - py_helper_keyword_to_image(n_args, args, 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_mask), NULL); +static mp_obj_t py_image_binary_moprh_op(uint n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, + binary_morph_op_t op) { + enum { ARG_ksize, ARG_threshold, ARG_mask }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_ksize, MP_ARG_INT | MP_ARG_REQUIRED, }, + { MP_QSTR_threshold, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0 } }, + { MP_QSTR_mask, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} }, + }; + + // Parse args. + image_t *image = py_helper_arg_to_image(pos_args[0], ARG_IMAGE_MUTABLE); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); fb_alloc_mark(); - imlib_erode(py_helper_arg_to_image(args[0], ARG_IMAGE_MUTABLE), arg_ksize, arg_threshold, arg_msk); + image_t *mask = NULL; + if (args[ARG_mask].u_obj != mp_const_none) { + mask = py_helper_arg_to_image(args[ARG_mask].u_obj, ARG_IMAGE_MUTABLE | ARG_IMAGE_ALLOC); + } + + op(image, args[ARG_ksize].u_int, args[ARG_threshold].u_int, mask); fb_alloc_free_till_mark(); - return args[0]; + return pos_args[0]; } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_erode_obj, 2, py_image_erode); -STATIC mp_obj_t py_image_dilate(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { - int arg_ksize = - py_helper_arg_to_ksize(args[1]); - int arg_threshold = - py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold), - 0); - image_t *arg_msk = - py_helper_keyword_to_image(n_args, args, 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_mask), NULL); - - fb_alloc_mark(); - imlib_dilate(py_helper_arg_to_image(args[0], ARG_IMAGE_MUTABLE), arg_ksize, arg_threshold, arg_msk); - fb_alloc_free_till_mark(); - return args[0]; +STATIC mp_obj_t py_image_erode(uint n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + return py_image_binary_moprh_op(n_args, pos_args, kw_args, imlib_erode); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_dilate_obj, 2, py_image_dilate); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_erode_obj, 1, py_image_erode); -STATIC mp_obj_t py_image_open(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { - int arg_ksize = - py_helper_arg_to_ksize(args[1]); - int arg_threshold = - py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold), 0); - image_t *arg_msk = - py_helper_keyword_to_image(n_args, args, 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_mask), NULL); - - fb_alloc_mark(); - imlib_open(py_helper_arg_to_image(args[0], ARG_IMAGE_MUTABLE), arg_ksize, arg_threshold, arg_msk); - fb_alloc_free_till_mark(); - return args[0]; +STATIC mp_obj_t py_image_dilate(uint n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + return py_image_binary_moprh_op(n_args, pos_args, kw_args, imlib_dilate); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_open_obj, 2, py_image_open); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_dilate_obj, 1, py_image_dilate); -STATIC mp_obj_t py_image_close(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { - int arg_ksize = - py_helper_arg_to_ksize(args[1]); - int arg_threshold = - py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold), 0); - image_t *arg_msk = - py_helper_keyword_to_image(n_args, args, 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_mask), NULL); - - fb_alloc_mark(); - imlib_close(py_helper_arg_to_image(args[0], ARG_IMAGE_MUTABLE), arg_ksize, arg_threshold, arg_msk); - fb_alloc_free_till_mark(); - return args[0]; +STATIC mp_obj_t py_image_open(uint n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + return py_image_binary_moprh_op(n_args, pos_args, kw_args, imlib_open); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_close_obj, 2, py_image_close); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_open_obj, 1, py_image_open); + +STATIC mp_obj_t py_image_close(uint n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + return py_image_binary_moprh_op(n_args, pos_args, kw_args, imlib_close); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_close_obj, 1, py_image_close); #endif // IMLIB_ENABLE_BINARY_OPS #ifdef IMLIB_ENABLE_MATH_OPS @@ -2416,36 +2399,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_blend_obj, 2, py_image_blend); #endif//IMLIB_ENABLE_MATH_OPS #if defined(IMLIB_ENABLE_MATH_OPS) && defined(IMLIB_ENABLE_BINARY_OPS) -STATIC mp_obj_t py_image_top_hat(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { - int arg_ksize = - py_helper_arg_to_ksize(args[1]); - int arg_threshold = - py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold), 0); - image_t *arg_msk = - py_helper_keyword_to_image(n_args, args, 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_mask), NULL); - - fb_alloc_mark(); - imlib_top_hat(py_helper_arg_to_image(args[0], ARG_IMAGE_MUTABLE), arg_ksize, arg_threshold, arg_msk); - fb_alloc_free_till_mark(); - return args[0]; +STATIC mp_obj_t py_image_top_hat(uint n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + return py_image_binary_moprh_op(n_args, pos_args, kw_args, imlib_top_hat); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_top_hat_obj, 2, py_image_top_hat); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_top_hat_obj, 1, py_image_top_hat); -STATIC mp_obj_t py_image_black_hat(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { - int arg_ksize = - py_helper_arg_to_ksize(args[1]); - int arg_threshold = - py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold), 0); - image_t *arg_msk = - py_helper_keyword_to_image(n_args, args, 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_mask), NULL); - - fb_alloc_mark(); - imlib_black_hat(py_helper_arg_to_image(args[0], ARG_IMAGE_MUTABLE), arg_ksize, arg_threshold, arg_msk); - fb_alloc_free_till_mark(); - return args[0]; +STATIC mp_obj_t py_image_black_hat(uint n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + return py_image_binary_moprh_op(n_args, pos_args, kw_args, imlib_black_hat); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_black_hat_obj, 2, py_image_black_hat); -#endif // defined(IMLIB_ENABLE_MATH_OPS) && defined (IMLIB_ENABLE_BINARY_OPS) +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_black_hat_obj, 1, py_image_black_hat); +#endif // defined(IMLIB_ENABLE_MATH_OPS) && defined(IMLIB_ENABLE_BINARY_OPS) //////////////////// // Filtering Methods