From 54f98c09431faafd5fb952c291b6dfb2179d4229 Mon Sep 17 00:00:00 2001 From: Tomas Farago Date: Fri, 20 Mar 2020 16:37:12 +0100 Subject: Add sliding-stack task fixes #196. --- docs/filters.rst | 17 ++++ src/CMakeLists.txt | 1 + src/meson.build | 1 + src/ufo-sliding-stack-task.c | 231 +++++++++++++++++++++++++++++++++++++++++++ src/ufo-sliding-stack-task.h | 53 ++++++++++ 5 files changed, 303 insertions(+) create mode 100644 src/ufo-sliding-stack-task.c create mode 100644 src/ufo-sliding-stack-task.h diff --git a/docs/filters.rst b/docs/filters.rst index 0e571b9..76b16e7 100644 --- a/docs/filters.rst +++ b/docs/filters.rst @@ -758,6 +758,23 @@ Stacking Number of items, i.e. the length of the third dimension. +Stacking with sliding window +---------------------------- + +.. gobj:class:: sliding-stack + + Stacks input images up to the specified :gobj:prop:`number` and then + replaces old images with incoming new ones as they come. The first image is + copied to all positions in the beginning. Images in the window are not + ordered, i.e. if e.g. :gobj:prop:`number` = 3, then the window will contain + the following input images: (0, 0, 0), (0, 1, 0), (0, 1, 2), (3, 1, 2), (3, + 4, 2), (3, 4, 5) and so on. + + .. gobj:prop:: number:uint + + Number of items, i.e. the length of the third dimension. + + Merging ------- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index babf659..1aca963 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -77,6 +77,7 @@ set(ufofilter_SRCS ufo-rotate-task.c ufo-sleep-task.c ufo-slice-task.c + ufo-sliding-stack-task.c ufo-stack-task.c ufo-stdin-task.c ufo-stitch-task.c diff --git a/src/meson.build b/src/meson.build index 3287438..dffac34 100644 --- a/src/meson.build +++ b/src/meson.build @@ -66,6 +66,7 @@ plugins = [ 'segment', 'sleep', 'slice', + 'sliding-stack', 'stack', 'stitch', 'stdin', diff --git a/src/ufo-sliding-stack-task.c b/src/ufo-sliding-stack-task.c new file mode 100644 index 0000000..eb012bf --- /dev/null +++ b/src/ufo-sliding-stack-task.c @@ -0,0 +1,231 @@ +/* + * 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 . + */ + +#include +#include "ufo-sliding-stack-task.h" + + +struct _UfoSlidingStackTaskPrivate { + guint n_items; + guint current; + guint8 *window; +}; + +static void ufo_task_interface_init (UfoTaskIface *iface); + +G_DEFINE_TYPE_WITH_CODE (UfoSlidingStackTask, ufo_sliding_stack_task, UFO_TYPE_TASK_NODE, + G_IMPLEMENT_INTERFACE (UFO_TYPE_TASK, + ufo_task_interface_init)) + +#define UFO_SLIDING_STACK_TASK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_SLIDING_STACK_TASK, UfoSlidingStackTaskPrivate)) + +enum { + PROP_0, + PROP_NUM_ITEMS, + N_PROPERTIES +}; + +static GParamSpec *properties[N_PROPERTIES] = { NULL, }; + +UfoNode * +ufo_sliding_stack_task_new (void) +{ + return UFO_NODE (g_object_new (UFO_TYPE_SLIDING_STACK_TASK, NULL)); +} + +static void +ufo_sliding_stack_task_setup (UfoTask *task, + UfoResources *resources, + GError **error) +{ + UfoSlidingStackTaskPrivate *priv; + + priv = UFO_SLIDING_STACK_TASK_GET_PRIVATE (task); + priv->current = 0; +} + +static void +ufo_sliding_stack_task_get_requisition (UfoTask *task, + UfoBuffer **inputs, + UfoRequisition *requisition, + GError **error) +{ + UfoSlidingStackTaskPrivate *priv; + + priv = UFO_SLIDING_STACK_TASK_GET_PRIVATE (task); + + ufo_buffer_get_requisition (inputs[0], requisition); + requisition->n_dims = 3; + requisition->dims[2] = priv->n_items; + + if (priv->window == NULL) { + priv->window = g_malloc0 (requisition->dims[0] * + requisition->dims[1] * + requisition->dims[2] * sizeof (gfloat)); + } +} + +static guint +ufo_sliding_stack_task_get_num_inputs (UfoTask *task) +{ + return 1; +} + +static guint +ufo_sliding_stack_task_get_num_dimensions (UfoTask *task, + guint input) +{ + return 2; +} + +static UfoTaskMode +ufo_sliding_stack_task_get_mode (UfoTask *task) +{ + return UFO_TASK_MODE_PROCESSOR | UFO_TASK_MODE_CPU; +} + +static gboolean +ufo_sliding_stack_task_process (UfoTask *task, + UfoBuffer **inputs, + UfoBuffer *output, + UfoRequisition *requisition) +{ + UfoSlidingStackTaskPrivate *priv; + guint8 *in_mem; + guint8 *out_mem; + gsize size, window_size; + guint i; + + priv = UFO_SLIDING_STACK_TASK_GET_PRIVATE (task); + + size = ufo_buffer_get_size (inputs[0]); + window_size = requisition->dims[0] * requisition->dims[1] * requisition->dims[2] * sizeof (gfloat); + in_mem = (guint8 *) ufo_buffer_get_host_array (inputs[0], NULL); + out_mem = (guint8 *) ufo_buffer_get_host_array (output, NULL); + memcpy (priv->window + priv->current % priv->n_items * size, in_mem, size); + priv->current++; + + if (priv->current == 1) { + /* Copy the first input to the whole window. */ + for (i = 1; i < priv->n_items; i++) { + memcpy (priv->window + i * size, in_mem, size); + } + } + + /* The double buffering prevents us to use *out_mem* directly, because we would + * replace even indices in one output buffer and odd in the other. So we + * need to keep a copy of the input locally and copy to the output. + * TODO: improve this on a lower level in ufo-core. */ + memcpy (out_mem, priv->window, window_size); + + return TRUE; +} + + +static void +ufo_sliding_stack_task_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + UfoSlidingStackTaskPrivate *priv = UFO_SLIDING_STACK_TASK_GET_PRIVATE (object); + + switch (property_id) { + case PROP_NUM_ITEMS: + priv->n_items = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +ufo_sliding_stack_task_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + UfoSlidingStackTaskPrivate *priv = UFO_SLIDING_STACK_TASK_GET_PRIVATE (object); + + switch (property_id) { + case PROP_NUM_ITEMS: + g_value_set_uint (value, priv->n_items); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +ufo_sliding_stack_task_finalize (GObject *object) +{ + UfoSlidingStackTaskPrivate *priv; + + priv = UFO_SLIDING_STACK_TASK_GET_PRIVATE (object); + + if (priv->window) { + g_free (priv->window); + priv->window = NULL; + } + + G_OBJECT_CLASS (ufo_sliding_stack_task_parent_class)->finalize (object); +} + +static void +ufo_task_interface_init (UfoTaskIface *iface) +{ + iface->setup = ufo_sliding_stack_task_setup; + iface->get_num_inputs = ufo_sliding_stack_task_get_num_inputs; + iface->get_num_dimensions = ufo_sliding_stack_task_get_num_dimensions; + iface->get_mode = ufo_sliding_stack_task_get_mode; + iface->get_requisition = ufo_sliding_stack_task_get_requisition; + iface->process = ufo_sliding_stack_task_process; +} + +static void +ufo_sliding_stack_task_class_init (UfoSlidingStackTaskClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS (klass); + + oclass->set_property = ufo_sliding_stack_task_set_property; + oclass->get_property = ufo_sliding_stack_task_get_property; + oclass->finalize = ufo_sliding_stack_task_finalize; + + properties[PROP_NUM_ITEMS] = + g_param_spec_uint ("number", + "Number of items in the sliding window", + "Number of items in the sliding window", + 1, G_MAXUINT, 1, + 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(UfoSlidingStackTaskPrivate)); +} + +static void +ufo_sliding_stack_task_init(UfoSlidingStackTask *self) +{ + self->priv = UFO_SLIDING_STACK_TASK_GET_PRIVATE(self); + self->priv->n_items = 1; + self->priv->window = NULL; +} diff --git a/src/ufo-sliding-stack-task.h b/src/ufo-sliding-stack-task.h new file mode 100644 index 0000000..647932f --- /dev/null +++ b/src/ufo-sliding-stack-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 . + */ + +#ifndef __UFO_SLIDING_STACK_TASK_H +#define __UFO_SLIDING_STACK_TASK_H + +#include + +G_BEGIN_DECLS + +#define UFO_TYPE_SLIDING_STACK_TASK (ufo_sliding_stack_task_get_type()) +#define UFO_SLIDING_STACK_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UFO_TYPE_SLIDING_STACK_TASK, UfoSlidingStackTask)) +#define UFO_IS_SLIDING_STACK_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UFO_TYPE_SLIDING_STACK_TASK)) +#define UFO_SLIDING_STACK_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_SLIDING_STACK_TASK, UfoSlidingStackTaskClass)) +#define UFO_IS_SLIDING_STACK_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UFO_TYPE_SLIDING_STACK_TASK)) +#define UFO_SLIDING_STACK_TASK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UFO_TYPE_SLIDING_STACK_TASK, UfoSlidingStackTaskClass)) + +typedef struct _UfoSlidingStackTask UfoSlidingStackTask; +typedef struct _UfoSlidingStackTaskClass UfoSlidingStackTaskClass; +typedef struct _UfoSlidingStackTaskPrivate UfoSlidingStackTaskPrivate; + +struct _UfoSlidingStackTask { + UfoTaskNode parent_instance; + + UfoSlidingStackTaskPrivate *priv; +}; + +struct _UfoSlidingStackTaskClass { + UfoTaskNodeClass parent_class; +}; + +UfoNode *ufo_sliding_stack_task_new (void); +GType ufo_sliding_stack_task_get_type (void); + +G_END_DECLS + +#endif -- cgit v1.2.1