[gegl] alpha-inpaint: search on demand in vicinity of current search spot
- From: Øyvind "pippin" Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] alpha-inpaint: search on demand in vicinity of current search spot
- Date: Wed, 3 Jul 2019 14:00:59 +0000 (UTC)
commit a9b9fe8a2e4286231fc62e174ae40fe4cc9b9832
Author: Øyvind Kolås <pippin gimp org>
Date: Wed Jul 3 13:38:58 2019 +0200
alpha-inpaint: search on demand in vicinity of current search spot
One big performance improvement in this commit is moving the needles
to the stack.
operations/workshop/inpaint.c | 11 +-
operations/workshop/pixel-duster.h | 314 ++++++++++++++-----------------------
2 files changed, 125 insertions(+), 200 deletions(-)
---
diff --git a/operations/workshop/inpaint.c b/operations/workshop/inpaint.c
index a3a6b486a..a9307d5d9 100644
--- a/operations/workshop/inpaint.c
+++ b/operations/workshop/inpaint.c
@@ -27,10 +27,10 @@
#ifdef GEGL_PROPERTIES
-property_int (seek_distance, "seek radius", 30)
- value_range (4, 512)
+property_int (seek_distance, "seek radius", 5)
+ value_range (1, 512)
-property_int (min_neigh, "min neigh", 2)
+property_int (min_neigh, "min neigh", 3)
value_range (0, 4)
property_int (min_iter, "min iter", 100)
@@ -41,9 +41,6 @@ property_int (max_iter, "max iter", 2000)
property_int (improvement_iters, "improvement iters", 2)
-property_int (k, "k", 3)
- value_range (1, 8)
-
property_double (chance_try, "try chance", 0.33)
value_range (0.0, 1.0)
ui_steps (0.01, 0.1)
@@ -165,7 +162,6 @@ process (GeglOperation *operation,
GeglRectangle out_rect = *gegl_buffer_get_extent (output);
PixelDuster *duster = pixel_duster_new (input, input, output, &in_rect, &out_rect,
o->seek_distance,
- o->k, // max_k
o->min_neigh,
o->min_iter,
o->max_iter,
@@ -194,7 +190,6 @@ process (GeglOperation *operation,
pixel_duster_add_probes_for_transparent (duster);
- seed_db (duster);
pixel_duster_fill (duster);
pixel_duster_destroy (duster);
diff --git a/operations/workshop/pixel-duster.h b/operations/workshop/pixel-duster.h
index c778ddde0..d9e4f52eb 100644
--- a/operations/workshop/pixel-duster.h
+++ b/operations/workshop/pixel-duster.h
@@ -50,7 +50,6 @@ typedef struct
GeglSampler *in_sampler_f;
GeglSampler *ref_sampler_f;
GeglSampler *out_sampler_f;
- int max_k;
int seek_radius;
int minimum_neighbors;
int minimum_iterations;
@@ -86,30 +85,30 @@ typedef struct
} PixelDuster;
-#define MAX_K 8
-
#define RINGS 3 // increments works up to 7-8 with no adver
#define RAYS 12 // good values for testing 6 8 10 12 16
#define NEIGHBORHOOD (RINGS*RAYS+1)
-#define N_SCALE_NEEDLES 1
+#define N_SCALE_NEEDLES 3
+#define DIRECTION_INVARIANT // uncomment to make search be direction dependent
typedef struct _Probe Probe;
+
+typedef float needles_t[N_SCALE_NEEDLES][4 * NEIGHBORHOOD ];// should be on stack
+
+
struct _Probe {
- float needles[N_SCALE_NEEDLES][4 * NEIGHBORHOOD ];
int target_x;
int target_y;
- int target_neighbors;
- int age;
- int k;
+ Probe *neighbors[8]; // cached from coords and iterating all
+ int target_neighbors; // cached computation
+ int age; // not really needed
+ float old_score; // should be on stack
float score;
- float old_score;
- Probe *neighbors[8]; // first the 4 connected, then the rest of 8 connected
- float source_x[MAX_K];
- float source_y[MAX_K];
- gfloat *hay[MAX_K];
+ int source_x;
+ int source_y;
};
/* used for hash-table keys */
@@ -169,7 +168,6 @@ static PixelDuster * pixel_duster_new (GeglBuffer *reference,
const GeglRectangle *in_rect,
const GeglRectangle *out_rect,
int seek_radius,
- int max_k,
int minimum_neighbors,
int minimum_iterations,
int maximum_iterations,
@@ -216,9 +214,6 @@ static PixelDuster * pixel_duster_new (GeglBuffer *reference,
ret->ring_gamma = ring_gamma;
ret->ring_twist = ring_twist;
- if (max_k < 1) max_k = 1;
- if (max_k > MAX_K) max_k = MAX_K;
- ret->max_k = max_k;
ret->in_rect = *in_rect;
ret->out_rect = *out_rect;
ret->scale_x = scale_x;
@@ -280,9 +275,7 @@ void gegl_sampler_prepare (GeglSampler *sampler);
static void extract_site (PixelDuster *duster, GeglBuffer *buffer, double x, double y, float scale, gfloat
*dst)
{
static const Babl *format = NULL;
-
GeglSampler *sampler_f;
-
if (buffer == duster->output)
{
sampler_f = duster->out_sampler_f;
@@ -301,7 +294,6 @@ static void extract_site (PixelDuster *duster, GeglBuffer *buffer, double x, dou
format = babl_format ("RGBA float");
}
-#if 1
for (int i = 0; i < NEIGHBORHOOD; i++)
{
int dx, dy;
@@ -309,6 +301,7 @@ static void extract_site (PixelDuster *duster, GeglBuffer *buffer, double x, dou
gegl_sampler_get (sampler_f, x + dx * scale, y + dy * scale, NULL, &dst[i*4], 0);
}
+#ifdef DIRECTION_INVARIANT
{
int warmest_ray = 0;
float warmest_ray_energy = 0;
@@ -407,21 +400,21 @@ score_site (PixelDuster *duster,
}
{
- float sum_x = probe->source_x[0];
- float sum_y = probe->source_y[0];
+ float sum_x = probe->source_x;
+ float sum_y = probe->source_y;
int count = 1;
for (int i = 0; i < 8; i++)
if (probe->neighbors[i])
{
- sum_x += probe->neighbors[i]->source_x[0];
- sum_y += probe->neighbors[i]->source_y[0];
+ sum_x += probe->neighbors[i]->source_x;
+ sum_y += probe->neighbors[i]->source_y;
count++;
}
sum_x /= count;
sum_y /= count;
- score += (POW2(sum_x - probe->source_x[0]) +
- POW2(sum_y - probe->source_y[0])) * duster->metric_cohesion;
+ score += (POW2(sum_x - probe->source_x) +
+ POW2(sum_y - probe->source_y)) * duster->metric_cohesion;
}
score = sqrtf (score);
@@ -443,9 +436,8 @@ add_probe (PixelDuster *duster, int target_x, int target_y)
probe->target_x = target_x;
probe->target_y = target_y;
- probe->source_x[0] = target_x / duster->scale_x;
- probe->source_y[0] = target_y / duster->scale_y;
- probe->k = 0;
+ probe->source_x = target_x / duster->scale_x;
+ probe->source_y = target_y / duster->scale_y;
probe->score = INITIAL_SCORE;
g_hash_table_insert (duster->probes_ht,
xy2offset(target_x, target_y), probe);
@@ -472,16 +464,6 @@ probe_rel_is_set (PixelDuster *duster, GeglBuffer *output, Probe *probe, int rel
static inline void probe_push (PixelDuster *duster, Probe *probe)
{
- int j;
- for (j = duster->max_k-1; j >= 1; j --)
- {
- probe->source_x[j] = probe->source_x[j-1];
- probe->source_y[j] = probe->source_y[j-1];
- probe->hay[j] = probe->hay[j-1];
- }
- probe->k++;
- if (probe->k > duster->max_k)
- probe->k = duster->max_k;
}
@@ -534,25 +516,36 @@ static gfloat *ensure_hay (PixelDuster *duster, int x, int y)
return hay;
}
+
+static float
+probe_score (PixelDuster *duster,
+ Probe *probe,
+ needles_t needles,
+ int x,
+ int y,
+ gfloat *hay,
+ float bail);
+
static inline void
probe_prep (PixelDuster *duster,
- Probe *probe)
+ Probe *probe,
+ needles_t needles)
{
gint dst_x = probe->target_x;
gint dst_y = probe->target_y;
- extract_site (duster, duster->output, dst_x, dst_y, 1.0, &probe->needles[0][0]);
+ extract_site (duster, duster->output, dst_x, dst_y, 1.0, &needles[0][0]);
if (N_SCALE_NEEDLES > 1)
- extract_site (duster, duster->output, dst_x, dst_y, 0.9, &probe->needles[1][0]);
+ extract_site (duster, duster->output, dst_x, dst_y, 0.82, &needles[1][0]);
if (N_SCALE_NEEDLES > 2)
- extract_site (duster, duster->output, dst_x, dst_y, 1.1, &probe->needles[2][0]);
+ extract_site (duster, duster->output, dst_x, dst_y, 1.2, &needles[2][0]);
if (N_SCALE_NEEDLES > 3)
- extract_site (duster, duster->output, dst_x, dst_y, 0.8, &probe->needles[3][0]);
+ extract_site (duster, duster->output, dst_x, dst_y, 0.66, &needles[3][0]);
if (N_SCALE_NEEDLES > 4)
- extract_site (duster, duster->output, dst_x, dst_y, 1.2, &probe->needles[4][0]);
+ extract_site (duster, duster->output, dst_x, dst_y, 1.5, &needles[4][0]);
if (N_SCALE_NEEDLES > 5)
- extract_site (duster, duster->output, dst_x, dst_y, 0.66, &probe->needles[5][0]);
+ extract_site (duster, duster->output, dst_x, dst_y, 2.0,&needles[5][0]);
if (N_SCALE_NEEDLES > 6)
- extract_site (duster, duster->output, dst_x, dst_y, 1.5, &probe->needles[6][0]);
+ extract_site (duster, duster->output, dst_x, dst_y, 0.5, &needles[6][0]);
probe->old_score = probe->score;
{
@@ -593,71 +586,38 @@ probe_prep (PixelDuster *duster,
}
- if (probe->score == INITIAL_SCORE)
- {
-
- }
-
-}
-
-static void probe_compare_hay (PixelDuster *duster,
- Probe *probe,
- gfloat *hay,
- gint x, gint y)
-{
-
- float score;
-
-#define pow2(a) ((a)*(a))
-
- if ( duster->seek_radius > 1 &&
- pow2 (probe->target_x / duster->scale_x - x) +
- pow2 (probe->target_y / duster->scale_y - y) >
- pow2 (duster->seek_radius))
-#if 0
- if (duster->scale_x == 1.0 && x == probe->target_x &&
-- duster->scale_y == 1.0 && y == probe->target_y )
- return;
-#endif
- {
- }
- else
+ if(1)for (int i = 0; i < 4; i++)
{
- for (int n = 0; n < N_SCALE_NEEDLES; n++)
+ if (probe->neighbors[i])
{
- score = score_site (duster, probe, x, y, &probe->needles[n][0], hay, probe->score);
-
- if (score < probe->score)
+ Probe *oprobe = probe->neighbors[i];
+ int coords[8][2]={{-1,0},
+ {1,0},
+ {0,1},
+ {0,-1},
+ {-1,-1},
+ {1,1},
+ {-1,1},
+ {1,-1} };
+ for (int c = 0; c < 8; c++)
{
- probe_push (duster, probe);
- probe->source_x[0] = x;
- probe->source_y[0] = y;
- probe->hay[0] = hay;
- probe->score = score;
+ float test_x = oprobe->source_x + coords[c][0];
+ float test_y = oprobe->source_y + coords[c][1];
+ float *hay = ensure_hay (duster, test_x, test_y);
+ float score = probe_score (duster, probe, needles, test_x, test_y, hay, probe->score);
+ if (score <= probe->score)
+ {
+ probe_push (duster, probe);
+ probe->source_x = test_x;
+ probe->source_y = test_y;
+ probe->score = score;
+ //probe_update_target (duster, probe);
+ }
}
}
-
- /* XXX : incorporate distance to average destination of 4 connected
- neighborhoods source coordinates.. */
- {
- }
-
}
}
-static void compare_needle (gpointer key, gpointer value, gpointer data)
-{
- void **ptr = data;
- PixelDuster *duster = ptr[0];
- Probe *probe = ptr[1];
- gfloat *hay = value;
- gint offset = GPOINTER_TO_INT (key);
- gint x = offset % 65536;
- gint y = offset / 65536;
-
- probe_compare_hay (duster, probe, hay, x, y);
-}
-
static void
probe_post_search (PixelDuster *duster, Probe *probe)
{
@@ -668,28 +628,11 @@ probe_post_search (PixelDuster *duster, Probe *probe)
if (probe->score != probe->old_score)
{
- gfloat sum_rgba[4]={0.0,0.0,0.0,0.0};
gfloat rgba[4];
- if (probe->k>1)
- {
- for (gint i = 0; i < probe->k; i++)
- {
- gegl_sampler_get (duster->in_sampler_f,
- probe->source_x[i], probe->source_y[i],
- NULL, &rgba[0], 0);
- for (gint c = 0; c < 4; c++)
- sum_rgba[c] += rgba[c];
- }
- for (gint c = 0; c < 4; c++)
- rgba[c] = sum_rgba[c] / probe->k;
- }
- else
- {
- gegl_sampler_get (duster->in_sampler_f,
- probe->source_x[0], probe->source_y[0], NULL,
- &rgba[0], 0);
- }
+ gegl_sampler_get (duster->in_sampler_f,
+ probe->source_x, probe->source_y, NULL,
+ &rgba[0], 0);
gegl_buffer_set (duster->output,
GEGL_RECTANGLE(probe->target_x, probe->target_y, 1, 1),
@@ -697,10 +640,40 @@ probe_post_search (PixelDuster *duster, Probe *probe)
}
}
+
+static float
+probe_score (PixelDuster *duster,
+ Probe *probe,
+ needles_t needles,
+ int x,
+ int y,
+ gfloat *hay,
+ float bail)
+{
+ float best_score = 10000000.0;
+ /* bail early with really bad score - the target site doesnt have opacity */
+
+ if (hay[3] < 0.001f)
+ {
+ return INITIAL_SCORE;
+ }
+
+ for (int n = 0; n < N_SCALE_NEEDLES; n++)
+ {
+ float score = score_site (duster, probe, x, y, &needles[n][0], hay, bail);
+ if (score < best_score)
+ best_score = score;
+ }
+
+ return best_score;
+}
+
+
static int probe_improve (PixelDuster *duster,
Probe *probe)
{
- void *ptr[2] = {duster, probe};
+ needles_t needles;
+ //void *ptr[2] = {duster, probe};
static const Babl *format = NULL;
if (probe->age >= duster->max_age)
@@ -713,36 +686,37 @@ static int probe_improve (PixelDuster *duster,
if (!format)
format = babl_format ("RGBA float");
- probe_prep (duster, probe);
+ probe_prep (duster, probe, needles);
+
+ {
+ float iter_start_x = probe->source_x;
+ float iter_start_y = probe->source_y;
+ for (int dx = -duster->seek_radius; dx < duster->seek_radius; dx++)
+ for (int dy = -duster->seek_radius; dy < duster->seek_radius; dy++)
+ if (!(dx == 0 && dy == 0))
+ {
+ int test_x = iter_start_x + dx;
+ int test_y = iter_start_y + dy;
+ float *hay = ensure_hay (duster, test_x, test_y);
+ float score = probe_score (duster, probe, needles, test_x, test_y, hay, probe->score);
+ if (score < probe->score)
+ {
+ probe_push (duster, probe);
+
+ probe->source_x = test_x;
+ probe->source_y = test_y;
+ probe->score = score;
+ //probe_update_target (duster, probe);
+ }
+ }
+ }
- g_hash_table_foreach (duster->ht[0], compare_needle, ptr);
probe_post_search (duster, probe);
return 0;
}
-static inline void compare_probes (gpointer key, gpointer value, gpointer data)
-{
- void **ptr = data;
- PixelDuster *duster = ptr[0];
- Probe **probes = ptr[1];
- int n_probes = GPOINTER_TO_INT (ptr[2]);
- gfloat *hay = value;
- gint offset = GPOINTER_TO_INT (key);
- gint x = offset % 65536;
- gint y = offset / 65536;
-
- for (int p = 0; p < n_probes; p++)
- if (probes[p])
- {
- Probe *probe = probes[p];
- if (probe)
- probe_compare_hay (duster, probe, hay, x, y);
- }
-}
-
-
static inline int probes_improve (PixelDuster *duster,
Probe **probes,
int n_probes)
@@ -853,47 +827,3 @@ static inline void pixel_duster_fill (PixelDuster *duster)
fprintf (stderr, "\n");
#endif
}
-
-static void seed_db (PixelDuster *duster)
-{
- fprintf (stderr, "db seed");
-
- if (duster->max_x > duster->min_x)
- {
- fprintf (stderr, "ing");
- for (gint y = duster->min_y - duster->seek_radius;
- y < duster->max_y + duster->seek_radius; y++)
- {
- for (gint x = duster->min_x - duster->seek_radius;
- x < duster->max_x + duster->seek_radius; x++)
- {
- ensure_hay (duster, x, y);
- }
-
-
- if (y % 13 == 0)
- {
- if (duster->op)
- gegl_operation_progress (duster->op,
-
- (y - duster->min_y + duster->seek_radius) * 0.2 / (duster->seek_radius * 2 +
duster->max_y-duster->min_y),
- "generating neighborhood db");
-
-
- fprintf (stderr, "\rdb seeding %s (%.2f%%)", y%4==0?"-":y%4==1?"/":y%4==2?"\\":"|",
- (y - duster->min_y + duster->seek_radius) * 100.0 / (duster->seek_radius * 2 +
duster->max_y-duster->min_y));
- }
- }
- fprintf (stderr, "\rdb seeded \n");
- }
- else
- {
-
- for (gint y = 0; y < duster->in_rect.height; y++)
- for (gint x = 0; x < duster->in_rect.width; x++)
- {
- ensure_hay (duster, x, y);
- }
- fprintf (stderr, "ed\n");
- }
-}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]