[gegl] Matting operations: Unify input and output formats
- From: Daniel Sabo <daniels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] Matting operations: Unify input and output formats
- Date: Wed, 8 May 2013 21:57:34 +0000 (UTC)
commit 558cecea6fa4b5e20bfed72343b01940ef5c357e
Author: Miroslav Talasek <miroslav talasek seznam cz>
Date: Wed May 8 13:23:50 2013 -0700
Matting operations: Unify input and output formats
operations/common/matting-global.c | 89 +++++++++++++++++------------------
operations/external/matting-levin.c | 15 +++++-
2 files changed, 57 insertions(+), 47 deletions(-)
---
diff --git a/operations/common/matting-global.c b/operations/common/matting-global.c
index 802ce0a..b0a68dd 100644
--- a/operations/common/matting-global.c
+++ b/operations/common/matting-global.c
@@ -55,23 +55,17 @@ gegl_chant_int (iterations, _("Iterations"), 1, G_MAXINT, 10,
// Shortcut for doing things in all three channels
#define COLOR(expr) {int c; for (c = 0; c < 3; c++) { expr; }}
-// Save all important memories to output image buffer to save memory
-#define FG_DISTANCE(output, index) (output[index*4+0])
-#define BG_DISTANCE(output, index) (output[index*4+1])
-#define FG_INDEX(output, index) (*((int*)(&output[index*4+2])))
-#define BG_INDEX(output, index) (*((int*)(&output[index*4+3])))
-
/* We don't use the babl_format_get_n_components function for these values,
* as literal constants can be used for stack allocation of array sizes. They
* are double checked in matting_process.
*/
#define COMPONENTS_AUX 1
#define COMPONENTS_INPUT 3
-#define COMPONENTS_OUTPUT 4
+#define COMPONENTS_OUTPUT 1
static const gchar *FORMAT_AUX = "Y u8";
static const gchar *FORMAT_INPUT = "R'G'B' float";
-static const gchar *FORMAT_OUTPUT = "R'G'B'A float";
+static const gchar *FORMAT_OUTPUT = "Y float";
static void
matting_prepare (GeglOperation *operation)
@@ -98,6 +92,13 @@ matting_get_cached_region (GeglOperation * operation,
return *gegl_operation_source_get_bounding_box (operation, "input");
}
+typedef struct {
+ gfloat fg_distance;
+ gfloat bg_distance;
+ gint fg_index;
+ gint bg_index;
+} BufferRecord;
+
typedef float Color[3];
typedef struct {
@@ -169,7 +170,7 @@ static inline float get_cost (ColorSample foreground, ColorSample background, Co
return cost;
}
-static inline void do_propagate(GArray *foreground_samples, GArray *background_samples, gfloat *input,
gfloat *output, guchar *trimap, int x, int y, int w, int h) {
+static inline void do_propagate(GArray *foreground_samples, GArray *background_samples, gfloat *input,
BufferRecord *buffer, guchar *trimap, int x, int y, int w, int h) {
int index_orig = y * w + x;
int index_new;
@@ -177,8 +178,8 @@ static inline void do_propagate(GArray *foreground_samples, GArray *background_s
{
int xdiff, ydiff;
float best_cost = FLT_MAX;
- float *best_fg_distance = &output[index_orig * 4 + 0];
- float *best_bg_distance = &output[index_orig * 4 + 1];
+ float *best_fg_distance = &buffer[index_orig].fg_distance;
+ float *best_bg_distance = &buffer[index_orig].bg_distance;
for (ydiff = -1; ydiff <= 1; ydiff++)
{
@@ -195,8 +196,8 @@ static inline void do_propagate(GArray *foreground_samples, GArray *background_s
if (!(trimap[index_new] == 0 || trimap[index_new] == 255))
{
- int fi = FG_INDEX(output, index_new);
- int bi = BG_INDEX(output, index_new);
+ int fi = buffer[index_new].fg_index;
+ int bi = buffer[index_new].bg_index;
ColorSample foreground = g_array_index(foreground_samples, ColorSample, fi);
ColorSample background = g_array_index(background_samples, ColorSample, bi);
@@ -204,8 +205,8 @@ static inline void do_propagate(GArray *foreground_samples, GArray *background_s
float cost = get_cost(foreground, background, &input[index_orig * 3], x, y,
best_fg_distance, best_bg_distance);
if (cost < best_cost)
{
- FG_INDEX(output, index_orig) = fi;
- BG_INDEX(output, index_orig) = bi;
+ buffer[index_orig].fg_index = fi;
+ buffer[index_orig].bg_index = bi;
best_cost = cost;
}
}
@@ -214,20 +215,20 @@ static inline void do_propagate(GArray *foreground_samples, GArray *background_s
}
}
-static inline void do_random_search(GArray *foreground_samples, GArray *background_samples, gfloat *input,
gfloat *output, int x, int y, int w) {
+static inline void do_random_search(GArray *foreground_samples, GArray *background_samples, gfloat *input,
BufferRecord *buffer, int x, int y, int w) {
int dist_f = foreground_samples->len;
int dist_b = background_samples->len;
int index = y * w + x;
- int best_fi = FG_INDEX(output, index);
- int best_bi = BG_INDEX(output, index);
+ int best_fi = buffer[index].fg_index;
+ int best_bi = buffer[index].bg_index;
int start_fi = best_fi;
int start_bi = best_bi;
// Get current best result
- float *best_fg_distance = &FG_DISTANCE(output, index);
- float *best_bg_distance = &BG_DISTANCE(output, index);
+ float *best_fg_distance = &buffer[index].fg_distance;
+ float *best_bg_distance = &buffer[index].bg_distance;
ColorSample foreground = g_array_index(foreground_samples, ColorSample, best_fi);
ColorSample background = g_array_index(background_samples, ColorSample, best_bi);
@@ -258,8 +259,8 @@ static inline void do_random_search(GArray *foreground_samples, GArray *backgrou
dist_b /= 2;
}
- FG_INDEX(output, index) = best_fi;
- BG_INDEX(output, index) = best_bi;
+ buffer[index].fg_index = best_fi;
+ buffer[index].bg_index = best_bi;
}
// Compare color intensities
@@ -284,9 +285,10 @@ matting_process (GeglOperation *operation,
{
const GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
- gfloat *input = NULL;
- guchar *trimap = NULL;
- gfloat *output = NULL;
+ gfloat *input = NULL;
+ guchar *trimap = NULL;
+ gfloat *output = NULL;
+ BufferRecord *buffer = NULL;
gboolean success = FALSE;
int w, h, i, x, y, xdiff, ydiff, neighbour_mask;
@@ -310,6 +312,7 @@ matting_process (GeglOperation *operation,
input = g_new (gfloat, w * h * COMPONENTS_INPUT);
trimap = g_new (guchar, w * h * COMPONENTS_AUX);
output = g_new0 (gfloat, w * h * COMPONENTS_OUTPUT);
+ buffer = g_new0 (BufferRecord, w * h);
gegl_buffer_get (input_buf, result, 1.0, babl_format (FORMAT_INPUT), input, GEGL_AUTO_ROWSTRIDE,
GEGL_ABYSS_NONE);
gegl_buffer_get ( aux_buf, result, 1.0, babl_format (FORMAT_AUX), trimap, GEGL_AUTO_ROWSTRIDE,
GEGL_ABYSS_NONE);
@@ -348,14 +351,14 @@ matting_process (GeglOperation *operation,
if (mask == 255)
{
g_array_append_val(foreground_samples, s);
- FG_DISTANCE(output, index) = 0;
- BG_DISTANCE(output, index) = FLT_MAX;
+ buffer[index].fg_distance = 0;
+ buffer[index].bg_distance = FLT_MAX;
}
else
{
g_array_append_val(background_samples, s);
- FG_DISTANCE(output, index) = 0;
- BG_DISTANCE(output, index) = FLT_MAX;
+ buffer[index].fg_distance = 0;
+ buffer[index].bg_distance = FLT_MAX;
}
// Go to next pixel
@@ -380,10 +383,10 @@ matting_process (GeglOperation *operation,
p.x = x;
p.y = y;
g_array_append_val(unknown_positions, p);
- FG_DISTANCE(output, index) = FLT_MAX;
- BG_DISTANCE(output, index) = FLT_MAX;
- FG_INDEX(output, index) = rand() % foreground_samples->len;
- BG_INDEX(output, index) = rand() % background_samples->len;
+ buffer[index].fg_distance = FLT_MAX;
+ buffer[index].bg_distance = FLT_MAX;
+ buffer[index].fg_index = rand() % foreground_samples->len;
+ buffer[index].bg_index = rand() % background_samples->len;
}
}
}
@@ -401,13 +404,13 @@ matting_process (GeglOperation *operation,
for (j=0; j<unknown_positions->len; j++)
{
Position p = g_array_index(unknown_positions, Position, j);
- do_random_search(foreground_samples, background_samples, input, output, p.x, p.y, w);
+ do_random_search(foreground_samples, background_samples, input, buffer, p.x, p.y, w);
}
for (j=0; j<unknown_positions->len; j++)
{
Position p = g_array_index(unknown_positions, Position, j);
- do_propagate(foreground_samples, background_samples, input, output, trimap, p.x, p.y, w, h);
+ do_propagate(foreground_samples, background_samples, input, buffer, trimap, p.x, p.y, w, h);
}
}
@@ -419,29 +422,24 @@ matting_process (GeglOperation *operation,
int index = y * w + x;
if (trimap[index] == 0 || trimap[index] == 255)
{
- // Use known values
- output[index * 4 + 0] = input[index * 3 + 0];
- output[index * 4 + 1] = input[index * 3 + 1];
- output[index * 4 + 2] = input[index * 3 + 2];
if (trimap[index] == 0)
{
- output[index * 4 + 3] = 0;
+ output[index] = 0;
}
else if (trimap[index] == 255)
{
- output[index * 4 + 3] = 1;
+ output[index] = 1;
}
}
else
{
ColorSample background, foreground;
- foreground = g_array_index(foreground_samples, ColorSample, FG_INDEX(output, index));
- background = g_array_index(background_samples, ColorSample, BG_INDEX(output, index));
+ foreground = g_array_index(foreground_samples, ColorSample, buffer[index].fg_index);
+ background = g_array_index(background_samples, ColorSample, buffer[index].bg_index);
- output[index * 4 + 3] = get_alpha(foreground.color, background.color, &input[index * 3]);
+ output[index] = get_alpha(foreground.color, background.color, &input[index * 3]);
- COLOR(output[index * 4 + c] = foreground.color[c]);
}
}
}
@@ -455,6 +453,7 @@ matting_process (GeglOperation *operation,
g_free (input);
g_free (trimap);
g_free (output);
+ g_free (buffer);
g_array_free(foreground_samples, FALSE);
g_array_free(background_samples, FALSE);
g_array_free(unknown_positions, FALSE);
diff --git a/operations/external/matting-levin.c b/operations/external/matting-levin.c
index 9add013..786eab0 100644
--- a/operations/external/matting-levin.c
+++ b/operations/external/matting-levin.c
@@ -105,8 +105,10 @@ static const gchar *FORMAT_AUX = "Y'A double";
static const gchar *FORMAT_INPUT = "R'G'B' double";
static const gchar *FORMAT_OUTPUT = "Y' double";
-static const guint AUX_VALUE = 0;
-static const guint AUX_ALPHA = 1;
+static const guint AUX_VALUE = 0;
+static const guint AUX_ALPHA = 1;
+static const gdouble AUX_BACKGROUND = 0.1;
+static const gdouble AUX_FOREGROUND = 0.9;
/* Threshold below which we consider the Y channel to be undefined (or
@@ -1267,6 +1269,15 @@ matting_solve_level (gdouble *restrict pixels,
gint i;
gdouble *new_alpha = NULL,
*eroded_alpha = NULL;
+ gdouble value;
+
+ /* add alpha to trimap because algo is need it */
+ for (i = 0; i < region->width * region->height; ++i)
+ {
+ value = trimap[i * COMPONENTS_AUX + AUX_VALUE];
+ if (value > AUX_BACKGROUND && value < AUX_FOREGROUND)
+ trimap[i * COMPONENTS_AUX + AUX_ALPHA] = 0.0;
+ }
if (region->width < MIN_LEVEL_DIAMETER ||
region->height < MIN_LEVEL_DIAMETER)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]