diff options
author | Tomas Farago <sensej007@email.cz> | 2018-03-12 12:11:19 +0100 |
---|---|---|
committer | Tomas Farago <sensej007@email.cz> | 2018-03-12 13:58:20 +0100 |
commit | c9f0c66fe24fd8f15a389347319f7ed8f0f67bb3 (patch) | |
tree | 32fed4ad180c8846d30ea674f698dbf886b1f2fe | |
parent | d701b2c11122883321763c7611e0d8a487b41431 (diff) | |
download | ufo-filters-c9f0c66fe24fd8f15a389347319f7ed8f0f67bb3.tar.gz ufo-filters-c9f0c66fe24fd8f15a389347319f7ed8f0f67bb3.tar.bz2 ufo-filters-c9f0c66fe24fd8f15a389347319f7ed8f0f67bb3.tar.xz ufo-filters-c9f0c66fe24fd8f15a389347319f7ed8f0f67bb3.zip |
Add gradient filter
-rw-r--r-- | docs/filters.rst | 12 | ||||
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/kernels/gradient.cl | 92 | ||||
-rw-r--r-- | src/meson.build | 1 | ||||
-rw-r--r-- | src/ufo-gradient-task.c | 238 | ||||
-rw-r--r-- | src/ufo-gradient-task.h | 53 |
6 files changed, 397 insertions, 0 deletions
diff --git a/docs/filters.rst b/docs/filters.rst index a72a52a..37f585f 100644 --- a/docs/filters.rst +++ b/docs/filters.rst @@ -488,6 +488,18 @@ Gaussian blur Sigma of the kernel. +Gradient +-------- + +.. gobj:class:: gradient + + Compute gradient. + + .. gobj:prop:: direction:enum + + Direction of the gradient, can be either ``horizontal``, ``vertical``, + ``both`` or ``both_abs``. + Stream transformations ====================== diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9d3e849..4307862 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -36,6 +36,7 @@ set(ufofilter_SRCS ufo-flip-task.c ufo-forwardproject-task.c ufo-get-dup-circ-task.c + ufo-gradient-task.c ufo-ifft-task.c ufo-interpolate-task.c ufo-interpolate-stream-task.c diff --git a/src/kernels/gradient.cl b/src/kernels/gradient.cl new file mode 100644 index 0000000..1db394b --- /dev/null +++ b/src/kernels/gradient.cl @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2011-2018 Karlsruhe Institute of Technology + * + * This file is part of Ufo. + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +float compute_horizontal (global float *input, + int idx, + int idy, + int width) { + int dx = 1; + if (idx == width - 1) { + dx = 0; + } else if (idx == 0) { + dx = 2; + } + + return 0.5f * (input[idy * width + idx + dx] - input[idy * width + idx + dx - 2]); +} + +float compute_vertical (global float *input, + int idx, + int idy, + int width, + int height) { + int dy = 1; + if (idy == height - 1) { + dy = 0; + } else if (idy == 0) { + dy = 2; + } + + return 0.5f * (input[(idy + dy) * width + idx] - input[(idy + dy - 2) * width + idx]); +} + +kernel void horizontal (global float *input, + global float *output) +{ + int width = get_global_size (0); + int idx = get_global_id (0); + int idy = get_global_id (1); + + output[idy * width + idx] = compute_horizontal (input, idx, idy, width); +} + +kernel void vertical (global float *input, + global float *output) +{ + int width = get_global_size (0); + int height = get_global_size (1); + int idx = get_global_id (0); + int idy = get_global_id (1); + + output[idy * width + idx] = compute_vertical (input, idx, idy, width, height); +} + +kernel void both (global float *input, + global float *output) +{ + int width = get_global_size (0); + int height = get_global_size (1); + int idx = get_global_id (0); + int idy = get_global_id (1); + + output[idy * width + idx] = compute_vertical (input, idx, idy, width, height) + + compute_horizontal (input, idx, idy, width); +} + +kernel void both_abs (global float *input, + global float *output) +{ + int width = get_global_size (0); + int height = get_global_size (1); + int idx = get_global_id (0); + int idy = get_global_id (1); + + output[idy * width + idx] = fabs (compute_vertical (input, idx, idy, width, height)) + + fabs (compute_horizontal (input, idx, idy, width)); +} diff --git a/src/meson.build b/src/meson.build index 17544cc..f65f89f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -32,6 +32,7 @@ plugins = [ 'flip', 'forwardproject', 'get-dup-circ', + 'gradient', 'interpolate', 'interpolate-stream', 'loop', diff --git a/src/ufo-gradient-task.c b/src/ufo-gradient-task.c new file mode 100644 index 0000000..1d6a7d3 --- /dev/null +++ b/src/ufo-gradient-task.c @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2011-2015 Karlsruhe Institute of Technology + * + * This file is part of Ufo. + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef __APPLE__ +#include <OpenCL/cl.h> +#else +#include <CL/cl.h> +#endif + +#include "ufo-gradient-task.h" + +typedef enum { + DIRECTION_HORIZONTAL, + DIRECTION_VERTICAL, + DIRECTION_BOTH, + DIRECTION_BOTH_ABS, + DIRECTION_LAST +} Direction; + +static GEnumValue direction_values[] = { + {DIRECTION_HORIZONTAL, "DIRECTION_HORIZONTAL", "horizontal" }, + {DIRECTION_VERTICAL, "DIRECTION_VERTICAL", "vertical" }, + {DIRECTION_BOTH, "DIRECTION_BOTH", "both" }, + {DIRECTION_BOTH_ABS, "DIRECTION_BOTH_ABS", "both_abs" }, + {0, NULL, NULL} +}; + +struct _UfoGradientTaskPrivate { + Direction direction; + cl_kernel kernel; +}; + +static void ufo_task_interface_init (UfoTaskIface *iface); + +G_DEFINE_TYPE_WITH_CODE (UfoGradientTask, ufo_gradient_task, UFO_TYPE_TASK_NODE, + G_IMPLEMENT_INTERFACE (UFO_TYPE_TASK, + ufo_task_interface_init)) + +#define UFO_GRADIENT_TASK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_GRADIENT_TASK, UfoGradientTaskPrivate)) + +enum { + PROP_0, + PROP_DIRECTION, + N_PROPERTIES +}; + +static GParamSpec *properties[N_PROPERTIES] = { NULL, }; + +UfoNode * +ufo_gradient_task_new (void) +{ + return UFO_NODE (g_object_new (UFO_TYPE_GRADIENT_TASK, NULL)); +} + +static void +ufo_gradient_task_setup (UfoTask *task, + UfoResources *resources, + GError **error) +{ + UfoGradientTaskPrivate *priv = UFO_GRADIENT_TASK_GET_PRIVATE (task); + priv->kernel = ufo_resources_get_kernel (resources, "gradient.cl", + direction_values[priv->direction].value_nick, + error); + UFO_RESOURCES_CHECK_CLERR (clRetainKernel (priv->kernel)); +} + +static void +ufo_gradient_task_get_requisition (UfoTask *task, + UfoBuffer **inputs, + UfoRequisition *requisition) +{ + ufo_buffer_get_requisition (inputs[0], requisition); +} + +static guint +ufo_gradient_task_get_num_inputs (UfoTask *task) +{ + return 1; +} + +static guint +ufo_gradient_task_get_num_dimensions (UfoTask *task, + guint input) +{ + return 2; +} + +static UfoTaskMode +ufo_gradient_task_get_mode (UfoTask *task) +{ + return UFO_TASK_MODE_PROCESSOR | UFO_TASK_MODE_GPU; +} + +static gboolean +ufo_gradient_task_process (UfoTask *task, + UfoBuffer **inputs, + UfoBuffer *output, + UfoRequisition *requisition) +{ + UfoGradientTaskPrivate *priv; + UfoGpuNode *node; + UfoProfiler *profiler; + cl_command_queue cmd_queue; + cl_mem in_mem, out_mem; + + priv = UFO_GRADIENT_TASK_GET_PRIVATE (task); + node = UFO_GPU_NODE (ufo_task_node_get_proc_node (UFO_TASK_NODE (task))); + cmd_queue = ufo_gpu_node_get_cmd_queue (node); + in_mem = ufo_buffer_get_device_array (inputs[0], cmd_queue); + out_mem = ufo_buffer_get_device_array (output, cmd_queue); + profiler = ufo_task_node_get_profiler (UFO_TASK_NODE (task)); + + switch (priv->direction) { + case DIRECTION_BOTH: + case DIRECTION_BOTH_ABS: + case DIRECTION_HORIZONTAL: + if (requisition->dims[0] < 3) { + g_warning ("Skipping image with width less than 3"); + return TRUE; + } + case DIRECTION_VERTICAL: + if (requisition->dims[1] < 3) { + g_warning ("Skipping image with height less than 3"); + return TRUE; + } + default: + break; + } + + UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->kernel, 0, sizeof (cl_mem), &in_mem)); + UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->kernel, 1, sizeof (cl_mem), &out_mem)); + ufo_profiler_call (profiler, cmd_queue, priv->kernel, 2, requisition->dims, NULL); + + return TRUE; +} + + +static void +ufo_gradient_task_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + UfoGradientTaskPrivate *priv = UFO_GRADIENT_TASK_GET_PRIVATE (object); + + switch (property_id) { + case PROP_DIRECTION: + priv->direction = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +ufo_gradient_task_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + UfoGradientTaskPrivate *priv = UFO_GRADIENT_TASK_GET_PRIVATE (object); + + switch (property_id) { + case PROP_DIRECTION: + g_value_set_enum (value, priv->direction); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +ufo_gradient_task_finalize (GObject *object) +{ + UfoGradientTaskPrivate *priv = UFO_GRADIENT_TASK_GET_PRIVATE (object); + UFO_RESOURCES_CHECK_CLERR (clReleaseKernel (priv->kernel)); + + G_OBJECT_CLASS (ufo_gradient_task_parent_class)->finalize (object); +} + +static void +ufo_task_interface_init (UfoTaskIface *iface) +{ + iface->setup = ufo_gradient_task_setup; + iface->get_num_inputs = ufo_gradient_task_get_num_inputs; + iface->get_num_dimensions = ufo_gradient_task_get_num_dimensions; + iface->get_mode = ufo_gradient_task_get_mode; + iface->get_requisition = ufo_gradient_task_get_requisition; + iface->process = ufo_gradient_task_process; +} + +static void +ufo_gradient_task_class_init (UfoGradientTaskClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS (klass); + + oclass->set_property = ufo_gradient_task_set_property; + oclass->get_property = ufo_gradient_task_get_property; + oclass->finalize = ufo_gradient_task_finalize; + + properties[PROP_DIRECTION] = + g_param_spec_enum ("direction", + "Direction (horizontal, vertical, both, both_abs)", + "Direction (horizontal, vertical, both, both_abs)", + g_enum_register_static ("direction", direction_values), + DIRECTION_HORIZONTAL, + 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(UfoGradientTaskPrivate)); +} + +static void +ufo_gradient_task_init(UfoGradientTask *self) +{ + self->priv = UFO_GRADIENT_TASK_GET_PRIVATE(self); + self->priv->direction = DIRECTION_HORIZONTAL; +} diff --git a/src/ufo-gradient-task.h b/src/ufo-gradient-task.h new file mode 100644 index 0000000..13c792a --- /dev/null +++ b/src/ufo-gradient-task.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2011-2013 Karlsruhe Institute of Technology + * + * This file is part of Ufo. + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __UFO_GRADIENT_TASK_H +#define __UFO_GRADIENT_TASK_H + +#include <ufo/ufo.h> + +G_BEGIN_DECLS + +#define UFO_TYPE_GRADIENT_TASK (ufo_gradient_task_get_type()) +#define UFO_GRADIENT_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_GRADIENT_TASK, UfoGradientTask)) +#define UFO_IS_GRADIENT_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_GRADIENT_TASK)) +#define UFO_GRADIENT_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_GRADIENT_TASK, UfoGradientTaskClass)) +#define UFO_IS_GRADIENT_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_GRADIENT_TASK)) +#define UFO_GRADIENT_TASK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_GRADIENT_TASK, UfoGradientTaskClass)) + +typedef struct _UfoGradientTask UfoGradientTask; +typedef struct _UfoGradientTaskClass UfoGradientTaskClass; +typedef struct _UfoGradientTaskPrivate UfoGradientTaskPrivate; + +struct _UfoGradientTask { + UfoTaskNode parent_instance; + + UfoGradientTaskPrivate *priv; +}; + +struct _UfoGradientTaskClass { + UfoTaskNodeClass parent_class; +}; + +UfoNode *ufo_gradient_task_new (void); +GType ufo_gradient_task_get_type (void); + +G_END_DECLS + +#endif |