ufo-remove-stripes-task.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. * Copyright (C) 2011-2014 Karlsruhe Institute of Technology
  3. *
  4. * This file is part of Ufo.
  5. *
  6. * This library is free software: you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation, either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifdef __APPLE__
  20. #include <OpenCL/cl.h>
  21. #else
  22. #include <CL/cl.h>
  23. #endif
  24. #include <math.h>
  25. #include "ufo-remove-stripes-task.h"
  26. /**
  27. * SECTION:ufo-remove-stripes-task
  28. * @Short_description: Remove stripes from 2D images, requires frequency domain
  29. * input
  30. * @Title: remove_stripes
  31. *
  32. */
  33. struct _UfoRemoveStripesTaskPrivate {
  34. guint last_width;
  35. /* OpenCL */
  36. cl_context context;
  37. cl_kernel kernel;
  38. cl_mem filter_mem;
  39. /* properties */
  40. gfloat strength;
  41. };
  42. static void ufo_task_interface_init (UfoTaskIface *iface);
  43. G_DEFINE_TYPE_WITH_CODE (UfoRemoveStripesTask, ufo_remove_stripes_task, UFO_TYPE_TASK_NODE,
  44. G_IMPLEMENT_INTERFACE (UFO_TYPE_TASK,
  45. ufo_task_interface_init))
  46. #define UFO_REMOVE_STRIPES_TASK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_REMOVE_STRIPES_TASK, UfoRemoveStripesTaskPrivate))
  47. enum {
  48. PROP_0,
  49. PROP_STRENGTH,
  50. N_PROPERTIES
  51. };
  52. static GParamSpec *properties[N_PROPERTIES] = { NULL, };
  53. /**
  54. * create_coefficients:
  55. * @priv: UfoRemoveStripesTaskPrivate
  56. * @width: image width (not the interleaved from fft, rather the real width)
  57. *
  58. * Compute symmetric filter coefficients.
  59. */
  60. static void
  61. create_coefficients (UfoRemoveStripesTaskPrivate *priv, const guint width)
  62. {
  63. gfloat *coefficients = g_malloc0 (sizeof (gfloat) * width);
  64. gfloat sigma = priv->strength / (2.0 * sqrt (2.0 * log (2.0)));
  65. /* Divided by 2 because of the symmetry and we need the +1 to correctly handle
  66. * the frequency at width / 2 */
  67. const guint real_width = width / 2 + 1;
  68. cl_int cl_err;
  69. if (!coefficients) {
  70. g_warning ("Could not allocate memory for coeefficients");
  71. }
  72. if (width % 2) {
  73. g_warning ("Width must be an even number");
  74. }
  75. for (gint x = 0; x < (gint) real_width; x++) {
  76. coefficients[x] = 1.0f - exp (- x * x / (sigma * sigma * 2.0f));
  77. }
  78. if (priv->filter_mem) {
  79. UFO_RESOURCES_CHECK_CLERR (clReleaseMemObject (priv->filter_mem));
  80. }
  81. priv->filter_mem = clCreateBuffer (priv->context,
  82. CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
  83. sizeof (cl_float) * real_width,
  84. coefficients,
  85. &cl_err);
  86. UFO_RESOURCES_CHECK_CLERR (cl_err);
  87. g_free (coefficients);
  88. priv->last_width = width;
  89. }
  90. UfoNode *
  91. ufo_remove_stripes_task_new (void)
  92. {
  93. return UFO_NODE (g_object_new (UFO_TYPE_REMOVE_STRIPES_TASK, NULL));
  94. }
  95. static void
  96. ufo_remove_stripes_task_setup (UfoTask *task,
  97. UfoResources *resources,
  98. GError **error)
  99. {
  100. UfoRemoveStripesTaskPrivate *priv;
  101. priv = UFO_REMOVE_STRIPES_TASK_GET_PRIVATE (task);
  102. priv->context = ufo_resources_get_context (resources);
  103. priv->kernel = ufo_resources_get_kernel (resources, "ankacomplex.cl", "multiply_frequencies_with_real_sym", error);
  104. priv->filter_mem = NULL;
  105. UFO_RESOURCES_CHECK_CLERR (clRetainContext (priv->context));
  106. if (priv->kernel) {
  107. UFO_RESOURCES_CHECK_CLERR (clRetainKernel (priv->kernel));
  108. }
  109. }
  110. static void
  111. ufo_remove_stripes_task_get_requisition (UfoTask *task,
  112. UfoBuffer **inputs,
  113. UfoRequisition *requisition)
  114. {
  115. UfoRemoveStripesTaskPrivate *priv;
  116. priv = UFO_REMOVE_STRIPES_TASK_GET_PRIVATE (task);
  117. ufo_buffer_get_requisition (inputs[0], requisition);
  118. if (!priv->filter_mem || requisition->dims[0] / 2 != priv->last_width) {
  119. create_coefficients (priv, requisition->dims[0] / 2);
  120. }
  121. }
  122. static guint
  123. ufo_remove_stripes_task_get_num_inputs (UfoTask *task)
  124. {
  125. return 1;
  126. }
  127. static guint
  128. ufo_remove_stripes_task_get_num_dimensions (UfoTask *task,
  129. guint input)
  130. {
  131. g_return_val_if_fail (input == 0, 0);
  132. return 2;
  133. }
  134. static UfoTaskMode
  135. ufo_remove_stripes_task_get_mode (UfoTask *task)
  136. {
  137. return UFO_TASK_MODE_PROCESSOR | UFO_TASK_MODE_GPU;
  138. }
  139. static gboolean
  140. ufo_remove_stripes_task_process (UfoTask *task,
  141. UfoBuffer **inputs,
  142. UfoBuffer *output,
  143. UfoRequisition *requisition)
  144. {
  145. UfoRemoveStripesTaskPrivate *priv;
  146. UfoGpuNode *node;
  147. UfoProfiler *profiler;
  148. cl_command_queue cmd_queue;
  149. cl_mem in_mem;
  150. cl_mem out_mem;
  151. priv = UFO_REMOVE_STRIPES_TASK_GET_PRIVATE (task);
  152. node = UFO_GPU_NODE (ufo_task_node_get_proc_node (UFO_TASK_NODE (task)));
  153. cmd_queue = ufo_gpu_node_get_cmd_queue (node);
  154. out_mem = ufo_buffer_get_device_array (output, cmd_queue);
  155. in_mem = ufo_buffer_get_device_array (inputs[0], cmd_queue);
  156. UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->kernel, 0, sizeof (cl_mem), &in_mem));
  157. UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->kernel, 1, sizeof (cl_mem), &out_mem));
  158. UFO_RESOURCES_CHECK_CLERR (clSetKernelArg (priv->kernel, 2, sizeof (cl_mem), &priv->filter_mem));
  159. profiler = ufo_task_node_get_profiler (UFO_TASK_NODE (task));
  160. ufo_profiler_call (profiler, cmd_queue, priv->kernel, 2, requisition->dims, NULL);
  161. return TRUE;
  162. }
  163. static void
  164. ufo_remove_stripes_task_set_property (GObject *object,
  165. guint property_id,
  166. const GValue *value,
  167. GParamSpec *pspec)
  168. {
  169. UfoRemoveStripesTaskPrivate *priv = UFO_REMOVE_STRIPES_TASK_GET_PRIVATE (object);
  170. switch (property_id) {
  171. case PROP_STRENGTH:
  172. priv->strength = g_value_get_float (value);
  173. if (priv->last_width) {
  174. /* Update only if we know how big the data is */
  175. create_coefficients (priv, priv->last_width);
  176. }
  177. break;
  178. default:
  179. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  180. break;
  181. }
  182. }
  183. static void
  184. ufo_remove_stripes_task_get_property (GObject *object,
  185. guint property_id,
  186. GValue *value,
  187. GParamSpec *pspec)
  188. {
  189. UfoRemoveStripesTaskPrivate *priv = UFO_REMOVE_STRIPES_TASK_GET_PRIVATE (object);
  190. switch (property_id) {
  191. case PROP_STRENGTH:
  192. g_value_set_float (value, priv->strength);
  193. break;
  194. default:
  195. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  196. break;
  197. }
  198. }
  199. static void
  200. ufo_remove_stripes_task_finalize (GObject *object)
  201. {
  202. UfoRemoveStripesTaskPrivate *priv;
  203. priv = UFO_REMOVE_STRIPES_TASK_GET_PRIVATE (object);
  204. if (priv->filter_mem) {
  205. UFO_RESOURCES_CHECK_CLERR (clReleaseMemObject (priv->filter_mem));
  206. priv->filter_mem = NULL;
  207. }
  208. if (priv->kernel) {
  209. UFO_RESOURCES_CHECK_CLERR (clReleaseKernel (priv->kernel));
  210. priv->kernel = NULL;
  211. }
  212. if (priv->context) {
  213. UFO_RESOURCES_CHECK_CLERR (clReleaseContext (priv->context));
  214. priv->context = NULL;
  215. }
  216. G_OBJECT_CLASS (ufo_remove_stripes_task_parent_class)->finalize (object);
  217. }
  218. static void
  219. ufo_task_interface_init (UfoTaskIface *iface)
  220. {
  221. iface->setup = ufo_remove_stripes_task_setup;
  222. iface->get_num_inputs = ufo_remove_stripes_task_get_num_inputs;
  223. iface->get_num_dimensions = ufo_remove_stripes_task_get_num_dimensions;
  224. iface->get_mode = ufo_remove_stripes_task_get_mode;
  225. iface->get_requisition = ufo_remove_stripes_task_get_requisition;
  226. iface->process = ufo_remove_stripes_task_process;
  227. }
  228. static void
  229. ufo_remove_stripes_task_class_init (UfoRemoveStripesTaskClass *klass)
  230. {
  231. GObjectClass *oclass = G_OBJECT_CLASS (klass);
  232. oclass->set_property = ufo_remove_stripes_task_set_property;
  233. oclass->get_property = ufo_remove_stripes_task_get_property;
  234. oclass->finalize = ufo_remove_stripes_task_finalize;
  235. properties[PROP_STRENGTH] =
  236. g_param_spec_float ("strength",
  237. "Filter strength",
  238. "Filter strength, it is the full width at half maximum of a Gaussian "\
  239. "in the frequency domain. The real filter is then 1 - Gaussian",
  240. 1e-3f, G_MAXFLOAT, 1.0f,
  241. G_PARAM_READWRITE);
  242. for (guint i = PROP_0 + 1; i < N_PROPERTIES; i++)
  243. g_object_class_install_property (oclass, i, properties[i]);
  244. g_type_class_add_private (oclass, sizeof(UfoRemoveStripesTaskPrivate));
  245. }
  246. static void
  247. ufo_remove_stripes_task_init(UfoRemoveStripesTask *self)
  248. {
  249. self->priv = UFO_REMOVE_STRIPES_TASK_GET_PRIVATE(self);
  250. self->priv->strength = 1.0f;
  251. self->priv->last_width = 0;
  252. }