From e032d752dc9e4723445d82a099cc02163df3ddd3 Mon Sep 17 00:00:00 2001 From: Tomas Farago Date: Wed, 15 Dec 2021 16:22:05 +0100 Subject: horizontal-interpolate: add use-one-sided-gradient Which gives finer contol over what happens when the mask spans to the border. --- src/kernels/interpolator.cl | 23 +++++++++----- src/ufo-horizontal-interpolate-task.c | 59 +++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/kernels/interpolator.cl b/src/kernels/interpolator.cl index 6600af9..4d4eae8 100644 --- a/src/kernels/interpolator.cl +++ b/src/kernels/interpolator.cl @@ -53,7 +53,8 @@ interpolate_horizontally (global float *a, kernel void interpolate_mask_horizontally (global float *input, global float *mask, - global float *output) + global float *output, + const int use_gradient) { const int idx = get_global_id (0); const int idy = get_global_id (1); @@ -73,9 +74,13 @@ interpolate_mask_horizontally (global float *input, if (left < 0) { /* Mask spans to the left border, use only the right value */ if (right < width - 1) { - /* There are two valid pixels on the right, use gradient */ - diff = input[offset + right] - input[offset + right + 1]; - output[offset + idx] = input[offset + right] + diff * (right - idx); + if (use_gradient) { + /* There are two valid pixels on the right, use gradient */ + diff = input[offset + right] - input[offset + right + 1]; + output[offset + idx] = input[offset + right] + diff * (right - idx); + } else { + output[offset + idx] = input[offset + right]; + } } else if (right == width - 1) { /* There is only one valid pixel on the right, which is the only * valid pixel in this row, so use it's value everywhere */ @@ -87,9 +92,13 @@ interpolate_mask_horizontally (global float *input, } else if (right >= width) { /* Mask spans to the right border, use only the left value */ if (left > 0) { - /* There are two valid pixels on the left, use gradient */ - diff = input[offset + left] - input[offset + left - 1]; - output[offset + idx] = input[offset + left] + diff * (idx - left); + if (use_gradient) { + /* There are two valid pixels on the left, use gradient */ + diff = input[offset + left] - input[offset + left - 1]; + output[offset + idx] = input[offset + left] + diff * (idx - left); + } else { + output[offset + idx] = input[offset + left]; + } } else if (left == 0) { /* There is only one valid pixel on the left, which is the only * valid pixel in this row, so use it's value everywhere */ diff --git a/src/ufo-horizontal-interpolate-task.c b/src/ufo-horizontal-interpolate-task.c index 436018b..abe6d27 100644 --- a/src/ufo-horizontal-interpolate-task.c +++ b/src/ufo-horizontal-interpolate-task.c @@ -29,6 +29,7 @@ struct _UfoHorizontalInterpolateTaskPrivate { cl_kernel kernel; + gboolean use_onesided_gradient; }; static void ufo_task_interface_init (UfoTaskIface *iface); @@ -39,6 +40,14 @@ G_DEFINE_TYPE_WITH_CODE (UfoHorizontalInterpolateTask, ufo_horizontal_interpolat #define UFO_HORIZONTAL_INTERPOLATE_TASK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_HORIZONTAL_INTERPOLATE_TASK, UfoHorizontalInterpolateTaskPrivate)) +enum { + PROP_0, + PROP_USE_ONESIDED_GRADIENT, + N_PROPERTIES +}; + +static GParamSpec *properties[N_PROPERTIES] = { NULL, }; + UfoNode * ufo_horizontal_interpolate_task_new (void) { @@ -106,6 +115,7 @@ ufo_horizontal_interpolate_task_process (UfoTask *task, UfoProfiler *profiler; cl_command_queue cmd_queue; cl_mem mask_in_mem, in_mem, out_mem; + gint use_onesided_gradient; priv = UFO_HORIZONTAL_INTERPOLATE_TASK_GET_PRIVATE (task); node = UFO_GPU_NODE (ufo_task_node_get_proc_node (UFO_TASK_NODE (task))); @@ -114,15 +124,52 @@ ufo_horizontal_interpolate_task_process (UfoTask *task, mask_in_mem = ufo_buffer_get_device_array (inputs[1], cmd_queue); out_mem = ufo_buffer_get_device_array (output, cmd_queue); profiler = ufo_task_node_get_profiler (UFO_TASK_NODE (task)); + use_onesided_gradient = (gint) priv->use_onesided_gradient; UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->kernel, 0, sizeof (cl_mem), &in_mem)); UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->kernel, 1, sizeof (cl_mem), &mask_in_mem)); UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->kernel, 2, sizeof (cl_mem), &out_mem)); + UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->kernel, 3, sizeof (cl_int), &use_onesided_gradient)); ufo_profiler_call (profiler, cmd_queue, priv->kernel, 2, requisition->dims, NULL); return TRUE; } +static void +ufo_horizontal_interpolate_task_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + UfoHorizontalInterpolateTaskPrivate *priv = UFO_HORIZONTAL_INTERPOLATE_TASK_GET_PRIVATE (object); + + switch (property_id) { + case PROP_USE_ONESIDED_GRADIENT: + priv->use_onesided_gradient = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +ufo_horizontal_interpolate_task_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + UfoHorizontalInterpolateTaskPrivate *priv = UFO_HORIZONTAL_INTERPOLATE_TASK_GET_PRIVATE (object); + + switch (property_id) { + case PROP_USE_ONESIDED_GRADIENT: + g_value_set_boolean (value, priv->use_onesided_gradient); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} static void ufo_horizontal_interpolate_task_finalize (GObject *object) { @@ -153,9 +200,20 @@ ufo_horizontal_interpolate_task_class_init (UfoHorizontalInterpolateTaskClass *k GObjectClass *oclass = G_OBJECT_CLASS (klass); UfoNodeClass *node_class = UFO_NODE_CLASS (klass); + oclass->set_property = ufo_horizontal_interpolate_task_set_property; + oclass->get_property = ufo_horizontal_interpolate_task_get_property; oclass->finalize = ufo_horizontal_interpolate_task_finalize; node_class->equal = ufo_horizontal_interpolate_task_equal_real; + properties[PROP_USE_ONESIDED_GRADIENT] = + g_param_spec_boolean ("use-one-sided-gradient", + "In case the mask spans all the way to the border, use two points on one side and fill with gradient", + "In case the mask spans all the way to the border, use two points on one side and fill with gradient", + TRUE, G_PARAM_READWRITE); + + for (guint i = PROP_0 + 1; i < N_PROPERTIES; i++) + g_object_class_install_property (oclass, i, properties[i]); + g_type_class_add_private (oclass, sizeof(UfoHorizontalInterpolateTaskPrivate)); } @@ -163,4 +221,5 @@ static void ufo_horizontal_interpolate_task_init(UfoHorizontalInterpolateTask *self) { self->priv = UFO_HORIZONTAL_INTERPOLATE_TASK_GET_PRIVATE(self); + self->priv->use_onesided_gradient = TRUE; } -- cgit v1.2.1