diff --git a/data/darktableconfig.xml.in b/data/darktableconfig.xml.in
index df6abf21d852..daf3111dadeb 100644
--- a/data/darktableconfig.xml.in
+++ b/data/darktableconfig.xml.in
@@ -3586,27 +3586,6 @@
AI mask binarization threshold
sigmoid threshold for converting AI mask to binary. higher values (0.6-0.7) tighten boundaries, lower values include more area.
-
- plugins/darkroom/masks/object/morph_radius
- int
- 3
- AI mask morphological cleanup radius
- radius of structuring element for morphological open+close cleanup. removes small protrusions and fills small holes in the mask. 0 = disabled, 1-3 = typical values.
-
-
- plugins/darkroom/masks/object/guided_radius
- int
- 5
- AI mask guided filter radius
- radius of the guided filter used to snap the mask boundary to image edges. larger values produce smoother boundaries. 0 = disabled.
-
-
- plugins/darkroom/masks/object/guided_eps
- float
- 0.01
- AI mask guided filter edge sensitivity
- edge sensitivity for the guided filter. smaller values preserve finer edges. 0.001 = very sharp, 0.1 = soft, 1.0 = nearly no edge preservation.
-
plugins/darkroom/masks/object/render_size
int
diff --git a/src/develop/masks/object.c b/src/develop/masks/object.c
index 191e0b8eea8e..9ca6ec036493 100644
--- a/src/develop/masks/object.c
+++ b/src/develop/masks/object.c
@@ -20,7 +20,6 @@
#include "common/ai_models.h"
#include "common/colorspaces.h"
#include "common/debug.h"
-#include "common/guided_filter.h"
#include "common/mipmap_cache.h"
#include "common/ras2vect.h"
#include "control/conf.h"
@@ -40,9 +39,6 @@
#define CONF_OBJECT_MODEL_KEY "plugins/darkroom/masks/object/model"
#define CONF_OBJECT_THRESHOLD_KEY "plugins/darkroom/masks/object/threshold"
#define CONF_OBJECT_REFINE_KEY "plugins/darkroom/masks/object/refine_passes"
-#define CONF_OBJECT_MORPH_KEY "plugins/darkroom/masks/object/morph_radius"
-#define CONF_OBJECT_GUIDED_RADIUS_KEY "plugins/darkroom/masks/object/guided_radius"
-#define CONF_OBJECT_GUIDED_EPS_KEY "plugins/darkroom/masks/object/guided_eps"
#define CONF_OBJECT_CLEANUP_KEY "plugins/darkroom/masks/object/cleanup"
#define CONF_OBJECT_SMOOTHING_KEY "plugins/darkroom/masks/object/smoothing"
#define CONF_OBJECT_FEATHER_KEY "plugins/darkroom/masks/object/feather"
@@ -535,149 +531,6 @@ static void _keep_seed_component(float *mask,
g_free(labels);
}
-// morphological erode: output pixel is 1 only if all pixels in the
-// square structuring element of given radius are 1
-static void _morph_erode(const uint8_t *src,
- uint8_t *dst,
- const int w,
- const int h,
- const int radius)
-{
- for(int y = 0; y < h; y++)
- {
- const int y0 = MAX(y - radius, 0);
- const int y1 = MIN(y + radius, h - 1);
- for(int x = 0; x < w; x++)
- {
- const int x0 = MAX(x - radius, 0);
- const int x1 = MIN(x + radius, w - 1);
- uint8_t val = 1;
- for(int ny = y0; ny <= y1 && val; ny++)
- for(int nx = x0; nx <= x1 && val; nx++)
- if(!src[ny * w + nx]) val = 0;
- dst[y * w + x] = val;
- }
- }
-}
-
-// morphological dilate: output pixel is 1 if any pixel in the
-// square structuring element of given radius is 1
-static void _morph_dilate(const uint8_t *src,
- uint8_t *dst,
- const int w,
- const int h,
- const int radius)
-{
- for(int y = 0; y < h; y++)
- {
- const int y0 = MAX(y - radius, 0);
- const int y1 = MIN(y + radius, h - 1);
- for(int x = 0; x < w; x++)
- {
- const int x0 = MAX(x - radius, 0);
- const int x1 = MIN(x + radius, w - 1);
- uint8_t val = 0;
- for(int ny = y0; ny <= y1 && !val; ny++)
- for(int nx = x0; nx <= x1 && !val; nx++)
- if(src[ny * w + nx]) val = 1;
- dst[y * w + x] = val;
- }
- }
-}
-
-// morphological open+close on a float mask,
-// open (erode->dilate) removes small protrusions/bridges,
-// close (dilate->erode) fills small holes/gaps
-static void _morph_open_close(float *mask,
- const int w,
- const int h,
- const float threshold,
- const int radius)
-{
- if(radius <= 0) return;
-
- const size_t n = (size_t)w * h;
- uint8_t *bin = g_try_malloc(n);
- uint8_t *tmp = g_try_malloc(n);
- if(!bin || !tmp)
- {
- g_free(bin);
- g_free(tmp);
- return;
- }
-
- // binarize
- for(size_t i = 0; i < n; i++)
- bin[i] = mask[i] > threshold ? 1 : 0;
-
- // open: erode into tmp, then dilate back into bin
- _morph_erode(bin, tmp, w, h, radius);
- _morph_dilate(tmp, bin, w, h, radius);
-
- // close: dilate into tmp, then erode back into bin
- _morph_dilate(bin, tmp, w, h, radius);
- _morph_erode(tmp, bin, w, h, radius);
-
- // apply result back to float mask
- for(size_t i = 0; i < n; i++)
- {
- if(bin[i] && mask[i] <= threshold)
- mask[i] = 1.0f; // filled by close
- else if(!bin[i] && mask[i] > threshold)
- mask[i] = 0.0f; // removed by open
- }
-
- g_free(bin);
- g_free(tmp);
-}
-
-// edge-aware mask refinement using guided filter: smooths the mask in
-// flat regions while preserving sharp transitions at image edges.
-// the stored RGB image is used as the guide
-static void _guided_filter_refine(float *mask,
- const int mw,
- const int mh,
- const uint8_t *rgb,
- const int rgb_w,
- const int rgb_h,
- const int radius,
- const float sqrt_eps)
-{
- if(!rgb || rgb_w < 3 || rgb_h < 3)
- return;
- if(mw != rgb_w || mh != rgb_h)
- return;
-
- const size_t npix = (size_t)mw * mh;
-
- // convert uint8 RGB to float RGBA guide (guided_filter expects 4ch)
- float *guide = dt_alloc_align_float(npix * 4);
- if(!guide) return;
-
- for(size_t i = 0; i < npix; i++)
- {
- guide[i * 4 + 0] = (float)rgb[i * 3 + 0] / 255.0f;
- guide[i * 4 + 1] = (float)rgb[i * 3 + 1] / 255.0f;
- guide[i * 4 + 2] = (float)rgb[i * 3 + 2] / 255.0f;
- guide[i * 4 + 3] = 0.0f;
- }
-
- // run guided filter: smooths mask but preserves edges from the guide
- float *mask_bak = dt_alloc_align_float(npix);
- if(!mask_bak)
- {
- dt_free_align(guide);
- return;
- }
-
- memcpy(mask_bak, mask, npix * sizeof(float));
- guided_filter(guide, mask_bak, mask, mw, mh, 4,
- radius, sqrt_eps, 1.0f, 0.0f, 1.0f);
-
- dt_free_align(mask_bak);
- dt_free_align(guide);
-}
-
// run the decoder with accumulated points and update the cached mask
static void _run_decoder(dt_masks_form_gui_t *gui)
{
@@ -760,22 +613,8 @@ static void _run_decoder(dt_masks_form_gui_t *gui)
const float threshold = CLAMP(dt_conf_get_float(CONF_OBJECT_THRESHOLD_KEY),
0.3f, 0.9f);
- // guided filter edge refinement: snap mask boundary to image edges
- const int gf_radius = CLAMP(dt_conf_get_int(CONF_OBJECT_GUIDED_RADIUS_KEY),
- 0, 20);
- const float gf_eps = CLAMP(dt_conf_get_float(CONF_OBJECT_GUIDED_EPS_KEY),
- 0.001f, 1.0f);
- if(gf_radius > 0 && d->encode_rgb)
- _guided_filter_refine(mask, mw, mh,
- d->encode_rgb, d->encode_rgb_w, d->encode_rgb_h,
- gf_radius, sqrtf(gf_eps));
-
_keep_seed_component(mask, mw, mh, threshold, seed_x, seed_y);
- // morphological open+close to remove small protrusions and fill holes
- const int morph_radius = CLAMP(dt_conf_get_int(CONF_OBJECT_MORPH_KEY), 0, 5);
- _morph_open_close(mask, mw, mh, threshold, morph_radius);
-
g_free(d->mask);
d->mask = mask;
d->mask_w = mw;