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.
This commit is contained in:
Kwabena W. Agyeman 2018-02-21 01:27:13 -05:00
parent 5d3ebda192
commit 646425b2a6
7 changed files with 151 additions and 88 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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)]++;
}
}
}
}
}

View File

@ -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);
}
}

View File

@ -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__

View File

@ -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.");

View File

@ -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)