[gegl] workshop: add max iterations and cohesion parameters
- From: Øyvind "pippin" Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] workshop: add max iterations and cohesion parameters
- Date: Tue, 2 Jul 2019 13:42:57 +0000 (UTC)
commit 29acb1dd4a6b60808004fd0d61d9b44b21537bcf
Author: Øyvind Kolås <pippin gimp org>
Date: Tue Jul 2 15:08:55 2019 +0200
workshop: add max iterations and cohesion parameters
The coehsion is implemented by taking the difference average of the
neighborhood of probes source neighborhood's average sampling location and
the probes sampling position.
Max iterations avoids infinite loops in the cases where pixels are not
being filled in at all.
Also expose indivdual ring radiuses, that when non 0 are taken directly
as the radius for that ring
operations/workshop/inpaint.c | 54 +++++++++++++++++-----
operations/workshop/pixel-duster.h | 91 +++++++++++++++++++++++++++++++++-----
2 files changed, 122 insertions(+), 23 deletions(-)
---
diff --git a/operations/workshop/inpaint.c b/operations/workshop/inpaint.c
index 3f23aa57f..7a7f41b7f 100644
--- a/operations/workshop/inpaint.c
+++ b/operations/workshop/inpaint.c
@@ -29,40 +29,66 @@
property_int (seek_distance, "seek radius", 30)
value_range (4, 512)
-property_int (min_neigh, "min neigh", 4)
- value_range (1, 4)
+property_int (min_neigh, "min neigh", 3)
+ value_range (0, 4)
property_int (min_iter, "min iter", 100)
value_range (1, 512)
+property_int (max_iter, "max iter", 2000)
+ value_range (1, 40000)
+
property_int (improvement_iters, "improvement iters", 3)
- value_range (1, 30)
+ value_range (0, 30)
-property_double (chance_try, "try chance", 0.75)
+property_double (chance_try, "try chance", 0.5)
value_range (0.0, 1.0)
ui_steps (0.01, 0.1)
-property_double (chance_retry, "retry chance", 0.8)
+property_double (chance_retry, "retry chance", 1.0)
value_range (0.0, 1.0)
ui_steps (0.01, 0.1)
-property_double (ring_gap, "ring gap", 1.25)
- value_range (0.0, 4.0)
+property_double (ring_gap, "ring gap", 1.3)
+ value_range (0.0, 8.0)
ui_steps (0.1, 0.2)
-property_double (ring_gamma, "ring gamma", 1.2)
+
+property_double (ring_gamma, "ring gamma", 1.4)
value_range (0.0, 4.0)
ui_steps (0.1, 0.2)
-property_double (ring_twist, "ring twist", 0.040)
+property_double (ring_twist, "ring twist", 0.10)
value_range (0.0, 1.0)
ui_steps (0.01, 0.2)
-property_double (metric_dist_powk, "metric dist powk", 1.35)
+property_double (ring_gap1, "ring gap1", 1.5)
+ value_range (0.0, 8.0)
+ ui_steps (0.25, 0.25)
+
+property_double (ring_gap2, "ring gap2", 2.5)
+ value_range (0.0, 8.0)
+ ui_steps (0.25, 0.25)
+
+property_double (ring_gap3, "ring gap3", 3.5)
+ value_range (0.0, 8.0)
+ ui_steps (0.25, 0.25)
+
+property_double (ring_gap4, "ring gap4", 4.5)
+ value_range (0.0, 8.0)
+ ui_steps (0.25, 0.25)
+
+property_double (metric_dist_powk, "metric dist powk", 2.0)
value_range (0.0, 10.0)
ui_steps (0.1, 1.0)
-property_double (metric_empty_score, "metric empty score", 0.05)
+property_double (metric_empty_score, "metric empty score", 0.07)
value_range (0.01, 100.0)
ui_steps (0.05, 0.1)
+property_double (metric_cohesion, "metric cohesion", 0.005)
+ value_range (0.0, 10.0)
+ ui_steps (0.2, 0.2)
+
+
+
#else
#define GEGL_OP_FILTER
@@ -109,16 +135,22 @@ process (GeglOperation *operation,
1, // max_k
o->min_neigh,
o->min_iter,
+ o->max_iter,
o->chance_try,
o->chance_retry,
1.0, // scale_x
1.0, // scale_y
o->improvement_iters,
o->ring_gap,
+ o->ring_gap1,
+ o->ring_gap2,
+ o->ring_gap3,
+ o->ring_gap4,
o->ring_gamma,
o->ring_twist,
o->metric_dist_powk,
o->metric_empty_score,
+ o->metric_cohesion/1000.0,
operation);
gegl_buffer_copy (input, NULL, GEGL_ABYSS_NONE, output, NULL);
pixel_duster_add_probes_for_transparent (duster);
diff --git a/operations/workshop/pixel-duster.h b/operations/workshop/pixel-duster.h
index 546c0c9ad..499116c76 100644
--- a/operations/workshop/pixel-duster.h
+++ b/operations/workshop/pixel-duster.h
@@ -54,6 +54,7 @@ typedef struct
int seek_radius;
int minimum_neighbors;
int minimum_iterations;
+ int maximum_iterations;
int max_age;
float try_chance;
float retry_chance;
@@ -61,11 +62,15 @@ typedef struct
float scale_y;
float ring_gap;
+ float ring_gaps[8];
+
+
float ring_gamma;
float ring_twist;
float metric_dist_powk;
float metric_empty_score;
+ float metric_cohesion;
GHashTable *ht[1];
@@ -83,10 +88,10 @@ typedef struct
#define MAX_K 4
#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 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 BATCH_PROBES 64 // batch this many probes to process concurently
@@ -104,7 +109,7 @@ struct _Probe {
int k;
float score;
float old_score;
- Probe *neighbors[4];
+ Probe *neighbors[8]; // first the 4 connected, then the rest of 8 connected
float k_score[MAX_K];
float source_x[MAX_K];
float source_y[MAX_K];
@@ -135,12 +140,18 @@ static void init_order(PixelDuster *duster)
i = 1;
{
- for (int circleno = 0; circleno < RINGS; circleno++)
+ for (int circleno = 1; circleno < RINGS; circleno++)
for (float angleno = 0; angleno < RAYS; angleno++)
{
- float mag = pow(duster->ring_gap * (circleno + 1), duster->ring_gamma);
- float x = cosf ((angleno / RAYS + duster->ring_twist*circleno) * M_PI * 2) * mag;
- float y = sinf ((angleno / RAYS + duster->ring_twist*circleno) * M_PI * 2) * mag;
+ float mag;
+ float x, y;
+ if (duster->ring_gaps[circleno] > 0.0)
+ mag = duster->ring_gaps[circleno];
+ else
+ mag = pow(duster->ring_gap * (circleno + 1), duster->ring_gamma);
+
+ x = cosf ((angleno / RAYS + duster->ring_twist*circleno) * M_PI * 2) * mag;
+ y = sinf ((angleno / RAYS + duster->ring_twist*circleno) * M_PI * 2) * mag;
duster->order[i][0] = x;
duster->order[i][1] = y;
duster->order[i][2] = powf (1.0 / (POW2(x)+POW2(y)), duster->metric_dist_powk);
@@ -165,16 +176,23 @@ static PixelDuster * pixel_duster_new (GeglBuffer *reference,
int max_k,
int minimum_neighbors,
int minimum_iterations,
+ int maximum_iterations,
float try_chance,
float retry_chance,
float scale_x,
float scale_y,
int improvement_iterations,
float ring_gap,
+ float ring_gap1,
+ float ring_gap2,
+ float ring_gap3,
+ float ring_gap4,
float ring_gamma,
float ring_twist,
float metric_dist_powk,
float metric_empty_score,
+ float metric_cohesion,
+
GeglOperation *op)
{
PixelDuster *ret = g_malloc0 (sizeof (PixelDuster));
@@ -184,9 +202,14 @@ static PixelDuster * pixel_duster_new (GeglBuffer *reference,
ret->seek_radius = seek_radius;
ret->minimum_neighbors = minimum_neighbors;
ret->minimum_iterations = minimum_iterations;
+ ret->maximum_iterations = maximum_iterations;
ret->try_chance = try_chance;
ret->retry_chance = retry_chance;
ret->op = op;
+ ret->ring_gaps[1] = ring_gap1;
+ ret->ring_gaps[2] = ring_gap2;
+ ret->ring_gaps[3] = ring_gap3;
+ ret->ring_gaps[4] = ring_gap4;
ret->max_x = 0;
ret->max_y = 0;
ret->min_x = 10000;
@@ -205,6 +228,7 @@ static PixelDuster * pixel_duster_new (GeglBuffer *reference,
ret->scale_y = scale_y;
ret->metric_dist_powk = metric_dist_powk;
ret->metric_empty_score = metric_empty_score;
+ ret->metric_cohesion = metric_cohesion;
ret->in_sampler_f = gegl_buffer_sampler_new (input,
babl_format ("RGBA float"),
@@ -338,6 +362,9 @@ static inline float f_rgb_diff (float *a, float *b)
static float inline
score_site (PixelDuster *duster,
+ Probe *probe,
+ int x,
+ int y,
gfloat *needle,
gfloat *hay,
float bail)
@@ -364,7 +391,28 @@ score_site (PixelDuster *duster,
score += duster->metric_empty_score * duster->order[i][2];
}
}
- return sqrtf (score);
+
+ {
+ float sum_x = probe->source_x[0];
+ float sum_y = probe->source_y[0];
+ 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];
+ 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 = sqrtf (score);
+ return score;
}
static Probe *
@@ -499,9 +547,21 @@ probe_prep (PixelDuster *duster,
if ( (probe->target_x == oprobe->target_x) &&
(probe->target_y == oprobe->target_y + 1))
probe->neighbors[neighbours++] = oprobe;
+ if ( (probe->target_x == oprobe->target_x + 1) &&
+ (probe->target_y == oprobe->target_y + 1))
+ probe->neighbors[neighbours++] = oprobe;
+ if ( (probe->target_x == oprobe->target_x + 1) &&
+ (probe->target_y == oprobe->target_y - 1))
+ probe->neighbors[neighbours++] = oprobe;
+ if ( (probe->target_x == oprobe->target_x - 1) &&
+ (probe->target_y == oprobe->target_y + 1))
+ probe->neighbors[neighbours++] = oprobe;
+ if ( (probe->target_x == oprobe->target_x - 1) &&
+ (probe->target_y == oprobe->target_y - 1))
+ probe->neighbors[neighbours++] = oprobe;
}
}
- for (;neighbours < 4; neighbours++)
+ for (;neighbours < 8; neighbours++)
probe->neighbors[neighbours] = NULL;
}
@@ -538,7 +598,7 @@ static void probe_compare_hay (PixelDuster *duster,
{
for (int n = 0; n < N_SCALE_NEEDLES; n++)
{
- score = score_site (duster, &probe->needles[n][0], hay, probe->score);
+ score = score_site (duster, probe, x, y, &probe->needles[n][0], hay, probe->score);
if (score < probe->score)
{
@@ -559,6 +619,12 @@ static void probe_compare_hay (PixelDuster *duster,
probe->score = probe->k_score[0] = score;
}
}
+
+ /* XXX : incorporate distance to average destination of 4 connected
+ neighborhoods source coordinates.. */
+ {
+ }
+
}
}
@@ -742,8 +808,9 @@ static inline void pixel_duster_fill (PixelDuster *duster)
gint total = 0;
gint runs = 0;
- while ( ((missing >0) /* && (missing != old_missing) */) ||
- (runs < duster->minimum_iterations))
+ while ( (((missing >0) /* && (missing != old_missing) */) ||
+ (runs < duster->minimum_iterations)) &&
+ runs < duster->maximum_iterations)
{
#ifdef BATCH_PROBES
Probe *probes[BATCH_PROBES];
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]