[gegl] workshop: add max iterations and cohesion parameters



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]