summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Farago <sensej007@email.cz>2021-12-15 16:23:25 +0100
committerGitHub <noreply@github.com>2021-12-15 16:23:25 +0100
commit6cffd94d4d266b023015d21ec8963344cf5d3fb3 (patch)
tree86430966d84e68633da666f470f98aa5a045157c
parent4c5d52debe42d0ad3d04df03e0bb462d11854b51 (diff)
parente032d752dc9e4723445d82a099cc02163df3ddd3 (diff)
downloadufo-filters-6cffd94d4d266b023015d21ec8963344cf5d3fb3.tar.gz
ufo-filters-6cffd94d4d266b023015d21ec8963344cf5d3fb3.tar.bz2
ufo-filters-6cffd94d4d266b023015d21ec8963344cf5d3fb3.tar.xz
ufo-filters-6cffd94d4d266b023015d21ec8963344cf5d3fb3.zip
Merge pull request #218 from ufo-kit/horizontal-interpolate-just-copy
horizontal-interpolate: add use-one-sided-gradient
-rw-r--r--docs/filters.rst23
-rw-r--r--src/kernels/interpolator.cl23
-rw-r--r--src/ufo-horizontal-interpolate-task.c59
3 files changed, 91 insertions, 14 deletions
diff --git a/docs/filters.rst b/docs/filters.rst
index 287a0c5..822ad20 100644
--- a/docs/filters.rst
+++ b/docs/filters.rst
@@ -629,13 +629,22 @@ Horizontal interpolation
Interpolate masked values in rows of an image. For all pixels equal to one
in the mask, find the closest pixel where mask is zero to the left and right
and linearly interpolate the value in the current pixel based on the found
- left and right values. If the mask goes to the left or right border of the
- image and on the other side there are at least two non-masked pixels
- :math:`x_1` and :math:`x_2`, compute the value in the current pixel
- :math:`x` by (in case the mask goes to the right border, left is analogous)
- :math:`f(x) = f(x_2) + (x - x_2) * (f(x_2) - f(x_1))`. In case there is only
- one valid pixel on one of the borders and all the others are masked, use
- that pixel's value in all the remaining ones.
+ left and right values. If :gobj:prop:`use-one-sided-gradient` is *TRUE* and
+ the mask goes to the left or right border of the image and on the other side
+ there are at least two non-masked pixels :math:`x_1` and :math:`x_2`,
+ compute the value in the current pixel :math:`x` by (in case the mask goes
+ to the right border, left is analogous) :math:`f(x) = f(x_2) + (x - x_2) *
+ (f(x_2) - f(x_1))`. In case :gobj:prop:`use-one-sided-gradient` is *FALSE*
+ or there is only one valid pixel on one of the borders and all the others
+ are masked, use that pixel's value in all the remaining ones.
+
+ .. gobj:prop:: use-one-sided-gradient:boolean
+
+ If *TRUE*, use two good pixels on one side to compute gradient and fill
+ the masked values accordingly (for the case the mask spans to the
+ border). If *FALSE*, just copy the last "good" pixel value to the masked
+ values.
+
Stream transformations
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,16 +124,53 @@ 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)
{
UfoHorizontalInterpolateTaskPrivate *priv = UFO_HORIZONTAL_INTERPOLATE_TASK_GET_PRIVATE (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;
}