3 * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
23 * Alternatively, the contents of this file may be used under the
24 * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
25 * which case the following provisions apply instead of the ones
28 * This library is free software; you can redistribute it and/or
29 * modify it under the terms of the GNU Library General Public
30 * License as published by the Free Software Foundation; either
31 * version 2 of the License, or (at your option) any later version.
33 * This library is distributed in the hope that it will be useful,
34 * but WITHOUT ANY WARRANTY; without even the implied warranty of
35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36 * Library General Public License for more details.
38 * You should have received a copy of the GNU Library General Public
39 * License along with this library; if not, write to the
40 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
41 * Boston, MA 02110-1301, USA.
45 * SECTION:element-cvsmooth
47 * Smooths the image using thes cvSmooth OpenCV function.
49 * ## Example launch line
52 * gst-launch-1.0 videotestsrc ! cvsmooth ! videoconvert ! autovideosink
60 #include "gst/opencv/gstopencvutils.h"
61 #include "gstcvsmooth.h"
62 #include <opencv2/imgproc.hpp>
65 GST_DEBUG_CATEGORY_STATIC (gst_cv_smooth_debug);
66 #define GST_CAT_DEFAULT gst_cv_smooth_debug
69 /* Filter signals and args */
89 /* blur-no-scale only handle: gray 8bits -> gray 16bits
90 * FIXME there is no way in base transform to override pad's getcaps
91 * to be property-sensitive, instead of using the template caps as
92 * the base caps, this might lead us to negotiating rgb in this
95 * Keep it deactivated for now.
98 enum GstCvSmoothMethod
101 GST_SMOOTH_GAUSSIAN = 2,
102 GST_SMOOTH_MEDIAN = 3,
103 GST_SMOOTH_BILATERAL = 4
107 #define GST_TYPE_CV_SMOOTH_TYPE (gst_cv_smooth_type_get_type ())
109 gst_cv_smooth_type_get_type (void)
111 static GType cv_smooth_type_type = 0;
113 static const GEnumValue smooth_types[] = {
114 {GST_SMOOTH_BLUR, "CV Blur", "blur"},
115 {GST_SMOOTH_GAUSSIAN, "CV Gaussian", "gaussian"},
116 {GST_SMOOTH_MEDIAN, "CV Median", "median"},
117 {GST_SMOOTH_BILATERAL, "CV Bilateral", "bilateral"},
121 if (!cv_smooth_type_type) {
122 cv_smooth_type_type =
123 g_enum_register_static ("GstCvSmoothTypeType", smooth_types);
125 return cv_smooth_type_type;
128 #define DEFAULT_CV_SMOOTH_TYPE GST_SMOOTH_GAUSSIAN
129 #define DEFAULT_KERNELWIDTH 3
130 #define DEFAULT_KERNELHEIGHT 3
131 #define DEFAULT_COLORSIGMA 0.0
132 #define DEFAULT_SPATIALSIGMA 0.0
133 #define DEFAULT_POSITION_X 0
134 #define DEFAULT_POSITION_Y 0
135 #define DEFAULT_WIDTH G_MAXINT
136 #define DEFAULT_HEIGHT G_MAXINT
138 G_DEFINE_TYPE (GstCvSmooth, gst_cv_smooth, GST_TYPE_OPENCV_VIDEO_FILTER);
140 static void gst_cv_smooth_set_property (GObject * object, guint prop_id,
141 const GValue * value, GParamSpec * pspec);
142 static void gst_cv_smooth_get_property (GObject * object, guint prop_id,
143 GValue * value, GParamSpec * pspec);
145 static GstFlowReturn gst_cv_smooth_transform_ip (GstOpencvVideoFilter *
146 filter, GstBuffer * buf, Mat img);
148 /* initialize the cvsmooth's class */
150 gst_cv_smooth_class_init (GstCvSmoothClass * klass)
152 GObjectClass *gobject_class;
153 GstOpencvVideoFilterClass *gstopencvbasefilter_class;
154 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
156 GstPadTemplate *templ;
158 gobject_class = (GObjectClass *) klass;
159 gstopencvbasefilter_class = (GstOpencvVideoFilterClass *) klass;
161 gobject_class->set_property = gst_cv_smooth_set_property;
162 gobject_class->get_property = gst_cv_smooth_get_property;
164 gstopencvbasefilter_class->cv_trans_ip_func = gst_cv_smooth_transform_ip;
166 g_object_class_install_property (gobject_class, PROP_SMOOTH_TYPE,
167 g_param_spec_enum ("type",
170 GST_TYPE_CV_SMOOTH_TYPE,
171 DEFAULT_CV_SMOOTH_TYPE,
172 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))
174 g_object_class_install_property (gobject_class, PROP_KERNELWIDTH,
175 g_param_spec_int ("kernel-width", "kernel width",
176 "The gaussian kernel width (must be positive and odd)."
177 "If type is median, this means the aperture linear size."
178 "Check OpenCV docs: http://docs.opencv.org"
179 "/2.4/modules/imgproc/doc/filtering.htm",
180 1, G_MAXINT, DEFAULT_KERNELWIDTH,
181 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
182 g_object_class_install_property (gobject_class, PROP_KERNELHEIGHT,
183 g_param_spec_int ("kernel-height", "kernel height",
184 "The gaussian kernel height (must be positive and odd).",
185 0, G_MAXINT, DEFAULT_KERNELHEIGHT,
186 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
187 g_object_class_install_property (gobject_class, PROP_COLORSIGMA,
188 g_param_spec_double ("color", "color (gaussian standard deviation or "
190 "If type is gaussian, this means the standard deviation."
191 "If type is bilateral, this means the color-sigma. If zero, "
192 "Default values are used.",
193 0, G_MAXDOUBLE, DEFAULT_COLORSIGMA,
194 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
195 g_object_class_install_property (gobject_class, PROP_SPATIALSIGMA,
196 g_param_spec_double ("spatial", "spatial (spatial sigma, bilateral only)",
197 "Only used in bilateral type, means the spatial-sigma.",
198 0, G_MAXDOUBLE, DEFAULT_SPATIALSIGMA,
199 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
200 g_object_class_install_property (gobject_class, PROP_POSITION_X,
201 g_param_spec_int ("position-x", "starting x position for blur",
202 "Starting x position for blur (in pixels).",
203 0, G_MAXINT, DEFAULT_POSITION_X,
204 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
205 g_object_class_install_property (gobject_class, PROP_POSITION_Y,
206 g_param_spec_int ("position-y", "starting y position for blur",
207 "Starting y position for blur (in pixels).",
208 0, G_MAXINT, DEFAULT_POSITION_Y,
209 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
210 g_object_class_install_property (gobject_class, PROP_WIDTH,
211 g_param_spec_int ("width", "width of area to blur",
212 "Width of the area to blur (in pixels).",
213 0, G_MAXINT, DEFAULT_WIDTH,
214 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
215 g_object_class_install_property (gobject_class, PROP_HEIGHT,
216 g_param_spec_int ("height", "height of area to blur",
217 "Height of the area to blur (in pixels).",
218 0, G_MAXINT, DEFAULT_HEIGHT,
219 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
221 gst_element_class_set_static_metadata (element_class,
223 "Transform/Effect/Video",
224 "Applies cvSmooth OpenCV function to the image",
225 "Thiago Santos<thiago.sousa.santos@collabora.co.uk>");
227 /* add sink and source pad templates */
228 caps = gst_opencv_caps_from_cv_image_type (CV_8UC3);
229 gst_caps_append (caps, gst_opencv_caps_from_cv_image_type (CV_8UC1));
230 templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
231 gst_caps_ref (caps));
232 gst_element_class_add_pad_template (element_class, templ);
233 templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps);
234 gst_element_class_add_pad_template (element_class, templ);
235 gst_caps_unref (caps);
238 /* initialize the new element
239 * instantiate pads and add them to element
240 * set pad callback functions
241 * initialize instance structure
244 gst_cv_smooth_init (GstCvSmooth * filter)
246 filter->type = DEFAULT_CV_SMOOTH_TYPE;
247 filter->kernelwidth = DEFAULT_KERNELWIDTH;
248 filter->kernelheight = DEFAULT_KERNELHEIGHT;
249 filter->colorsigma = DEFAULT_COLORSIGMA;
250 filter->spatialsigma = DEFAULT_SPATIALSIGMA;
251 filter->positionx = DEFAULT_POSITION_X;
252 filter->positiony = DEFAULT_POSITION_Y;
253 filter->width = DEFAULT_WIDTH;
254 filter->height = DEFAULT_HEIGHT;
256 gst_opencv_video_filter_set_in_place (GST_OPENCV_VIDEO_FILTER_CAST (filter),
261 gst_cv_smooth_change_type (GstCvSmooth * filter, gint value)
263 GST_DEBUG_OBJECT (filter, "Changing type from %d to %d", filter->type, value);
264 if (filter->type == value)
267 filter->type = value;
269 case GST_SMOOTH_GAUSSIAN:
270 case GST_SMOOTH_BLUR:
271 gst_opencv_video_filter_set_in_place (GST_OPENCV_VIDEO_FILTER_CAST
275 gst_opencv_video_filter_set_in_place (GST_OPENCV_VIDEO_FILTER_CAST
282 gst_cv_smooth_set_property (GObject * object, guint prop_id,
283 const GValue * value, GParamSpec * pspec)
285 GstCvSmooth *filter = GST_CV_SMOOTH (object);
288 case PROP_SMOOTH_TYPE:
289 gst_cv_smooth_change_type (filter, g_value_get_enum (value));
291 case PROP_KERNELWIDTH:{
292 gint prop = g_value_get_int (value);
295 filter->kernelwidth = prop;
297 GST_WARNING_OBJECT (filter, "Ignoring value for kernel-width, not odd"
302 case PROP_KERNELHEIGHT:{
303 gint prop = g_value_get_int (value);
306 filter->kernelheight = prop;
308 GST_WARNING_OBJECT (filter, "Ignoring value for kernel-height, not odd"
309 " nor zero (%d)", prop);
313 case PROP_COLORSIGMA:
314 filter->colorsigma = g_value_get_double (value);
316 case PROP_SPATIALSIGMA:
317 filter->spatialsigma = g_value_get_double (value);
319 case PROP_POSITION_X:
320 filter->positionx = g_value_get_int (value);
322 case PROP_POSITION_Y:
323 filter->positiony = g_value_get_int (value);
326 filter->width = g_value_get_int (value);
329 filter->height = g_value_get_int (value);
332 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
338 gst_cv_smooth_get_property (GObject * object, guint prop_id,
339 GValue * value, GParamSpec * pspec)
341 GstCvSmooth *filter = GST_CV_SMOOTH (object);
344 case PROP_SMOOTH_TYPE:
345 g_value_set_enum (value, filter->type);
347 case PROP_KERNELWIDTH:
348 g_value_set_int (value, filter->kernelwidth);
350 case PROP_KERNELHEIGHT:
351 g_value_set_int (value, filter->kernelheight);
353 case PROP_COLORSIGMA:
354 g_value_set_double (value, filter->colorsigma);
356 case PROP_SPATIALSIGMA:
357 g_value_set_double (value, filter->spatialsigma);
359 case PROP_POSITION_X:
360 g_value_set_int (value, filter->positionx);
362 case PROP_POSITION_Y:
363 g_value_set_int (value, filter->positiony);
366 g_value_set_int (value, filter->width);
369 g_value_set_int (value, filter->height);
372 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
378 gst_cv_smooth_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf,
381 GstCvSmooth *filter = GST_CV_SMOOTH (base);
383 if (filter->positionx != 0 || filter->positiony != 0 ||
384 filter->width != G_MAXINT || filter->height != G_MAXINT) {
385 Size mat_size = img.size ();
387 /* if the effect would start outside the image, just skip it */
388 if (filter->positionx >= mat_size.width
389 || filter->positiony >= mat_size.height)
391 /* explicitly account for empty area */
392 if (filter->width <= 0 || filter->height <= 0)
395 Rect mat_rect (filter->positionx,
397 MIN (filter->width, mat_size.width - filter->positionx),
398 MIN (filter->height, mat_size.height - filter->positiony));
400 img = img (mat_rect);
403 switch (filter->type) {
404 case GST_SMOOTH_BLUR:
405 blur (img, img, Size (filter->kernelwidth, filter->kernelheight),
408 case GST_SMOOTH_GAUSSIAN:
409 GaussianBlur (img, img, Size (filter->kernelwidth, filter->kernelheight),
410 filter->colorsigma, filter->colorsigma);
412 case GST_SMOOTH_MEDIAN:
413 medianBlur (img, img, filter->kernelwidth);
415 case GST_SMOOTH_BILATERAL:
416 bilateralFilter (img, img, -1, filter->colorsigma, 0.0);
426 gst_cv_smooth_plugin_init (GstPlugin * plugin)
428 GST_DEBUG_CATEGORY_INIT (gst_cv_smooth_debug, "cvsmooth", 0, "cvsmooth");
430 return gst_element_register (plugin, "cvsmooth", GST_RANK_NONE,