Imported Upstream version 0.10.23
[profile/ivi/gst-plugins-bad.git] / ext / opencv / gstfaceblur.c
1 /*
2  * GStreamer
3  * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
4  * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
5  * Copyright (C) 2008 Michael Sheldon <mike@mikeasoft.com>
6  * 
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  *
25  * Alternatively, the contents of this file may be used under the
26  * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
27  * which case the following provisions apply instead of the ones
28  * mentioned above:
29  *
30  * This library is free software; you can redistribute it and/or
31  * modify it under the terms of the GNU Library General Public
32  * License as published by the Free Software Foundation; either
33  * version 2 of the License, or (at your option) any later version.
34  *
35  * This library is distributed in the hope that it will be useful,
36  * but WITHOUT ANY WARRANTY; without even the implied warranty of
37  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
38  * Library General Public License for more details.
39  *
40  * You should have received a copy of the GNU Library General Public
41  * License along with this library; if not, write to the
42  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
43  * Boston, MA 02111-1307, USA.
44  */
45
46 /**
47  * SECTION:element-faceblur
48  *
49  * Blurs faces in images and videos.
50  *
51  * <refsect2>
52  * <title>Example launch line</title>
53  * |[
54  * gst-launch-0.10 videotestsrc ! decodebin ! ffmpegcolorspace ! faceblur ! ffmpegcolorspace ! xvimagesink
55  * ]|
56  * </refsect2>
57  */
58
59 #ifdef HAVE_CONFIG_H
60 #  include <config.h>
61 #endif
62
63 #include <gst/gst.h>
64
65 #include "gstopencvutils.h"
66 #include "gstfaceblur.h"
67
68 GST_DEBUG_CATEGORY_STATIC (gst_face_blur_debug);
69 #define GST_CAT_DEFAULT gst_face_blur_debug
70
71 #define DEFAULT_PROFILE "/usr/share/opencv/haarcascades/haarcascade_frontalface_default.xml"
72
73 /* Filter signals and args */
74 enum
75 {
76   /* FILL ME */
77   LAST_SIGNAL
78 };
79
80 enum
81 {
82   PROP_0,
83   PROP_PROFILE
84 };
85
86 /* the capabilities of the inputs and outputs.
87  */
88 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
89     GST_PAD_SINK,
90     GST_PAD_ALWAYS,
91     GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB)
92     );
93
94 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
95     GST_PAD_SRC,
96     GST_PAD_ALWAYS,
97     GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB)
98     );
99
100 GST_BOILERPLATE (GstFaceBlur, gst_face_blur, GstElement, GST_TYPE_ELEMENT);
101
102 static void gst_face_blur_set_property (GObject * object, guint prop_id,
103     const GValue * value, GParamSpec * pspec);
104 static void gst_face_blur_get_property (GObject * object, guint prop_id,
105     GValue * value, GParamSpec * pspec);
106
107 static gboolean gst_face_blur_set_caps (GstPad * pad, GstCaps * caps);
108 static GstFlowReturn gst_face_blur_chain (GstPad * pad, GstBuffer * buf);
109
110 static void gst_face_blur_load_profile (GstFaceBlur * filter);
111
112 /* Clean up */
113 static void
114 gst_face_blur_finalize (GObject * obj)
115 {
116   GstFaceBlur *filter = GST_FACE_BLUR (obj);
117
118   if (filter->cvImage) {
119     cvReleaseImage (&filter->cvImage);
120     cvReleaseImage (&filter->cvGray);
121   }
122
123   g_free (filter->profile);
124
125   G_OBJECT_CLASS (parent_class)->finalize (obj);
126 }
127
128
129 /* GObject vmethod implementations */
130 static void
131 gst_face_blur_base_init (gpointer gclass)
132 {
133   GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
134
135   gst_element_class_set_details_simple (element_class,
136       "faceblur",
137       "Filter/Effect/Video",
138       "Blurs faces in images and videos",
139       "Michael Sheldon <mike@mikeasoft.com>");
140
141   gst_element_class_add_static_pad_template (element_class, &src_factory);
142   gst_element_class_add_static_pad_template (element_class, &sink_factory);
143 }
144
145 /* initialize the faceblur's class */
146 static void
147 gst_face_blur_class_init (GstFaceBlurClass * klass)
148 {
149   GObjectClass *gobject_class;
150
151   gobject_class = (GObjectClass *) klass;
152   parent_class = g_type_class_peek_parent (klass);
153
154   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_face_blur_finalize);
155   gobject_class->set_property = gst_face_blur_set_property;
156   gobject_class->get_property = gst_face_blur_get_property;
157
158   g_object_class_install_property (gobject_class, PROP_PROFILE,
159       g_param_spec_string ("profile", "Profile",
160           "Location of Haar cascade file to use for face blurion",
161           DEFAULT_PROFILE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
162 }
163
164 /* initialize the new element
165  * instantiate pads and add them to element
166  * set pad calback functions
167  * initialize instance structure
168  */
169 static void
170 gst_face_blur_init (GstFaceBlur * filter, GstFaceBlurClass * gclass)
171 {
172   filter->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
173   gst_pad_set_setcaps_function (filter->sinkpad,
174       GST_DEBUG_FUNCPTR (gst_face_blur_set_caps));
175   gst_pad_set_getcaps_function (filter->sinkpad,
176       GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
177   gst_pad_set_chain_function (filter->sinkpad,
178       GST_DEBUG_FUNCPTR (gst_face_blur_chain));
179
180   filter->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
181   gst_pad_set_getcaps_function (filter->srcpad,
182       GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
183
184   gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
185   gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
186   filter->profile = g_strdup (DEFAULT_PROFILE);
187   gst_face_blur_load_profile (filter);
188 }
189
190 static void
191 gst_face_blur_set_property (GObject * object, guint prop_id,
192     const GValue * value, GParamSpec * pspec)
193 {
194   GstFaceBlur *filter = GST_FACE_BLUR (object);
195
196   switch (prop_id) {
197     case PROP_PROFILE:
198       g_free (filter->profile);
199       filter->profile = g_value_dup_string (value);
200       gst_face_blur_load_profile (filter);
201       break;
202     default:
203       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
204       break;
205   }
206 }
207
208 static void
209 gst_face_blur_get_property (GObject * object, guint prop_id,
210     GValue * value, GParamSpec * pspec)
211 {
212   GstFaceBlur *filter = GST_FACE_BLUR (object);
213
214   switch (prop_id) {
215     case PROP_PROFILE:
216       g_value_set_string (value, filter->profile);
217       break;
218     default:
219       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
220       break;
221   }
222 }
223
224 /* GstElement vmethod implementations */
225
226 /* this function handles the link with other elements */
227 static gboolean
228 gst_face_blur_set_caps (GstPad * pad, GstCaps * caps)
229 {
230   GstFaceBlur *filter;
231   GstPad *otherpad;
232   gint width, height;
233   GstStructure *structure;
234
235   filter = GST_FACE_BLUR (gst_pad_get_parent (pad));
236   structure = gst_caps_get_structure (caps, 0);
237   gst_structure_get_int (structure, "width", &width);
238   gst_structure_get_int (structure, "height", &height);
239
240   filter->cvImage = cvCreateImage (cvSize (width, height), IPL_DEPTH_8U, 3);
241   filter->cvGray = cvCreateImage (cvSize (width, height), IPL_DEPTH_8U, 1);
242   filter->cvStorage = cvCreateMemStorage (0);
243
244   otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad;
245   gst_object_unref (filter);
246
247   return gst_pad_set_caps (otherpad, caps);
248 }
249
250 /* chain function
251  * this function does the actual processing
252  */
253 static GstFlowReturn
254 gst_face_blur_chain (GstPad * pad, GstBuffer * buf)
255 {
256   GstFaceBlur *filter;
257   CvSeq *faces;
258   int i;
259
260   filter = GST_FACE_BLUR (GST_OBJECT_PARENT (pad));
261
262   filter->cvImage->imageData = (char *) GST_BUFFER_DATA (buf);
263
264   cvCvtColor (filter->cvImage, filter->cvGray, CV_RGB2GRAY);
265   cvClearMemStorage (filter->cvStorage);
266
267   if (filter->cvCascade) {
268     faces =
269         cvHaarDetectObjects (filter->cvGray, filter->cvCascade,
270         filter->cvStorage, 1.1, 2, 0, cvSize (30, 30)
271 #if (CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >= 2)
272         , cvSize (32, 32)
273 #endif
274         );
275
276     if (faces && faces->total > 0) {
277       buf = gst_buffer_make_writable (buf);
278     }
279     for (i = 0; i < (faces ? faces->total : 0); i++) {
280       CvRect *r = (CvRect *) cvGetSeqElem (faces, i);
281       cvSetImageROI (filter->cvImage, *r);
282       cvSmooth (filter->cvImage, filter->cvImage, CV_BLUR, 11, 11, 0, 0);
283       cvSmooth (filter->cvImage, filter->cvImage, CV_GAUSSIAN, 11, 11, 0, 0);
284       cvResetImageROI (filter->cvImage);
285     }
286   }
287
288   /* these filters operate in place, so we push the same buffer */
289
290   return gst_pad_push (filter->srcpad, buf);
291 }
292
293
294 static void
295 gst_face_blur_load_profile (GstFaceBlur * filter)
296 {
297   filter->cvCascade =
298       (CvHaarClassifierCascade *) cvLoad (filter->profile, 0, 0, 0);
299   if (!filter->cvCascade) {
300     GST_WARNING ("Couldn't load Haar classifier cascade: %s.", filter->profile);
301   }
302 }
303
304
305 /* entry point to initialize the plug-in
306  * initialize the plug-in itself
307  * register the element factories and other features
308  */
309 gboolean
310 gst_face_blur_plugin_init (GstPlugin * plugin)
311 {
312   /* debug category for filtering log messages */
313   GST_DEBUG_CATEGORY_INIT (gst_face_blur_debug, "faceblur",
314       0, "Blurs faces in images and videos");
315
316   return gst_element_register (plugin, "faceblur", GST_RANK_NONE,
317       GST_TYPE_FACE_BLUR);
318 }