summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Farago <sensej007@email.cz>2020-02-05 10:45:27 +0100
committerGitHub <noreply@github.com>2020-02-05 10:45:27 +0100
commit570972b8ec9ab80237812593123a2b465861ad0b (patch)
treee22c18f0502b1e9f17b53feb3a7199b2ad065632
parent64a980599dbbbc01866cf7cb2560694522e02155 (diff)
parentfd1dbaaab5bb182c2fc660992449fee954bc35b3 (diff)
downloadufo-filters-570972b8ec9ab80237812593123a2b465861ad0b.tar.gz
ufo-filters-570972b8ec9ab80237812593123a2b465861ad0b.tar.bz2
ufo-filters-570972b8ec9ab80237812593123a2b465861ad0b.tar.xz
ufo-filters-570972b8ec9ab80237812593123a2b465861ad0b.zip
Merge pull request #184 from ufo-kit/find-large-spots
Find large spots
-rw-r--r--docs/filters.rst31
-rw-r--r--src/CMakeLists.txt5
-rw-r--r--src/kernels/meson.build1
-rw-r--r--src/kernels/morphology.cl115
-rw-r--r--src/meson.build14
-rw-r--r--src/ufo-find-large-spots-task.c476
-rw-r--r--src/ufo-find-large-spots-task.h53
7 files changed, 695 insertions, 0 deletions
diff --git a/docs/filters.rst b/docs/filters.rst
index 8afd0cb..041b893 100644
--- a/docs/filters.rst
+++ b/docs/filters.rst
@@ -590,6 +590,37 @@ Non-local-means denoising
+Finding large spots
+-------------------
+
+.. gobj:class:: find-large-spots
+
+ Find large spots with extreme values in an image. First, pixels with values
+ greater than :gobj:prop:`spot_threshold` are added to the mask, then
+ connected pixels with absolute difference between them and the originally
+ detected greater than :gobj:prop:`grow-threshold` are added to the mask. In
+ the end, holes are also removed from the mask.
+
+ .. gobj:prop:: spot-threshold:float
+
+ Pixels with values greater than this threshold are added to the mask.
+
+ .. gobj:prop:: grow-threshold:float
+
+ Pixels connected to the ones found by :gobj:prop:`spot-threshold` with
+ absolute difference greater than this threshold are added to the mask.
+ If the value is 0, it is automatically set to full width at tenth
+ maximum of the estimated noise standard deviation.
+
+ .. gobj:prop:: addressing-mode:enum
+
+ Addressing mode specifies the behavior for pixels falling outside the
+ original image. See OpenCL ``sampler_t`` documentation for more
+ information. This parameter is used only for automatic noise standard
+ deviation estimation.
+
+
+
Horizontal interpolation
------------------------
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6f69f19..14e6f52 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -26,6 +26,7 @@ set(ufofilter_SRCS
ufo-dump-ring-task.c
ufo-duplicate-task.c
ufo-filter-task.c
+ ufo-find-large-spots-task.c
ufo-flatten-task.c
ufo-flatten-inplace-task.c
ufo-flat-field-correct-task.c
@@ -131,6 +132,10 @@ set(non_local_means_aux_SRCS
common/ufo-math.c
common/ufo-common.c)
+set(find_large_spots_aux_SRCS
+ common/ufo-math.c
+ common/ufo-common.c)
+
file(GLOB ufofilter_KERNELS "kernels/*.cl")
#}}}
#{{{ Variables
diff --git a/src/kernels/meson.build b/src/kernels/meson.build
index 4126c27..f8a685c 100644
--- a/src/kernels/meson.build
+++ b/src/kernels/meson.build
@@ -27,6 +27,7 @@ kernel_files = [
'mask.cl',
'median.cl',
'metaballs.cl',
+ 'morphology.cl',
'nlm.cl',
'ordfilt.cl',
'opencl.cl',
diff --git a/src/kernels/morphology.cl b/src/kernels/morphology.cl
new file mode 100644
index 0000000..af76b58
--- /dev/null
+++ b/src/kernels/morphology.cl
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2011-2019 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/>.
+ */
+
+/**
+ * Set mask to 1 if value exceeds threshold. If sgn is -1, value has to be below
+ * threshold, if it is 1 it has to be above threshold, if it is 0 absolute value
+ * is compared.
+ */
+kernel void
+set_above_threshold (global float *input,
+ global float *output,
+ const float threshold,
+ const int sgn)
+{
+ int index = get_global_id (1) * get_global_size (0) + get_global_id (0);
+ float value = input[index];
+ if (!sgn) {
+ value = fabs (value) - threshold;
+ } else {
+ value = sgn * (value - threshold);
+ }
+
+ output[index] = value > 0 ? 1 : 0;
+}
+
+kernel void
+set_to_ones (global float *values)
+{
+ int x = get_global_id (0) + 1;
+ int y = get_global_id (1) + 1;
+ int width = get_global_size (0) + 2;
+
+ values[y * width + x] = 1;
+}
+
+kernel void
+grow_region_above_threshold (global float *input,
+ global float *visited,
+ global float *output,
+ global int *counter,
+ const float threshold)
+{
+ int x = get_global_id (0) + 1;
+ int y = get_global_id (1) + 1;
+ int width = get_global_size (0) + 2;
+ int offset = y * width;
+ int index = offset + x;
+ float value, diff = 0.0f, maximum = 0.0f;
+ int dxy;
+
+ if (visited[index]) {
+ return;
+ }
+ value = input[index];
+
+ for (dxy = -1; dxy < 2; dxy += 2) {
+ /* Check x +/- 1 */
+ if (visited[offset + x + dxy]) {
+ diff = fabs (value - input[offset + x + dxy]);
+ if (diff > maximum) {
+ maximum = diff;
+ }
+ }
+ /* Check y +/- 1 */
+ if (visited[(y + dxy) * width + x]) {
+ diff = fabs (value - input[(y + dxy) * width + x]);
+ if (diff > maximum) {
+ maximum = diff;
+ }
+ }
+ }
+ if (maximum > threshold) {
+ output[index] = 1;
+ atomic_inc (counter);
+ }
+}
+
+kernel void
+fill_holes (global int *input,
+ global int *visited,
+ global int *output,
+ global int *counter)
+{
+ int x = get_global_id (0) + 1;
+ int y = get_global_id (1) + 1;
+ int width = get_global_size (0) + 2;
+ int offset = y * width;
+ int index = offset + x;
+
+ if (!visited[index] || input[index]) {
+ return;
+ }
+
+ if (!(visited[offset + x - 1] && visited[offset + x + 1] && visited[(y - 1) * width + x] && visited[(y + 1) * width + x])) {
+ output[index] = 0;
+ atomic_inc (counter);
+ }
+}
+
diff --git a/src/meson.build b/src/meson.build
index 4cd4bdc..510d119 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -184,6 +184,20 @@ shared_module('nonlocalmeans',
install_dir: plugin_install_dir,
)
+# find large spots
+
+shared_module('findlargespots',
+ sources: [
+ 'ufo-find-large-spots-task.c',
+ 'common/ufo-math.c',
+ 'common/ufo-common.c',
+ ],
+ dependencies: deps,
+ name_prefix: 'libufofilter',
+ install: true,
+ install_dir: plugin_install_dir,
+)
+
# fft plugins
have_clfft = clfft_dep.found()
diff --git a/src/ufo-find-large-spots-task.c b/src/ufo-find-large-spots-task.c
new file mode 100644
index 0000000..9875ffc
--- /dev/null
+++ b/src/ufo-find-large-spots-task.c
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2011-2019 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-find-large-spots-task.h"
+#include "common/ufo-addressing.h"
+#include "common/ufo-common.h"
+
+typedef enum {
+ SPOT_THRESHOLD_BELOW = -1,
+ SPOT_THRESHOLD_ABSOLUTE,
+ SPOT_THRESHOLD_ABOVE
+} SpotThresholdMode;
+
+static GEnumValue spot_threshold_mode_values[] = {
+ { SPOT_THRESHOLD_BELOW, "SPOT_THRESHOLD_BELOW", "below" },
+ { SPOT_THRESHOLD_ABSOLUTE, "SPOT_THRESHOLD_ABSOLUTE", "absolute" },
+ { SPOT_THRESHOLD_ABOVE, "SPOT_THRESHOLD_ABOVE", "above" },
+ { 0, NULL, NULL}
+};
+
+struct _UfoFindLargeSpotsTaskPrivate {
+ gfloat spot_threshold;
+ SpotThresholdMode spot_threshold_mode;
+ gfloat grow_threshold;
+ cl_context context;
+ cl_kernel set_ones_kernel, set_threshold_kernel, grow_kernel, holes_kernel, convolution_kernel, sum_kernel;
+ cl_sampler sampler;
+ cl_mem aux_mem[2], counter_mem;
+ AddressingMode addressing_mode;
+};
+
+static void ufo_task_interface_init (UfoTaskIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (UfoFindLargeSpotsTask, ufo_find_large_spots_task, UFO_TYPE_TASK_NODE,
+ G_IMPLEMENT_INTERFACE (UFO_TYPE_TASK,
+ ufo_task_interface_init))
+
+#define UFO_FIND_LARGE_SPOTS_TASK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_FIND_LARGE_SPOTS_TASK, UfoFindLargeSpotsTaskPrivate))
+
+enum {
+ PROP_0,
+ PROP_SPOT_THRESHOLD_MODE,
+ PROP_SPOT_THRESHOLD,
+ PROP_GROW_THRESHOLD,
+ PROP_ADDRESSING_MODE,
+ N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+UfoNode *
+ufo_find_large_spots_task_new (void)
+{
+ return UFO_NODE (g_object_new (UFO_TYPE_FIND_LARGE_SPOTS_TASK, NULL));
+}
+
+static void
+ufo_find_large_spots_task_setup (UfoTask *task,
+ UfoResources *resources,
+ GError **error)
+{
+ cl_int err;
+ UfoFindLargeSpotsTaskPrivate *priv = UFO_FIND_LARGE_SPOTS_TASK_GET_PRIVATE (task);
+
+ priv->context = ufo_resources_get_context (resources);
+ UFO_RESOURCES_CHECK_SET_AND_RETURN (clRetainContext (priv->context), error);
+
+ priv->set_ones_kernel = ufo_resources_get_kernel (resources, "morphology.cl", "set_to_ones", NULL, error);
+ priv->set_threshold_kernel = ufo_resources_get_kernel (resources, "morphology.cl", "set_above_threshold", NULL, error);
+ priv->grow_kernel = ufo_resources_get_kernel (resources, "morphology.cl", "grow_region_above_threshold", NULL, error);
+ priv->holes_kernel = ufo_resources_get_kernel (resources, "morphology.cl", "fill_holes", NULL, error);
+ priv->convolution_kernel = ufo_resources_get_kernel (resources, "estimate-noise.cl", "convolve_abs_laplacian_diff", NULL, error);
+ priv->sum_kernel = ufo_resources_get_kernel (resources, "reductor.cl", "reduce_M_SUM", NULL, error);
+ for (gint i = 0; i < 2; i++) {
+ priv->aux_mem[i] = NULL;
+ }
+ priv->counter_mem = NULL;
+
+ if (priv->set_ones_kernel) {
+ UFO_RESOURCES_CHECK_SET_AND_RETURN (clRetainKernel (priv->set_ones_kernel), error);
+ }
+ if (priv->set_threshold_kernel) {
+ UFO_RESOURCES_CHECK_SET_AND_RETURN (clRetainKernel (priv->set_threshold_kernel), error);
+ }
+ if (priv->grow_kernel) {
+ UFO_RESOURCES_CHECK_SET_AND_RETURN (clRetainKernel (priv->grow_kernel), error);
+ }
+ if (priv->holes_kernel) {
+ UFO_RESOURCES_CHECK_SET_AND_RETURN (clRetainKernel (priv->holes_kernel), error);
+ }
+ if (priv->convolution_kernel) {
+ UFO_RESOURCES_CHECK_SET_AND_RETURN (clRetainKernel (priv->convolution_kernel), error);
+ }
+ if (priv->sum_kernel) {
+ UFO_RESOURCES_CHECK_SET_AND_RETURN (clRetainKernel (priv->sum_kernel), error);
+ }
+ priv->sampler = clCreateSampler (priv->context,
+ (cl_bool) TRUE,
+ priv->addressing_mode,
+ CL_FILTER_NEAREST,
+ &err);
+ UFO_RESOURCES_CHECK_CLERR (err);
+}
+
+static void
+ufo_find_large_spots_task_get_requisition (UfoTask *task,
+ UfoBuffer **inputs,
+ UfoRequisition *requisition,
+ GError **error)
+{
+ cl_int err;
+ UfoFindLargeSpotsTaskPrivate *priv = UFO_FIND_LARGE_SPOTS_TASK_GET_PRIVATE (task);
+
+ ufo_buffer_get_requisition (inputs[0], requisition);
+
+ if (!priv->aux_mem[0]) {
+ for (gint i = 0; i < 2; i++) {
+ priv->aux_mem[i] = clCreateBuffer (priv->context,
+ CL_MEM_READ_WRITE,
+ sizeof (cl_float) * requisition->dims[0] * requisition->dims[1],
+ NULL,
+ &err);
+ UFO_RESOURCES_CHECK_CLERR (err);
+ }
+ priv->counter_mem = clCreateBuffer (priv->context,
+ CL_MEM_READ_WRITE,
+ sizeof (cl_int),
+ NULL,
+ &err);
+ UFO_RESOURCES_CHECK_CLERR (err);
+ }
+}
+
+static guint
+ufo_find_large_spots_task_get_num_inputs (UfoTask *task)
+{
+ return 1;
+}
+
+static guint
+ufo_find_large_spots_task_get_num_dimensions (UfoTask *task,
+ guint input)
+{
+ return 2;
+}
+
+static UfoTaskMode
+ufo_find_large_spots_task_get_mode (UfoTask *task)
+{
+ return UFO_TASK_MODE_PROCESSOR | UFO_TASK_MODE_GPU;
+}
+
+static gboolean
+ufo_find_large_spots_task_process (UfoTask *task,
+ UfoBuffer **inputs,
+ UfoBuffer *output,
+ UfoRequisition *requisition)
+{
+ UfoFindLargeSpotsTaskPrivate *priv;
+ UfoGpuNode *node;
+ UfoProfiler *profiler;
+ GValue *max_work_group_size_gvalue;
+ gsize max_work_group_size;
+ cl_command_queue cmd_queue;
+ cl_mem in_mem;
+ cl_mem out_mem;
+ gfloat estimated_sigma;
+ gsize global_size[2];
+ gint counter = 1, fill_pattern = 0;
+
+ priv = UFO_FIND_LARGE_SPOTS_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);
+ out_mem = ufo_buffer_get_device_array (output, cmd_queue);
+ profiler = ufo_task_node_get_profiler (UFO_TASK_NODE (task));
+ global_size[0] = requisition->dims[0] - 2;
+ global_size[1] = requisition->dims[1] - 2;
+
+ if (priv->grow_threshold <= 0.0f) {
+ max_work_group_size_gvalue = ufo_gpu_node_get_info (node, UFO_GPU_NODE_INFO_MAX_WORK_GROUP_SIZE);
+ max_work_group_size = g_value_get_ulong (max_work_group_size_gvalue);
+ g_value_unset (max_work_group_size_gvalue);
+ in_mem = ufo_buffer_get_device_image (inputs[0], cmd_queue);
+ estimated_sigma = ufo_common_estimate_sigma (priv->convolution_kernel,
+ priv->sum_kernel,
+ cmd_queue,
+ priv->sampler,
+ profiler,
+ in_mem,
+ out_mem,
+ max_work_group_size,
+ requisition->dims);
+ /* IF not specified, make grow_threshold FWTM of the assumed noise normal distribution. */
+ priv->grow_threshold = 4.29 * estimated_sigma;
+ g_debug ("Estimated sigma: %g", estimated_sigma);
+ }
+ in_mem = ufo_buffer_get_device_array (inputs[0], cmd_queue);
+
+ /* First set the mask to 1 where spot_threshold is exceeded */
+ UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->set_threshold_kernel, 0, sizeof (cl_mem), &in_mem));
+ UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->set_threshold_kernel, 1, sizeof (cl_mem), &priv->aux_mem[0]));
+ UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->set_threshold_kernel, 2, sizeof (cl_int), &priv->spot_threshold));
+ UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->set_threshold_kernel, 3, sizeof (cl_int), &priv->spot_threshold_mode));
+ ufo_profiler_call (profiler, cmd_queue, priv->set_threshold_kernel, 2, requisition->dims, NULL);
+ UFO_RESOURCES_CHECK_CLERR (clEnqueueCopyBuffer (cmd_queue,
+ priv->aux_mem[0],
+ priv->aux_mem[1],
+ 0, 0, sizeof (cl_float) * requisition->dims[0] * requisition->dims[1],
+ 0, NULL, NULL));
+
+ while (counter) {
+ /* Grow the seeds until the difference between surrouding pixels is less
+ * than grow_threshold. */
+ /* Reset counter */
+ UFO_RESOURCES_CHECK_CLERR (clEnqueueFillBuffer (cmd_queue, priv->counter_mem, &fill_pattern, sizeof (cl_int),
+ 0, sizeof (cl_int), 0, NULL, NULL));
+
+ /* Grow region */
+ UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->grow_kernel, 0, sizeof (cl_mem), &in_mem));
+ UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->grow_kernel, 1, sizeof (cl_mem), &priv->aux_mem[0]));
+ UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->grow_kernel, 2, sizeof (cl_mem), &priv->aux_mem[1]));
+ UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->grow_kernel, 3, sizeof (cl_mem), &priv->counter_mem));
+ UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->grow_kernel, 4, sizeof (cl_int), &priv->grow_threshold));
+ ufo_profiler_call (profiler, cmd_queue, priv->grow_kernel, 2, global_size, NULL);
+ /* New visited is the last grown. */
+ UFO_RESOURCES_CHECK_CLERR (clEnqueueCopyBuffer (cmd_queue,
+ priv->aux_mem[1],
+ priv->aux_mem[0],
+ 0, 0, sizeof (cl_float) * requisition->dims[0] * requisition->dims[1],
+ 0, NULL, NULL));
+ UFO_RESOURCES_CHECK_CLERR (clEnqueueReadBuffer (cmd_queue,
+ priv->counter_mem,
+ CL_TRUE,
+ 0,
+ sizeof (cl_int),
+ &counter,
+ 0, NULL, NULL));
+ }
+
+ /* Initialize resulting mask to ones except borders and pixels where current
+ * mask is set. This will serve for growing the boundary towards the center,
+ * i.e. filling holes. From now on, aux_mem[0] is the fixed mask with holes
+ * and aux_mem[1] with out_mem are the result/visited pair.
+ */
+ UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->set_ones_kernel, 0, sizeof (cl_mem), &priv->aux_mem[1]));
+ ufo_profiler_call (profiler, cmd_queue, priv->set_ones_kernel, 2, global_size, NULL);
+ UFO_RESOURCES_CHECK_CLERR (clEnqueueCopyBuffer (cmd_queue,
+ priv->aux_mem[1],
+ out_mem,
+ 0, 0, sizeof (cl_float) * requisition->dims[0] * requisition->dims[1],
+ 0, NULL, NULL));
+
+ counter = 1;
+ while (counter) {
+ /* Fill holes by progressing from the edges towards the center and
+ * taking into account the pre-computed mask. */
+ /* Reset counter */
+ UFO_RESOURCES_CHECK_CLERR (clEnqueueFillBuffer (cmd_queue, priv->counter_mem, &fill_pattern, sizeof (cl_int),
+ 0, sizeof (cl_int), 0, NULL, NULL));
+
+ /* Grow region towards the center */
+ UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->holes_kernel, 0, sizeof (cl_mem), &priv->aux_mem[0]));
+ UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->holes_kernel, 1, sizeof (cl_mem), &priv->aux_mem[1]));
+ UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->holes_kernel, 2, sizeof (cl_mem), &out_mem));
+ UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->holes_kernel, 3, sizeof (cl_mem), &priv->counter_mem));
+ ufo_profiler_call (profiler, cmd_queue, priv->holes_kernel, 2, global_size, NULL);
+ /* New visited is the last grown. */
+ UFO_RESOURCES_CHECK_CLERR (clEnqueueCopyBuffer (cmd_queue,
+ out_mem,
+ priv->aux_mem[1],
+ 0, 0, sizeof (cl_float) * requisition->dims[0] * requisition->dims[1],
+ 0, NULL, NULL));
+ UFO_RESOURCES_CHECK_CLERR (clEnqueueReadBuffer (cmd_queue,
+ priv->counter_mem,
+ CL_TRUE,
+ 0,
+ sizeof (cl_int),
+ &counter,
+ 0, NULL, NULL));
+ }
+
+ return TRUE;
+}
+
+
+static void
+ufo_find_large_spots_task_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ UfoFindLargeSpotsTaskPrivate *priv = UFO_FIND_LARGE_SPOTS_TASK_GET_PRIVATE (object);
+
+ switch (property_id) {
+ case PROP_SPOT_THRESHOLD:
+ priv->spot_threshold = g_value_get_float (value);
+ break;
+ case PROP_SPOT_THRESHOLD_MODE:
+ priv->spot_threshold_mode = g_value_get_enum (value);
+ break;
+ case PROP_GROW_THRESHOLD:
+ priv->grow_threshold = g_value_get_float (value);
+ break;
+ case PROP_ADDRESSING_MODE:
+ priv->addressing_mode = g_value_get_enum (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+ufo_find_large_spots_task_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ UfoFindLargeSpotsTaskPrivate *priv = UFO_FIND_LARGE_SPOTS_TASK_GET_PRIVATE (object);
+
+ switch (property_id) {
+ case PROP_SPOT_THRESHOLD:
+ g_value_set_float (value, priv->spot_threshold);
+ break;
+ case PROP_SPOT_THRESHOLD_MODE:
+ g_value_set_enum (value, priv->spot_threshold_mode);
+ break;
+ case PROP_GROW_THRESHOLD:
+ g_value_set_float (value, priv->grow_threshold);
+ break;
+ case PROP_ADDRESSING_MODE:
+ g_value_set_enum (value, priv->addressing_mode);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+ufo_find_large_spots_task_finalize (GObject *object)
+{
+ UfoFindLargeSpotsTaskPrivate *priv = UFO_FIND_LARGE_SPOTS_TASK_GET_PRIVATE (object);
+
+ if (priv->set_ones_kernel) {
+ UFO_RESOURCES_CHECK_CLERR (clReleaseKernel (priv->set_ones_kernel));
+ priv->set_ones_kernel = NULL;
+ }
+ if (priv->set_threshold_kernel) {
+ UFO_RESOURCES_CHECK_CLERR (clReleaseKernel (priv->set_threshold_kernel));
+ priv->set_threshold_kernel = NULL;
+ }
+ if (priv->grow_kernel) {
+ UFO_RESOURCES_CHECK_CLERR (clReleaseKernel (priv->grow_kernel));
+ priv->grow_kernel = NULL;
+ }
+ if (priv->holes_kernel) {
+ UFO_RESOURCES_CHECK_CLERR (clReleaseKernel (priv->holes_kernel));
+ priv->holes_kernel = NULL;
+ }
+ if (priv->convolution_kernel) {
+ UFO_RESOURCES_CHECK_CLERR (clReleaseKernel (priv->convolution_kernel));
+ priv->convolution_kernel = NULL;
+ }
+ if (priv->sum_kernel) {
+ UFO_RESOURCES_CHECK_CLERR (clReleaseKernel (priv->sum_kernel));
+ priv->sum_kernel = NULL;
+ }
+ if (priv->sampler) {
+ UFO_RESOURCES_CHECK_CLERR (clReleaseSampler (priv->sampler));
+ priv->sampler = NULL;
+ }
+ for (gint i = 0; i < 2; i++) {
+ if (priv->aux_mem[i]) {
+ UFO_RESOURCES_CHECK_CLERR (clReleaseMemObject (priv->aux_mem[i]));
+ priv->aux_mem[i] = NULL;
+ }
+ }
+ if (priv->counter_mem) {
+ UFO_RESOURCES_CHECK_CLERR (clReleaseMemObject (priv->counter_mem));
+ priv->counter_mem = NULL;
+ }
+ if (priv->context) {
+ UFO_RESOURCES_CHECK_CLERR (clReleaseContext (priv->context));
+ priv->context = NULL;
+ }
+
+ G_OBJECT_CLASS (ufo_find_large_spots_task_parent_class)->finalize (object);
+}
+
+static void
+ufo_task_interface_init (UfoTaskIface *iface)
+{
+ iface->setup = ufo_find_large_spots_task_setup;
+ iface->get_num_inputs = ufo_find_large_spots_task_get_num_inputs;
+ iface->get_num_dimensions = ufo_find_large_spots_task_get_num_dimensions;
+ iface->get_mode = ufo_find_large_spots_task_get_mode;
+ iface->get_requisition = ufo_find_large_spots_task_get_requisition;
+ iface->process = ufo_find_large_spots_task_process;
+}
+
+static void
+ufo_find_large_spots_task_class_init (UfoFindLargeSpotsTaskClass *klass)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (klass);
+
+ oclass->set_property = ufo_find_large_spots_task_set_property;
+ oclass->get_property = ufo_find_large_spots_task_get_property;
+ oclass->finalize = ufo_find_large_spots_task_finalize;
+
+ properties[PROP_SPOT_THRESHOLD] =
+ g_param_spec_float ("spot-threshold",
+ "Pixels with grey value larger than this are considered as spots",
+ "Pixels with grey value larger than this are considered as spots",
+ -G_MAXFLOAT, G_MAXFLOAT, 0.0f,
+ G_PARAM_READWRITE);
+
+ properties[PROP_SPOT_THRESHOLD_MODE] =
+ g_param_spec_enum ("spot-threshold-mode",
+ "Pixels must be either \"below\", \"above\" the spot threshold, or their \"absolute\" value can be compared",
+ "Pixels must be either \"below\", \"above\" the spot threshold, or their \"absolute\" value can be compared",
+ g_enum_register_static ("spot-threshold-mode", spot_threshold_mode_values),
+ SPOT_THRESHOLD_ABSOLUTE, G_PARAM_READWRITE);
+
+ properties[PROP_GROW_THRESHOLD] =
+ g_param_spec_float ("grow-threshold",
+ "Spot growing threshold",
+ "Spot growing threshold",
+ 0.0f, G_MAXFLOAT, 0.0f,
+ G_PARAM_READWRITE);
+
+ properties[PROP_ADDRESSING_MODE] =
+ g_param_spec_enum ("addressing-mode",
+ "Outlier treatment (\"none\", \"clamp\", \"clamp_to_edge\", \"repeat\", \"mirrored_repeat\")",
+ "Outlier treatment (\"none\", \"clamp\", \"clamp_to_edge\", \"repeat\", \"mirrored_repeat\")",
+ g_enum_register_static ("find_addressing_mode", addressing_values),
+ CL_ADDRESS_MIRRORED_REPEAT,
+ 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(UfoFindLargeSpotsTaskPrivate));
+}
+
+static void
+ufo_find_large_spots_task_init(UfoFindLargeSpotsTask *self)
+{
+ self->priv = UFO_FIND_LARGE_SPOTS_TASK_GET_PRIVATE(self);
+ self->priv->spot_threshold = 0.0f;
+ self->priv->grow_threshold = 0.0f;
+ self->priv->spot_threshold_mode = SPOT_THRESHOLD_ABSOLUTE;
+ self->priv->addressing_mode = CL_ADDRESS_MIRRORED_REPEAT;
+}
diff --git a/src/ufo-find-large-spots-task.h b/src/ufo-find-large-spots-task.h
new file mode 100644
index 0000000..6afbfe0
--- /dev/null
+++ b/src/ufo-find-large-spots-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_FIND_LARGE_SPOTS_TASK_H
+#define __UFO_FIND_LARGE_SPOTS_TASK_H
+
+#include <ufo/ufo.h>
+
+G_BEGIN_DECLS
+
+#define UFO_TYPE_FIND_LARGE_SPOTS_TASK (ufo_find_large_spots_task_get_type())
+#define UFO_FIND_LARGE_SPOTS_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_FIND_LARGE_SPOTS_TASK, UfoFindLargeSpotsTask))
+#define UFO_IS_FIND_LARGE_SPOTS_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_FIND_LARGE_SPOTS_TASK))
+#define UFO_FIND_LARGE_SPOTS_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_FIND_LARGE_SPOTS_TASK, UfoFindLargeSpotsTaskClass))
+#define UFO_IS_FIND_LARGE_SPOTS_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_FIND_LARGE_SPOTS_TASK))
+#define UFO_FIND_LARGE_SPOTS_TASK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_FIND_LARGE_SPOTS_TASK, UfoFindLargeSpotsTaskClass))
+
+typedef struct _UfoFindLargeSpotsTask UfoFindLargeSpotsTask;
+typedef struct _UfoFindLargeSpotsTaskClass UfoFindLargeSpotsTaskClass;
+typedef struct _UfoFindLargeSpotsTaskPrivate UfoFindLargeSpotsTaskPrivate;
+
+struct _UfoFindLargeSpotsTask {
+ UfoTaskNode parent_instance;
+
+ UfoFindLargeSpotsTaskPrivate *priv;
+};
+
+struct _UfoFindLargeSpotsTaskClass {
+ UfoTaskNodeClass parent_class;
+};
+
+UfoNode *ufo_find_large_spots_task_new (void);
+GType ufo_find_large_spots_task_get_type (void);
+
+G_END_DECLS
+
+#endif