Example #1
0
static mp_obj_t py_image_dilate(mp_obj_t image_obj, mp_obj_t ksize_obj)
{
    image_t *image = NULL;
    image = py_image_cobj(image_obj);

    /* sanity checks */
    PY_ASSERT_TRUE(image->bpp==1);

    imlib_dilate(image, mp_obj_get_int(ksize_obj));
    return mp_const_none;
}
Example #2
0
static mp_obj_t py_image_dilate(mp_obj_t image_obj, mp_obj_t ksize_obj)
{
    image_t *image = NULL;
    image = py_image_cobj(image_obj);

    /* sanity checks */
    PY_ASSERT_TRUE_MSG(image->bpp == 1,
            "This function is only supported on GRAYSCALE images");

    imlib_dilate(image, mp_obj_get_int(ksize_obj));
    return mp_const_none;
}
Example #3
0
void imlib_remove_shadows(image_t *img, const char *path, image_t *other, int scalar, bool single)
{
    if (!single) {
        imlib_remove_shadows_line_op_state_t state;

        for (int i = 0; i < imlib_remove_shadows_kernel_size; i++) {
            state.img_lines[i] = fb_alloc(img->w * sizeof(uint16_t));
            state.other_lines[i] = fb_alloc(img->w * sizeof(uint16_t));
            state.out_lines[i] = fb_alloc(img->w * sizeof(uint16_t));
        }

        state.lines_processed = 0;

        imlib_image_operation(img, path, other, scalar, imlib_remove_shadows_line_op, &state);

        for (int i = 0; i < imlib_remove_shadows_kernel_size; i++) {
            fb_free();
            fb_free();
            fb_free();
        }
    } else {

        // Create Shadow Mask

        image_t temp_image;
        temp_image.w = img->w;
        temp_image.h = img->h;
        temp_image.bpp = img->bpp;
        temp_image.data = fb_alloc(image_size(img));

        memcpy(temp_image.data, img->data, image_size(img));

        rectangle_t r;
        r.x = 0;
        r.y = 0;
        r.w = temp_image.w;
        r.h = temp_image.h;

        histogram_t h;
        h.LBinCount = COLOR_L_MAX - COLOR_L_MIN + 1;
        h.ABinCount = COLOR_A_MAX - COLOR_A_MIN + 1;
        h.BBinCount = COLOR_B_MAX - COLOR_B_MIN + 1;
        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, NULL, false);

        statistics_t s;
        imlib_get_statistics(&s, temp_image.bpp, &h);

        int sum = 0;
        int mean = s.LMean * 0.8f;

        for (int y = 0, yy = temp_image.h; y < yy; y++) {
            uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&temp_image, y);

            for (int x = 0, xx = temp_image.w; x < xx; x++) {
                sum += COLOR_RGB565_TO_L(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x)) < mean;
            }
        }

        if (sum > ((temp_image.w * temp_image.h) / 20)) { // Don't do anything if the image is mostly flat.

            threshold_t t;
            imlib_get_threshold(&t, temp_image.bpp, &h);

            list_t thresholds;
            list_init(&thresholds, sizeof(color_thresholds_list_lnk_data_t));
            color_thresholds_list_lnk_data_t lnk_data;
            lnk_data.LMin = COLOR_L_MIN;
            lnk_data.AMin = COLOR_A_MIN;
            lnk_data.BMin = COLOR_B_MIN;
            lnk_data.LMax = t.LValue;
            lnk_data.AMax = COLOR_A_MAX;
            lnk_data.BMax = COLOR_B_MAX;
            list_push_back(&thresholds, &lnk_data);
            imlib_binary(&temp_image, &temp_image, &thresholds, false, false, NULL);
            list_free(&thresholds);

            imlib_erode(&temp_image, 3, 30, NULL);
            imlib_dilate(&temp_image, 1, 1, NULL);

            // Get Shadow Average

            image_t temp_image_2;
            temp_image_2.w = temp_image.w;
            temp_image_2.h = temp_image.h;
            temp_image_2.bpp = temp_image.bpp;
            temp_image_2.data = fb_alloc(image_size(&temp_image));

            memcpy(temp_image_2.data, temp_image.data, image_size(&temp_image));
            imlib_erode(&temp_image_2, 3, 48, NULL);

            int shadow_r_sum = 0;
            int shadow_g_sum = 0;
            int shadow_b_sum = 0;
            int shadow_count = 0;

            for (int y = 0, yy = temp_image_2.h; y < yy; y++) {
                uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&temp_image_2, y);
                uint16_t *row_ptr_2 = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);

                for (int x = 0, xx = temp_image_2.w; x < xx; x++) {
                    if (IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x)) {
                        int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr_2, x);
                        int r = COLOR_RGB565_TO_R8(pixel);
                        int g = COLOR_RGB565_TO_G8(pixel);
                        int b = COLOR_RGB565_TO_R8(pixel);
                        shadow_r_sum += r;
                        shadow_g_sum += g;
                        shadow_b_sum += b;
                        shadow_count += 1;
                    }
                }
            }

            memcpy(temp_image_2.data, temp_image.data, image_size(&temp_image));
            imlib_invert(&temp_image_2);
            imlib_erode(&temp_image_2, 5, 120, NULL);
            imlib_invert(&temp_image_2);
            imlib_b_xor(&temp_image_2, NULL, &temp_image, 0, NULL);
            imlib_erode(&temp_image_2, 2, 24, NULL);

            int not_shadow_r_sum = 0;
            int not_shadow_g_sum = 0;
            int not_shadow_b_sum = 0;
            int not_shadow_count = 0;

            for (int y = 0, yy = temp_image_2.h; y < yy; y++) {
                uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&temp_image_2, y);
                uint16_t *row_ptr_2 = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);

                for (int x = 0, xx = temp_image_2.w; x < xx; x++) {
                    if (IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x)) {
                        int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr_2, x);
                        int r = COLOR_RGB565_TO_R8(pixel);
                        int g = COLOR_RGB565_TO_G8(pixel);
                        int b = COLOR_RGB565_TO_R8(pixel);
                        not_shadow_r_sum += r;
                        not_shadow_g_sum += g;
                        not_shadow_b_sum += b;
                        not_shadow_count += 1;
                    }
                }
            }

            // Fill in the umbra... (inner part of the shadow)...

            memcpy(temp_image_2.data, temp_image.data, image_size(&temp_image));

            imlib_mean_filter(&temp_image, 2, false, 0, false, NULL);

            if (shadow_count && not_shadow_count) {

                float shadow_r_average = ((float) shadow_r_sum) / ((float) shadow_count);
                float shadow_g_average = ((float) shadow_g_sum) / ((float) shadow_count);
                float shadow_b_average = ((float) shadow_b_sum) / ((float) shadow_count);

                float not_shadow_r_average = ((float) not_shadow_r_sum) / ((float) not_shadow_count);
                float not_shadow_g_average = ((float) not_shadow_g_sum) / ((float) not_shadow_count);
                float not_shadow_b_average = ((float) not_shadow_b_sum) / ((float) not_shadow_count);

                float diff_r = not_shadow_r_average - shadow_r_average;
                float diff_g = not_shadow_g_average - shadow_g_average;
                float diff_b = not_shadow_b_average - shadow_b_average;

                for (int y = 0; y < img->h; y++) {
                    uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&temp_image, y);
                    uint16_t *row_ptr_2 = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);

                    for (int x = 0; x < img->w; x++) {
                        float alpha = ((float) (COLOR_RGB565_TO_Y(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x)) - COLOR_Y_MIN)) / ((float) (COLOR_Y_MAX - COLOR_Y_MIN));
                        int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr_2, x);
                        int r = COLOR_RGB565_TO_R8(pixel);
                        int g = COLOR_RGB565_TO_G8(pixel);
                        int b = COLOR_RGB565_TO_B8(pixel);

                        int r_new = IM_MIN(IM_MAX(r + (diff_r * alpha), COLOR_R8_MIN), COLOR_R8_MAX);
                        int g_new = IM_MIN(IM_MAX(g + (diff_g * alpha), COLOR_G8_MIN), COLOR_G8_MAX);
                        int b_new = IM_MIN(IM_MAX(b + (diff_b * alpha), COLOR_B8_MIN), COLOR_B8_MAX);
                        IMAGE_PUT_RGB565_PIXEL_FAST(row_ptr_2, x, COLOR_R8_G8_B8_TO_RGB565(r_new, g_new, b_new));
                    }
                }
            }

            // Fill in the penumbra... (outer part of the shadow)...

            memcpy(temp_image.data, temp_image_2.data, image_size(&temp_image_2));

            imlib_erode(&temp_image_2, 1, 8, NULL);
            imlib_b_xor(&temp_image, NULL, &temp_image_2, 0, NULL);
            imlib_dilate(&temp_image, 3, 0, NULL);
            imlib_median_filter(img, 2, 12, false, 0, false, &temp_image);

            fb_free(); // temp_image_2
        }

        fb_free(); // BBins
        fb_free(); // ABins
        fb_free(); // LBins

        fb_free(); // temp_image
    }
}