alpha-inpaint: adjust cohesion part of metric

instead of wanting the smallest possible distance to the average neighborhood
we now consider the situation optimal when we are on average 1px away from
the sources of the neighbors, hoping to encourage texture synthesis.
parent 81210225
Pipeline #95243 passed with stages
in 14 minutes and 42 seconds
......@@ -316,8 +316,8 @@ gegl_config_class_init (GeglConfigClass *klass)
+ zfs_arc_size;
}
#else
mem_total = sysconf (_SC_PHYS_PAGES) * sysconf (_SC_PAGESIZE);
mem_available = sysconf (_SC_AVPHYS_PAGES) * sysconf (_SC_PAGESIZE);
mem_total = (uint64_t) sysconf (_SC_PHYS_PAGES) * sysconf (_SC_PAGESIZE);
mem_available = (uint64_t) sysconf (_SC_AVPHYS_PAGES) * sysconf (_SC_PAGESIZE);
#endif
default_tile_cache_size = mem_total;
......
......@@ -190,8 +190,31 @@ gegl_node_set_time (GeglNode *node,
}
static char *
gegl_migrate_saturation_0_0_to_1_0 (const char *input)
{
//params_add_entry (params, "colorspace=CIE-lab");
//return TRUE;
return g_strdup (input);
}
gboolean
gegl_migrate_api (GeglNode *node,
const char *operation,
char **params)
{
// if there is no opi entry, nothing to migrate
// if we find opi key.. look for valid migration
return TRUE;
}
void
gegl_create_chain_argv (char **ops,
gegl_create_chain_argv (char **argv,
GeglNode *start,
GeglNode *proxy,
double time,
......@@ -201,7 +224,7 @@ gegl_create_chain_argv (char **ops,
{
GeglNode *iter[10] = {start, NULL};
GeglNode *new = NULL;
gchar **arg = ops;
gchar **arg = argv;
int level = 0;
char *level_op[10];
char *level_pad[10];
......@@ -212,6 +235,8 @@ gegl_create_chain_argv (char **ops,
GeglPath *path = NULL;
GString *string = NULL;
GeglNode **ret_sinkp = NULL;
char *op_args[64]={NULL, };
int n_op_args = 0;
if (error && *error)
{
......@@ -227,7 +252,6 @@ gegl_create_chain_argv (char **ops,
ht = g_hash_table_new (g_str_hash, g_str_equal);
while (*arg)
{
if (in_keyframes)
......@@ -388,6 +412,7 @@ gegl_create_chain_argv (char **ops,
{
/* should check for incompatibility rather than difference
*/
fprintf (stderr, "{%s}", value);
if (!g_str_equal (value,
gegl_operation_get_op_version (level_op[
level])))
......@@ -851,12 +876,11 @@ gegl_create_chain (const char *str, GeglNode *op_start, GeglNode *op_end,
}
}
/* TODO: serialize keyframed properties */
static gchar *
gegl_serialize2 (GeglNode *start,
GeglNode *end,
gegl_serialize2 (GeglNode *start,
GeglNode *end,
const char *basepath,
GHashTable *ht,
GHashTable *ht,
GeglSerializeFlag flags)
{
char *ret = NULL;
......@@ -937,6 +961,7 @@ gegl_serialize2 (GeglNode *start,
gint i;
guint n_properties;
GParamSpec **properties;
gboolean printed = FALSE;
properties = gegl_operation_list_properties (gegl_node_get_operation (
iter),
......@@ -950,7 +975,6 @@ gegl_serialize2 (GeglNode *start,
properties[i]);
char tmpbuf[1024];
GeglPath *anim_path = NULL;
gboolean printed = FALSE;
char *rel_orig = NULL;
GQuark anim_quark, rel_quark;
sprintf (tmpbuf, "%s-anim", property_name);
......@@ -1180,21 +1204,21 @@ gegl_serialize2 (GeglNode *start,
"%s: serialization of %s properties not implemented",
property_name, g_type_name (property_type));
}
}
if (printed && (flags & GEGL_SERIALIZE_INDENT))
if (printed && (flags & GEGL_SERIALIZE_INDENT))
g_string_append_printf (s2, "\n");
{
GeglNode *aux = gegl_node_get_producer (iter, "aux", NULL);
if (aux)
{
char *str = gegl_serialize2 (NULL, aux, basepath, ht,
flags);
g_string_append_printf (s2, " aux=[ %s ]%s", str,
{
GeglNode *aux = gegl_node_get_producer (iter, "aux", NULL);
if (aux)
{
char *str = gegl_serialize2 (NULL, aux, basepath, ht,
flags);
g_string_append_printf (s2, " aux=[ %s ]%s", str,
(flags& GEGL_SERIALIZE_INDENT)?"\n":" ");
g_free (str);
}
}
g_free (str);
}
}
}
......
......@@ -36,7 +36,7 @@ property_double (scale, _("Scale"), 1.0)
property_enum (colorspace, _("Interpolation Color Space"),
description(_("Set at Native if uncertain, the CIE based spaces might introduce hue shifts."))
GeglSaturationType, gegl_saturation_type,
GEGL_SATURATION_TYPE_CIE_LAB)
GEGL_SATURATION_TYPE_NATIVE)
#else
......@@ -380,6 +380,7 @@ gegl_op_class_init (GeglOpClass *klass)
gegl_operation_class_set_keys (operation_class,
"name" , "gegl:saturation",
"opi", "1:0",
"title", _("Saturation"),
"reference-hash", "584bfe714947a573f10399965c8b45b0",
"categories" , "color",
......
......@@ -29,7 +29,7 @@ property_int (seek_distance, "seek radius", 10)
description ("Maximum distance in neighborhood we look for better candidates per improvement.")
value_range (1, 512)
property_double (seek_reduction, "seek reduction", 0.75)
property_double (seek_reduction, "seek reduction", 0.6)
description ("factor seek distance is shortened, until we're about 2px short per iteration, 1.0 means no reduction")
value_range (0.0, 1.0)
......@@ -45,27 +45,31 @@ property_int (max_iter, "max rounds", 800)
description ("Mostly a saftey valve, so that we terminate")
value_range (1, 40000)
property_int (iterations, "iterations per round per probe", 16)
property_int (iterations, "iterations per round per probe", 23)
description ("number of improvement iterations, after initial search - that each probe gets.")
value_range (1, 1000)
property_double (histogram, "histogram", 0.5)
description ("only consider pixels whose neighborhood color distribution is smaller than specified, set to 1.0 for much faster processing, but needing lower seek distance to yield ok results.")
value_range (0.0, 1.0)
property_double (ring_gap1, "ring gap1", 1.1)
description ("radius, in pixels of nearest to pixel circle of neighborhood metric")
value_range (0.0, 16.0)
ui_steps (0.25, 0.25)
property_double (ring_gap2, "ring gap2", 1.75)
property_double (ring_gap2, "ring gap2", 1.9)
description ("radius, in pixels of second nearest to pixel circle")
value_range (0.0, 16.0)
ui_steps (0.25, 0.25)
property_double (ring_gap3, "ring gap3", 2.9)
property_double (ring_gap3, "ring gap3", 3.2)
description ("radius, in pixels of third pixel circle")
value_range (0.0, 16.0)
ui_steps (0.25, 0.25)
property_double (ring_gap4, "ring gap4", 4.0)
property_double (ring_gap4, "ring gap4", 4.1)
description ("radius, in pixels of fourth pixel circle (not always in use)")
value_range (0.0, 16.0)
ui_steps (0.25, 0.25)
......@@ -73,11 +77,11 @@ property_double (ring_gap4, "ring gap4", 4.0)
property_int (scale_needles, "scale needles", 5)
value_range (1, 7)
property_int (rounds, "rounds", 8)
property_int (rounds, "rounds", 16)
description ("number of improvement iterations, after initial search - that each probe gets.")
value_range (0, 1000)
property_double (chance_try, "try probability", 0.07)
property_double (chance_try, "try probability", 0.015)
description ("The chance that a candidate pixel probe will start being filled in")
value_range (0.0, 1.0)
ui_steps (0.01, 0.1)
......@@ -91,12 +95,12 @@ property_double (chance_neighbor, "chance neighbor", 1.0)
value_range (0.0, 1.0)
ui_steps (0.01, 0.1)
property_double (metric_dist_powk, "dist powk", 2.8)
property_double (metric_dist_powk, "dist powk", 1.8)
description ("influences the (lack of) importance of further away pixels")
value_range (0.0, 10.0)
ui_steps (0.1, 1.0)
property_double (metric_empty_hay_score, "empty hay score", 0.38)
property_double (metric_empty_hay_score, "empty hay score", 0.275)
description ("score given to pixels that are empty, in the search neighborhood of pixel, this being at default or higher value sometimes discourages some of the good very nearby matches")
value_range (0.001, 100.0)
ui_steps (0.05, 0.1)
......@@ -106,7 +110,7 @@ property_double (metric_empty_needle_score, "empty needle score", 0.18)
value_range (0.001, 100.0)
ui_steps (0.05, 0.1)
property_double (metric_cohesion, "metric cohesion", 0.5)
property_double (metric_cohesion, "metric cohesion", 0.13)
description ("influences the importance of probe spatial proximity")
value_range (0.0, 100.0)
ui_steps (0.2, 0.2)
......@@ -120,7 +124,7 @@ property_double (ring_twist, "ring twist", 0.0)
property_boolean (direction_invariant, "direction invariant", TRUE)
description ("wheter we normalize feature vector to start with highest energy ray")
property_int (source_neighbors, "source neighbors", 4)
property_int (source_neighbors, "source neighbors", 8)
description ("pick neighbor of neighbors as starting point if good, 4connected 8conntected or 12/16 with longer teleport")
value_range (0, 16)
......@@ -141,7 +145,7 @@ property_int (source_neighbors, "source neighbors", 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)
/* The pattern of the sampling neighborhood is RAYS of samples radiating out
......@@ -215,8 +219,10 @@ typedef struct
typedef struct _Probe Probe;
#define HIST_DIM 4
typedef float needles_t[N_SCALE_NEEDLES][4 * NEIGHBORHOOD ];// should be on stack
typedef float needles_hist_t[N_SCALE_NEEDLES][HIST_DIM * HIST_DIM * HIST_DIM];// should be on stack
struct _Probe {
......@@ -503,6 +509,62 @@ static inline float f_rgb_diff (float *a, float *b)
return POW2(a[0]-b[0]) + POW2(a[1]-b[1]) + POW2(a[2]-b[2]);
}
static inline void make_hist (PixelDuster *duster, gfloat *signature, float *hist)
{
float *rgba;
int count = 0;
rgba = signature + 4;
for (int i = 1; i < NEIGHBORHOOD; i++)
{
if (rgba[3] > 0.5)
{
int cell_a = rgba[0] * HIST_DIM + 0.5;
int cell_b = rgba[1] * HIST_DIM + 0.5;
int cell_c = rgba[2] * HIST_DIM + 0.5;
if (cell_a < 0) cell_a = 0;
if (cell_b < 0) cell_b = 0;
if (cell_c < 0) cell_c = 0;
if (cell_a >= HIST_DIM) cell_a = HIST_DIM-1;
if (cell_b >= HIST_DIM) cell_b = HIST_DIM-1;
if (cell_c >= HIST_DIM) cell_c = HIST_DIM-1;
hist[cell_a * HIST_DIM * HIST_DIM + cell_b * HIST_DIM + cell_c] += 1.0;
count++;
}
rgba += 4;
}
if (count)
for (int i = 0; i < HIST_DIM * HIST_DIM * HIST_DIM; i++)
{
hist[i] /= count;
}
}
static float inline
histogram_compare (PixelDuster *duster,
gfloat *needle,
gfloat *needle_hist,
gfloat *hay)
{
float diff = 0.0;
//float needle_hist[HIST_DIM * HIST_DIM * HIST_DIM]={0,};
float hay_hist[HIST_DIM * HIST_DIM * HIST_DIM]={0,};
//make_hist (duster, needle, needle_hist);
make_hist (duster, hay, hay_hist);
for (int i = 0; i < HIST_DIM * HIST_DIM * HIST_DIM; i++)
diff += POW2(needle_hist[i] - hay_hist[i]);
return sqrtf(diff);
}
static float inline
score_site (PixelDuster *duster,
Probe *probe,
......@@ -510,6 +572,7 @@ score_site (PixelDuster *duster,
int x,
int y,
gfloat *needle,
gfloat *needle_hist,
gfloat *hay,
float bail)
{
......@@ -523,22 +586,30 @@ score_site (PixelDuster *duster,
return INITIAL_SCORE;
}
// return histogram_compare (duster, needle, hay);
if (o->histogram < 1.0)
{
score = histogram_compare (duster, needle, needle_hist, hay);
if (score > o->histogram)
return INITIAL_SCORE;
}
{
float sum_x = probe->source_x;
float sum_y = probe->source_y;
int count = 1;
for (int i = 0; i < 4; i++)
float sum = 0;//probe->source_x;
int count = 0;
for (int i = 0; i < 8; i++)
if (neighbors[i])
{
sum_x += neighbors[i]->source_x;
sum_y += neighbors[i]->source_y;
int dx = abs(probe->source_x - neighbors[i]->source_x);
int dy = abs(probe->source_y - neighbors[i]->source_y);
int val = abs (MAX(dx,dy)-1);
sum += val;
count++;
}
sum_x /= count;
sum_y /= count;
sum /= count;
score += (POW2(sum_x - probe->source_x) +
POW2(sum_y - probe->source_y)) * o->metric_cohesion / 1000.0f;
score += sum * o->metric_cohesion;
}
for (i = 1; i < NEIGHBORHOOD && score < bail; i++)
......@@ -623,6 +694,7 @@ probe_score (PixelDuster *duster,
Probe *probe,
Probe **neighbors,
needles_t needles,
needles_hist_t needles_hist,
int x,
int y,
gfloat *hay,
......@@ -655,23 +727,20 @@ static inline void
probe_prep (PixelDuster *duster,
Probe *probe,
Probe **neighbors,
needles_t needles)
needles_t needles,
needles_hist_t needles_hist)
{
float scales[]={1.0, 1.2, 0.83333, 1.4, 0.7, 1.5, 0.66667};
gint dst_x = probe->target_x;
gint dst_y = probe->target_y;
extract_site (duster, duster->output, dst_x, dst_y, 1.0, &needles[0][0]);
if (duster->o->scale_needles > 1)
extract_site (duster, duster->output, dst_x, dst_y, 1.2, &needles[1][0]);
if (duster->o->scale_needles > 2)
extract_site (duster, duster->output, dst_x, dst_y, 0.8333, &needles[2][0]);
if (duster->o->scale_needles > 3)
extract_site (duster, duster->output, dst_x, dst_y, 1.4, &needles[3][0]);
if (duster->o->scale_needles > 4)
extract_site (duster, duster->output, dst_x, dst_y, 0.7, &needles[4][0]);
if (duster->o->scale_needles > 5)
extract_site (duster, duster->output, dst_x, dst_y, 1.5, &needles[5][0]);
if (duster->o->scale_needles > 6)
extract_site (duster, duster->output, dst_x, dst_y, 0.66667,&needles[6][0]);
for (int i = 0; i < sizeof(scales)/sizeof(scales[0]) &&
i < duster->o->scale_needles; i++)
{
extract_site (duster, duster->output, dst_x, dst_y, scales[i], &needles[i][0]);
make_hist (duster, &needles[i][0], &needles_hist[i][0]);
}
/* find neighbors */
{
......@@ -697,7 +766,7 @@ probe_prep (PixelDuster *duster,
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, neighbors, needles, test_x, test_y, hay, probe->score);
float score = probe_score (duster, probe, neighbors, needles, needles_hist, test_x, test_y, hay, probe->score);
if (score <= probe->score)
{
probe->source_x = test_x;
......@@ -715,6 +784,7 @@ probe_score (PixelDuster *duster,
Probe *probe,
Probe **neighbors,
needles_t needles,
needles_hist_t needles_hist,
int x,
int y,
gfloat *hay,
......@@ -730,7 +800,7 @@ probe_score (PixelDuster *duster,
for (int n = 0; n < duster->o->scale_needles; n++)
{
float score = score_site (duster, probe, neighbors, x, y, &needles[n][0], hay, bail);
float score = score_site (duster, probe, neighbors, x, y, &needles[n][0], &needles_hist[n][0], hay, bail);
if (score < best_score)
best_score = score;
}
......@@ -745,6 +815,7 @@ static void probe_improve (PixelDuster *duster,
Probe *neighbors[16]={NULL,};
GeglProperties *o = duster->o;
needles_t needles;
needles_hist_t needles_hist = {{0.0,},};
float old_score = probe->score;
if (probe->age >= o->rounds)
......@@ -753,26 +824,36 @@ static void probe_improve (PixelDuster *duster,
return;
}
probe_prep (duster, probe, neighbors, needles);
probe_prep (duster, probe, neighbors, needles, needles_hist);
{
float mag = o->seek_distance;
float mag = 5;//o->seek_distance;
float startx = probe->source_x;
float starty = probe->source_y;
int dir = 0;
for (int i = 0; i < o->iterations; i++)
{
int dx = g_random_int_range (-mag, mag);
int dy = g_random_int_range (-mag, mag);
mag *= o->seek_reduction; // reduce seek radius for each iteration
if (dir)
mag *= o->seek_reduction; // reduce seek radius for each iteration
else
mag /= o->seek_reduction; // reduce seek radius for each iteration
if (mag < 3)
mag = 2;
if (mag > o->seek_distance)
{
mag = o->seek_distance;
dir = 1;
}
if (!(dx == 0 && dy == 0))
{
int test_x = startx + dx;
int test_y = starty + dy;
float *hay = ensure_hay (duster, test_x, test_y);
float score = probe_score (duster, probe, neighbors, needles, test_x, test_y, hay, probe->score);
float score = probe_score (duster, probe, neighbors, needles, needles_hist, test_x, test_y, hay, probe->score);
if (score <= probe->score)
{
probe->source_x = test_x;
......@@ -844,7 +925,7 @@ pixel_duster_trim (PixelDuster *duster)
static int random_compare (gconstpointer a,
gconstpointer b)
{
return g_random_int_range (-1, 1);
return g_random_int_range (-5, 6);
}
static GList *list_randomize (GList *input)
......@@ -891,13 +972,13 @@ static inline void pixel_duster_fill (PixelDuster *duster)
}
else
{
try_replace = ((rand()%100)/100.0) < o->chance_retry;
try_replace = ((rand()%1000)/1000.0) < o->chance_retry;
}
total ++;
if (probe->score == INITIAL_SCORE || try_replace)
{
if ((rand()%100)/100.0 < o->chance_try)
if ((rand()%1000)/1000.0 < o->chance_try)
{
if (probe->score != INITIAL_SCORE ||
(probe_neighbors (duster, duster->output, probe, o->min_neighbors) >= o->min_neighbors))
......@@ -1135,6 +1216,7 @@ gegl_op_class_init (GeglOpClass *klass)
operation_class->get_required_for_output = get_required_for_output;
operation_class->get_cached_region = get_cached_region;
operation_class->opencl_support = FALSE;
// operation_class->threaded = FALSE; // it kind of works, set to TRUE for more performance and possible crashes
operation_class->threaded = FALSE; // it kind of works, set to TRUE for more performance and possible crashes
gegl_operation_class_set_keys (operation_class,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment