From 646425b2a6e249ed2a91fca4bc5e2972c6207f48 Mon Sep 17 00:00:00 2001 From: "Kwabena W. Agyeman" Date: Wed, 21 Feb 2018 01:27:13 -0500 Subject: [PATCH] Add color thresholding support to get_histogram/stats. You can now pass a color threshold list to get histogram and get stats (along with an invert arg) to control what gets put into the histogram. --- src/omv/img/imlib.h | 2 +- src/omv/img/shadow_removal.c | 2 +- src/omv/img/stats.c | 92 ++++++++++++++++++++++++++++------- src/omv/py/py_helper.c | 43 +++++++++++++++++ src/omv/py/py_helper.h | 2 + src/omv/py/py_image.c | 94 ++++++++++-------------------------- src/omv/py/qstrdefsomv.h | 4 ++ 7 files changed, 151 insertions(+), 88 deletions(-) diff --git a/src/omv/img/imlib.h b/src/omv/img/imlib.h index 243c641ff..b9bd211c4 100644 --- a/src/omv/img/imlib.h +++ b/src/omv/img/imlib.h @@ -1226,7 +1226,7 @@ void imlib_rotation_corr(image_t *img, float x_rotation, float y_rotation, float zoom); // Statistics void imlib_get_similarity(image_t *img, const char *path, image_t *other, float *avg, float *std, float *min, float *max); -void imlib_get_histogram(histogram_t *out, image_t *ptr, rectangle_t *roi); +void imlib_get_histogram(histogram_t *out, image_t *ptr, rectangle_t *roi, list_t *thresholds, bool invert); void imlib_get_percentile(percentile_t *out, image_bpp_t bpp, histogram_t *ptr, float percentile); void imlib_get_threshold(threshold_t *out, image_bpp_t bpp, histogram_t *ptr); void imlib_get_statistics(statistics_t *out, image_bpp_t bpp, histogram_t *ptr); diff --git a/src/omv/img/shadow_removal.c b/src/omv/img/shadow_removal.c index adf2bfeb4..75d2d0d1a 100644 --- a/src/omv/img/shadow_removal.c +++ b/src/omv/img/shadow_removal.c @@ -197,7 +197,7 @@ void imlib_remove_shadows(image_t *img, const char *path, image_t *other) h.LBins = fb_alloc(h.LBinCount * sizeof(float)); h.ABins = fb_alloc(h.ABinCount * sizeof(float)); h.BBins = fb_alloc(h.BBinCount * sizeof(float)); - imlib_get_histogram(&h, &temp_image, &r); + imlib_get_histogram(&h, &temp_image, &r, NULL, false); statistics_t s; imlib_get_statistics(&s, temp_image.bpp, &h); diff --git a/src/omv/img/stats.c b/src/omv/img/stats.c index 060ba94f5..848b88acf 100644 --- a/src/omv/img/stats.c +++ b/src/omv/img/stats.c @@ -141,7 +141,7 @@ void imlib_get_similarity(image_t *img, const char *path, image_t *other, float } #endif //IMLIB_ENABLE_GET_SIMILARITY -void imlib_get_histogram(histogram_t *out, image_t *ptr, rectangle_t *roi) +void imlib_get_histogram(histogram_t *out, image_t *ptr, rectangle_t *roi, list_t *thresholds, bool invert) { switch(ptr->bpp) { case IMAGE_BPP_BINARY: { @@ -149,11 +149,29 @@ void imlib_get_histogram(histogram_t *out, image_t *ptr, rectangle_t *roi) float mult = (out->LBinCount - 1) / ((float) (COLOR_BINARY_MAX - COLOR_BINARY_MIN)); - for (int y = roi->y, yy = roi->y + roi->h; y < yy; y++) { - uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(ptr, y); - for (int x = roi->x, xx = roi->x + roi->w; x < xx; x++) { - int pixel = IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x); - ((uint32_t *) out->LBins)[fast_roundf((pixel - COLOR_BINARY_MIN) * mult)]++; + if ((!thresholds) || (!list_size(thresholds))) { + // Fast histogram code when no color thresholds list... + for (int y = roi->y, yy = roi->y + roi->h; y < yy; y++) { + uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(ptr, y); + for (int x = roi->x, xx = roi->x + roi->w; x < xx; x++) { + int pixel = IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x); + ((uint32_t *) out->LBins)[fast_roundf((pixel - COLOR_BINARY_MIN) * mult)]++; + } + } + } else { + for (list_lnk_t *it = iterator_start_from_head(thresholds); it; it = iterator_next(it)) { + color_thresholds_list_lnk_data_t lnk_data; + iterator_get(thresholds, it, &lnk_data); + + for (int y = roi->y, yy = roi->y + roi->h; y < yy; y++) { + uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(ptr, y); + for (int x = roi->x, xx = roi->x + roi->w; x < xx; x++) { + int pixel = IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x); + if (COLOR_THRESHOLD_BINARY(pixel, &lnk_data, invert)) { + ((uint32_t *) out->LBins)[fast_roundf((pixel - COLOR_BINARY_MIN) * mult)]++; + } + } + } } } @@ -170,11 +188,29 @@ void imlib_get_histogram(histogram_t *out, image_t *ptr, rectangle_t *roi) float mult = (out->LBinCount - 1) / ((float) (COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN)); - for (int y = roi->y, yy = roi->y + roi->h; y < yy; y++) { - uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(ptr, y); - for (int x = roi->x, xx = roi->x + roi->w; x < xx; x++) { - int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x); - ((uint32_t *) out->LBins)[fast_roundf((pixel - COLOR_GRAYSCALE_MIN) * mult)]++; + if ((!thresholds) || (!list_size(thresholds))) { + // Fast histogram code when no color thresholds list... + for (int y = roi->y, yy = roi->y + roi->h; y < yy; y++) { + uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(ptr, y); + for (int x = roi->x, xx = roi->x + roi->w; x < xx; x++) { + int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x); + ((uint32_t *) out->LBins)[fast_roundf((pixel - COLOR_GRAYSCALE_MIN) * mult)]++; + } + } + } else { + for (list_lnk_t *it = iterator_start_from_head(thresholds); it; it = iterator_next(it)) { + color_thresholds_list_lnk_data_t lnk_data; + iterator_get(thresholds, it, &lnk_data); + + for (int y = roi->y, yy = roi->y + roi->h; y < yy; y++) { + uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(ptr, y); + for (int x = roi->x, xx = roi->x + roi->w; x < xx; x++) { + int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x); + if (COLOR_THRESHOLD_GRAYSCALE(pixel, &lnk_data, invert)) { + ((uint32_t *) out->LBins)[fast_roundf((pixel - COLOR_GRAYSCALE_MIN) * mult)]++; + } + } + } } } @@ -195,13 +231,33 @@ void imlib_get_histogram(histogram_t *out, image_t *ptr, rectangle_t *roi) float a_mult = (out->ABinCount - 1) / ((float) (COLOR_A_MAX - COLOR_A_MIN)); float b_mult = (out->BBinCount - 1) / ((float) (COLOR_B_MAX - COLOR_B_MIN)); - for (int y = roi->y, yy = roi->y + roi->h; y < yy; y++) { - uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(ptr, y); - for (int x = roi->x, xx = roi->x + roi->w; x < xx; x++) { - int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x); - ((uint32_t *) out->LBins)[fast_roundf((COLOR_RGB565_TO_L(pixel) - COLOR_L_MIN) * l_mult)]++; - ((uint32_t *) out->ABins)[fast_roundf((COLOR_RGB565_TO_A(pixel) - COLOR_A_MIN) * a_mult)]++; - ((uint32_t *) out->BBins)[fast_roundf((COLOR_RGB565_TO_B(pixel) - COLOR_B_MIN) * b_mult)]++; + if ((!thresholds) || (!list_size(thresholds))) { + // Fast histogram code when no color thresholds list... + for (int y = roi->y, yy = roi->y + roi->h; y < yy; y++) { + uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(ptr, y); + for (int x = roi->x, xx = roi->x + roi->w; x < xx; x++) { + int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x); + ((uint32_t *) out->LBins)[fast_roundf((COLOR_RGB565_TO_L(pixel) - COLOR_L_MIN) * l_mult)]++; + ((uint32_t *) out->ABins)[fast_roundf((COLOR_RGB565_TO_A(pixel) - COLOR_A_MIN) * a_mult)]++; + ((uint32_t *) out->BBins)[fast_roundf((COLOR_RGB565_TO_B(pixel) - COLOR_B_MIN) * b_mult)]++; + } + } + } else { + for (list_lnk_t *it = iterator_start_from_head(thresholds); it; it = iterator_next(it)) { + color_thresholds_list_lnk_data_t lnk_data; + iterator_get(thresholds, it, &lnk_data); + + for (int y = roi->y, yy = roi->y + roi->h; y < yy; y++) { + uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(ptr, y); + for (int x = roi->x, xx = roi->x + roi->w; x < xx; x++) { + int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x); + if (COLOR_THRESHOLD_RGB565(pixel, &lnk_data, invert)) { + ((uint32_t *) out->LBins)[fast_roundf((COLOR_RGB565_TO_L(pixel) - COLOR_L_MIN) * l_mult)]++; + ((uint32_t *) out->ABins)[fast_roundf((COLOR_RGB565_TO_A(pixel) - COLOR_A_MIN) * a_mult)]++; + ((uint32_t *) out->BBins)[fast_roundf((COLOR_RGB565_TO_B(pixel) - COLOR_B_MIN) * b_mult)]++; + } + } + } } } diff --git a/src/omv/py/py_helper.c b/src/omv/py/py_helper.c index e6bec10b3..69b774558 100644 --- a/src/omv/py/py_helper.c +++ b/src/omv/py/py_helper.c @@ -132,3 +132,46 @@ void py_helper_lookup_rectangle_2(mp_map_t *kw_args, mp_obj_t kw, image_t *img, nlr_raise(mp_obj_new_exception_msg(&mp_type_AssertionError, "Invalid ROI dimensions!")); } } + +void py_helper_arg_to_thresholds(const mp_obj_t arg, list_t *thresholds) +{ + mp_uint_t arg_thresholds_len; + mp_obj_t *arg_thresholds; + mp_obj_get_array(arg, &arg_thresholds_len, &arg_thresholds); + if (!arg_thresholds_len) return; + + for(mp_uint_t i = 0; i < arg_thresholds_len; i++) { + mp_uint_t arg_threshold_len; + mp_obj_t *arg_threshold; + mp_obj_get_array(arg_thresholds[i], &arg_threshold_len, &arg_threshold); + if (arg_threshold_len) { + color_thresholds_list_lnk_data_t lnk_data; + lnk_data.LMin = (arg_threshold_len > 0) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[0]), + IM_MAX(COLOR_L_MAX, COLOR_GRAYSCALE_MAX)), IM_MIN(COLOR_L_MIN, COLOR_GRAYSCALE_MIN)) : IM_MIN(COLOR_L_MIN, COLOR_GRAYSCALE_MIN); + lnk_data.LMax = (arg_threshold_len > 1) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[1]), + IM_MAX(COLOR_L_MAX, COLOR_GRAYSCALE_MAX)), IM_MIN(COLOR_L_MIN, COLOR_GRAYSCALE_MIN)) : IM_MAX(COLOR_L_MAX, COLOR_GRAYSCALE_MAX); + lnk_data.AMin = (arg_threshold_len > 2) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[2]), COLOR_A_MAX), COLOR_A_MIN) : COLOR_A_MIN; + lnk_data.AMax = (arg_threshold_len > 3) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[3]), COLOR_A_MAX), COLOR_A_MIN) : COLOR_A_MAX; + lnk_data.BMin = (arg_threshold_len > 4) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[4]), COLOR_B_MAX), COLOR_B_MIN) : COLOR_B_MIN; + lnk_data.BMax = (arg_threshold_len > 5) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[5]), COLOR_B_MAX), COLOR_B_MIN) : COLOR_B_MAX; + color_thresholds_list_lnk_data_t lnk_data_tmp; + memcpy(&lnk_data_tmp, &lnk_data, sizeof(color_thresholds_list_lnk_data_t)); + lnk_data.LMin = IM_MIN(lnk_data_tmp.LMin, lnk_data_tmp.LMax); + lnk_data.LMax = IM_MAX(lnk_data_tmp.LMin, lnk_data_tmp.LMax); + lnk_data.AMin = IM_MIN(lnk_data_tmp.AMin, lnk_data_tmp.AMax); + lnk_data.AMax = IM_MAX(lnk_data_tmp.AMin, lnk_data_tmp.AMax); + lnk_data.BMin = IM_MIN(lnk_data_tmp.BMin, lnk_data_tmp.BMax); + lnk_data.BMax = IM_MAX(lnk_data_tmp.BMin, lnk_data_tmp.BMax); + list_push_back(thresholds, &lnk_data); + } + } +} + +void py_helper_keyword_thresholds(mp_map_t *kw_args, mp_obj_t kw, list_t *thresholds) +{ + mp_map_elem_t *kw_arg = mp_map_lookup(kw_args, kw, MP_MAP_LOOKUP); + + if (kw_arg != NULL) { + py_helper_arg_to_thresholds(kw_arg->value, thresholds); + } +} diff --git a/src/omv/py/py_helper.h b/src/omv/py/py_helper.h index cbac69380..1cf7e57d1 100644 --- a/src/omv/py/py_helper.h +++ b/src/omv/py/py_helper.h @@ -18,4 +18,6 @@ int py_helper_lookup_color(mp_map_t *kw_args, int default_color); void py_helper_lookup_offset(mp_map_t *kw_args, image_t *img, point_t *p); void py_helper_lookup_rectangle(mp_map_t *kw_args, image_t *img, rectangle_t *r); void py_helper_lookup_rectangle_2(mp_map_t *kw_args, mp_obj_t kw, image_t *img, rectangle_t *r); +void py_helper_arg_to_thresholds(const mp_obj_t arg, list_t *thresholds); +void py_helper_keyword_thresholds(mp_map_t *kw_args, mp_obj_t kw, list_t *thresholds); #endif // __PY_HELPER__ diff --git a/src/omv/py/py_image.c b/src/omv/py/py_image.c index cf146a8a7..394e01c22 100644 --- a/src/omv/py/py_image.c +++ b/src/omv/py/py_image.c @@ -2217,6 +2217,11 @@ static mp_obj_t py_image_get_histogram(uint n_args, const mp_obj_t *args, mp_map rectangle_t roi; py_helper_lookup_rectangle(kw_args, arg_img, &roi); + list_t thresholds; + list_init(&thresholds, sizeof(color_thresholds_list_lnk_data_t)); + py_helper_keyword_thresholds(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_thresholds), &thresholds); + bool invert = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_invert), false); + histogram_t hist; switch(arg_img->bpp) { case IMAGE_BPP_BINARY: { @@ -2230,7 +2235,8 @@ static mp_obj_t py_image_get_histogram(uint n_args, const mp_obj_t *args, mp_map hist.LBins = fb_alloc(hist.LBinCount * sizeof(float)); hist.ABins = NULL; hist.BBins = NULL; - imlib_get_histogram(&hist, arg_img, &roi); + imlib_get_histogram(&hist, arg_img, &roi, &thresholds, invert); + list_free(&thresholds); break; } case IMAGE_BPP_GRAYSCALE: { @@ -2244,7 +2250,8 @@ static mp_obj_t py_image_get_histogram(uint n_args, const mp_obj_t *args, mp_map hist.LBins = fb_alloc(hist.LBinCount * sizeof(float)); hist.ABins = NULL; hist.BBins = NULL; - imlib_get_histogram(&hist, arg_img, &roi); + imlib_get_histogram(&hist, arg_img, &roi, &thresholds, invert); + list_free(&thresholds); break; } case IMAGE_BPP_RGB565: { @@ -2264,7 +2271,8 @@ static mp_obj_t py_image_get_histogram(uint n_args, const mp_obj_t *args, mp_map hist.LBins = fb_alloc(hist.LBinCount * sizeof(float)); hist.ABins = fb_alloc(hist.ABinCount * sizeof(float)); hist.BBins = fb_alloc(hist.BBinCount * sizeof(float)); - imlib_get_histogram(&hist, arg_img, &roi); + imlib_get_histogram(&hist, arg_img, &roi, &thresholds, invert); + list_free(&thresholds); break; } default: { @@ -2308,6 +2316,11 @@ static mp_obj_t py_image_get_statistics(uint n_args, const mp_obj_t *args, mp_ma rectangle_t roi; py_helper_lookup_rectangle(kw_args, arg_img, &roi); + list_t thresholds; + list_init(&thresholds, sizeof(color_thresholds_list_lnk_data_t)); + py_helper_keyword_thresholds(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_thresholds), &thresholds); + bool invert = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_invert), false); + histogram_t hist; switch(arg_img->bpp) { case IMAGE_BPP_BINARY: { @@ -2321,7 +2334,8 @@ static mp_obj_t py_image_get_statistics(uint n_args, const mp_obj_t *args, mp_ma hist.LBins = fb_alloc(hist.LBinCount * sizeof(float)); hist.ABins = NULL; hist.BBins = NULL; - imlib_get_histogram(&hist, arg_img, &roi); + imlib_get_histogram(&hist, arg_img, &roi, &thresholds, invert); + list_free(&thresholds); break; } case IMAGE_BPP_GRAYSCALE: { @@ -2335,7 +2349,8 @@ static mp_obj_t py_image_get_statistics(uint n_args, const mp_obj_t *args, mp_ma hist.LBins = fb_alloc(hist.LBinCount * sizeof(float)); hist.ABins = NULL; hist.BBins = NULL; - imlib_get_histogram(&hist, arg_img, &roi); + imlib_get_histogram(&hist, arg_img, &roi, &thresholds, invert); + list_free(&thresholds); break; } case IMAGE_BPP_RGB565: { @@ -2355,7 +2370,8 @@ static mp_obj_t py_image_get_statistics(uint n_args, const mp_obj_t *args, mp_ma hist.LBins = fb_alloc(hist.LBinCount * sizeof(float)); hist.ABins = fb_alloc(hist.ABinCount * sizeof(float)); hist.BBins = fb_alloc(hist.BBinCount * sizeof(float)); - imlib_get_histogram(&hist, arg_img, &roi); + imlib_get_histogram(&hist, arg_img, &roi, &thresholds, invert); + list_free(&thresholds); break; } default: { @@ -2508,39 +2524,10 @@ static mp_obj_t py_image_get_regression(uint n_args, const mp_obj_t *args, mp_ma rectangle_t roi; py_helper_lookup_rectangle(kw_args, arg_img, &roi); - mp_uint_t arg_thresholds_len; - mp_obj_t *arg_thresholds; - mp_obj_get_array(args[1], &arg_thresholds_len, &arg_thresholds); - if (!arg_thresholds_len) return mp_const_none; - list_t thresholds; list_init(&thresholds, sizeof(color_thresholds_list_lnk_data_t)); - - for(mp_uint_t i = 0; i < arg_thresholds_len; i++) { - mp_uint_t arg_threshold_len; - mp_obj_t *arg_threshold; - mp_obj_get_array(arg_thresholds[i], &arg_threshold_len, &arg_threshold); - if (arg_threshold_len) { - color_thresholds_list_lnk_data_t lnk_data; - lnk_data.LMin = (arg_threshold_len > 0) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[0]), - IM_MAX(COLOR_L_MAX, COLOR_GRAYSCALE_MAX)), IM_MIN(COLOR_L_MIN, COLOR_GRAYSCALE_MIN)) : IM_MIN(COLOR_L_MIN, COLOR_GRAYSCALE_MIN); - lnk_data.LMax = (arg_threshold_len > 1) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[1]), - IM_MAX(COLOR_L_MAX, COLOR_GRAYSCALE_MAX)), IM_MIN(COLOR_L_MIN, COLOR_GRAYSCALE_MIN)) : IM_MAX(COLOR_L_MAX, COLOR_GRAYSCALE_MAX); - lnk_data.AMin = (arg_threshold_len > 2) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[2]), COLOR_A_MAX), COLOR_A_MIN) : COLOR_A_MIN; - lnk_data.AMax = (arg_threshold_len > 3) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[3]), COLOR_A_MAX), COLOR_A_MIN) : COLOR_A_MAX; - lnk_data.BMin = (arg_threshold_len > 4) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[4]), COLOR_B_MAX), COLOR_B_MIN) : COLOR_B_MIN; - lnk_data.BMax = (arg_threshold_len > 5) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[5]), COLOR_B_MAX), COLOR_B_MIN) : COLOR_B_MAX; - color_thresholds_list_lnk_data_t lnk_data_tmp; - memcpy(&lnk_data_tmp, &lnk_data, sizeof(color_thresholds_list_lnk_data_t)); - lnk_data.LMin = IM_MIN(lnk_data_tmp.LMin, lnk_data_tmp.LMax); - lnk_data.LMax = IM_MAX(lnk_data_tmp.LMin, lnk_data_tmp.LMax); - lnk_data.AMin = IM_MIN(lnk_data_tmp.AMin, lnk_data_tmp.AMax); - lnk_data.AMax = IM_MAX(lnk_data_tmp.AMin, lnk_data_tmp.AMax); - lnk_data.BMin = IM_MIN(lnk_data_tmp.BMin, lnk_data_tmp.BMax); - lnk_data.BMax = IM_MAX(lnk_data_tmp.BMin, lnk_data_tmp.BMax); - list_push_back(&thresholds, &lnk_data); - } - } + py_helper_arg_to_thresholds(args[1], &thresholds); + if (!list_size(&thresholds)) return mp_const_none; unsigned int x_stride = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_stride), 2); PY_ASSERT_TRUE_MSG(x_stride > 0, "x_stride must not be zero."); @@ -2753,39 +2740,10 @@ static mp_obj_t py_image_find_blobs(uint n_args, const mp_obj_t *args, mp_map_t rectangle_t roi; py_helper_lookup_rectangle(kw_args, arg_img, &roi); - mp_uint_t arg_thresholds_len; - mp_obj_t *arg_thresholds; - mp_obj_get_array(args[1], &arg_thresholds_len, &arg_thresholds); - if (!arg_thresholds_len) return mp_obj_new_list(0, NULL); - list_t thresholds; list_init(&thresholds, sizeof(color_thresholds_list_lnk_data_t)); - - for(mp_uint_t i = 0; i < arg_thresholds_len; i++) { - mp_uint_t arg_threshold_len; - mp_obj_t *arg_threshold; - mp_obj_get_array(arg_thresholds[i], &arg_threshold_len, &arg_threshold); - if (arg_threshold_len) { - color_thresholds_list_lnk_data_t lnk_data; - lnk_data.LMin = (arg_threshold_len > 0) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[0]), - IM_MAX(COLOR_L_MAX, COLOR_GRAYSCALE_MAX)), IM_MIN(COLOR_L_MIN, COLOR_GRAYSCALE_MIN)) : IM_MIN(COLOR_L_MIN, COLOR_GRAYSCALE_MIN); - lnk_data.LMax = (arg_threshold_len > 1) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[1]), - IM_MAX(COLOR_L_MAX, COLOR_GRAYSCALE_MAX)), IM_MIN(COLOR_L_MIN, COLOR_GRAYSCALE_MIN)) : IM_MAX(COLOR_L_MAX, COLOR_GRAYSCALE_MAX); - lnk_data.AMin = (arg_threshold_len > 2) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[2]), COLOR_A_MAX), COLOR_A_MIN) : COLOR_A_MIN; - lnk_data.AMax = (arg_threshold_len > 3) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[3]), COLOR_A_MAX), COLOR_A_MIN) : COLOR_A_MAX; - lnk_data.BMin = (arg_threshold_len > 4) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[4]), COLOR_B_MAX), COLOR_B_MIN) : COLOR_B_MIN; - lnk_data.BMax = (arg_threshold_len > 5) ? IM_MAX(IM_MIN(mp_obj_get_int(arg_threshold[5]), COLOR_B_MAX), COLOR_B_MIN) : COLOR_B_MAX; - color_thresholds_list_lnk_data_t lnk_data_tmp; - memcpy(&lnk_data_tmp, &lnk_data, sizeof(color_thresholds_list_lnk_data_t)); - lnk_data.LMin = IM_MIN(lnk_data_tmp.LMin, lnk_data_tmp.LMax); - lnk_data.LMax = IM_MAX(lnk_data_tmp.LMin, lnk_data_tmp.LMax); - lnk_data.AMin = IM_MIN(lnk_data_tmp.AMin, lnk_data_tmp.AMax); - lnk_data.AMax = IM_MAX(lnk_data_tmp.AMin, lnk_data_tmp.AMax); - lnk_data.BMin = IM_MIN(lnk_data_tmp.BMin, lnk_data_tmp.BMax); - lnk_data.BMax = IM_MAX(lnk_data_tmp.BMin, lnk_data_tmp.BMax); - list_push_back(&thresholds, &lnk_data); - } - } + py_helper_arg_to_thresholds(args[1], &thresholds); + if (!list_size(&thresholds)) return mp_obj_new_list(0, NULL); unsigned int x_stride = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_stride), 2); PY_ASSERT_TRUE_MSG(x_stride > 0, "x_stride must not be zero."); diff --git a/src/omv/py/qstrdefsomv.h b/src/omv/py/qstrdefsomv.h index 23efe27c3..6d7886fd9 100644 --- a/src/omv/py/qstrdefsomv.h +++ b/src/omv/py/qstrdefsomv.h @@ -406,6 +406,8 @@ Q(bins) Q(l_bins) Q(a_bins) Q(b_bins) +Q(thresholds) +// duplicate Q(invert) // Histogram Object Q(histogram) // duplicate Q(bins) @@ -438,6 +440,8 @@ Q(b_value) // duplicate Q(l_bins) // duplicate Q(a_bins) // duplicate Q(b_bins) +// duplicate Q(thresholds) +// duplicate Q(invert) // Statistics Object // duplicate Q(statistics) // duplicate Q(mean)