summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Casas-Sanchez <miguelecasassanchez@gmail.com>2013-05-23 11:04:57 +0200
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2013-05-23 11:05:28 +0200
commitac4efd2914df0b23144ffba5644f354a962e24ec (patch)
tree3bc165a8f9311d3386a6a6dcb62a0ef61e5befc0
parent5f4ac8c58f884f677b89eaf438dff89f2cff4957 (diff)
downloadgstreamer-plugins-bad-ac4efd2914df0b23144ffba5644f354a962e24ec.tar.gz
opencv: Add skin color detection element
https://bugzilla.gnome.org/show_bug.cgi?id=700654
-rw-r--r--ext/opencv/Makefile.am1
-rw-r--r--ext/opencv/gstopencv.c4
-rw-r--r--ext/opencv/gstskindetect.c413
-rw-r--r--ext/opencv/gstskindetect.h92
4 files changed, 510 insertions, 0 deletions
diff --git a/ext/opencv/Makefile.am b/ext/opencv/Makefile.am
index 1e277bff3..4bf32e721 100644
--- a/ext/opencv/Makefile.am
+++ b/ext/opencv/Makefile.am
@@ -19,6 +19,7 @@ libgstopencv_la_SOURCES = gstopencv.c \
gsttemplatematch.c \
gsttextoverlay.c \
gstmotioncells.c \
+ gstskindetect.c \
motioncells_wrapper.cpp \
MotionCells.cpp
diff --git a/ext/opencv/gstopencv.c b/ext/opencv/gstopencv.c
index 289192240..7518d5393 100644
--- a/ext/opencv/gstopencv.c
+++ b/ext/opencv/gstopencv.c
@@ -37,6 +37,7 @@
#include "gsttemplatematch.h"
#include "gsttextoverlay.h"
#include "gsthanddetect.h"
+#include "gstskindetect.h"
static gboolean
plugin_init (GstPlugin * plugin)
@@ -83,6 +84,9 @@ plugin_init (GstPlugin * plugin)
if (!gst_handdetect_plugin_init (plugin))
return FALSE;
+ if (!gst_skin_detect_plugin_init (plugin))
+ return FALSE;
+
return TRUE;
}
diff --git a/ext/opencv/gstskindetect.c b/ext/opencv/gstskindetect.c
new file mode 100644
index 000000000..9cd5633e9
--- /dev/null
+++ b/ext/opencv/gstskindetect.c
@@ -0,0 +1,413 @@
+/*
+ * GStreamer
+ * Copyright (C) 2013 Miguel Casas-Sanchez <miguelecasassanchez@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:element-skindetect
+ *
+ * Human skin detection on videos and images
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch-1.0 videotestsrc ! decodebin ! videoconvert ! skindetect ! videoconvert ! xvimagesink
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gst/gst.h>
+
+#include "gstopencvutils.h"
+#include "gstskindetect.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_skin_detect_debug);
+#define GST_CAT_DEFAULT gst_skin_detect_debug
+
+/* Filter signals and args */
+enum
+{
+ /* FILL ME */
+ LAST_SIGNAL
+};
+
+enum
+{
+ PROP_0,
+ PROP_POSTPROCESS,
+ PROP_METHOD,
+ PROP_MASK
+};
+typedef enum
+{
+ HSV,
+ RGB
+} GstSkindetectMethod;
+
+#define GST_TYPE_SKIN_DETECT_METHOD (gst_skin_detect_method_get_type ())
+static GType
+gst_skin_detect_method_get_type (void)
+{
+ static GType etype = 0;
+ if (etype == 0) {
+ static const GEnumValue values[] = {
+ {HSV, "Classic HSV thresholding", "hsv"},
+ {RGB, "Normalised-RGB colorspace thresholding", "rgb"},
+ {0, NULL, NULL},
+ };
+ etype = g_enum_register_static ("GstSkindetectMethod", values);
+ }
+ return etype;
+}
+
+G_DEFINE_TYPE (GstSkinDetect, gst_skin_detect, GST_TYPE_OPENCV_VIDEO_FILTER);
+static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB")));
+
+static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB")));
+
+
+static void gst_skin_detect_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_skin_detect_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static GstFlowReturn gst_skin_detect_transform (GstOpencvVideoFilter * filter,
+ GstBuffer * buf, IplImage * img, GstBuffer * outbuf, IplImage * outimg);
+
+static gboolean gst_skin_detect_stop (GstBaseTransform * basesrc);
+static gboolean
+gst_skin_detect_set_caps (GstOpencvVideoFilter * transform,
+ gint in_width, gint in_height, gint in_depth, gint in_channels,
+ gint out_width, gint out_height, gint out_depth, gint out_channels);
+static void gst_skin_detect_release_all_images (GstSkinDetect * filter);
+
+/* initialize the skindetect's class */
+static void
+gst_skin_detect_class_init (GstSkinDetectClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstBaseTransformClass *basesrc_class = GST_BASE_TRANSFORM_CLASS (klass);
+ GstOpencvVideoFilterClass *gstopencvbasefilter_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstopencvbasefilter_class = (GstOpencvVideoFilterClass *) klass;
+
+ gobject_class->set_property = gst_skin_detect_set_property;
+ gobject_class->get_property = gst_skin_detect_get_property;
+
+ gstopencvbasefilter_class->cv_trans_func = gst_skin_detect_transform;
+
+ g_object_class_install_property (gobject_class, PROP_POSTPROCESS,
+ g_param_spec_boolean ("postprocess", "Postprocess",
+ "Apply opening-closing to skin detection to extract large, significant blobs ",
+ TRUE, (GParamFlags)
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+ g_object_class_install_property (gobject_class, PROP_METHOD,
+ g_param_spec_enum ("method",
+ "Method to use",
+ "Method to use",
+ GST_TYPE_SKIN_DETECT_METHOD, HSV,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ gst_element_class_set_static_metadata (element_class,
+ "skindetect",
+ "Filter/Effect/Video",
+ "Performs non-parametric skin detection on input",
+ "Miguel Casas-Sanchez <miguelecasassanchez@gmail.com>");
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&src_factory));
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&sink_factory));
+
+ basesrc_class->stop = gst_skin_detect_stop;
+ gstopencvbasefilter_class->cv_set_caps = gst_skin_detect_set_caps;
+}
+
+/* initialize the new element
+ * instantiate pads and add them to element
+ * set pad calback functions
+ * initialize instance structure
+ */
+static void
+gst_skin_detect_init (GstSkinDetect * filter)
+{
+ filter->postprocess = TRUE;
+ filter->method = HSV;
+
+ gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), FALSE);
+}
+
+
+static void
+gst_skin_detect_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstSkinDetect *filter = GST_SKIN_DETECT (object);
+
+ switch (prop_id) {
+ case PROP_POSTPROCESS:
+ filter->postprocess = g_value_get_boolean (value);
+ break;
+ case PROP_METHOD:
+ filter->method = g_value_get_enum (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_skin_detect_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstSkinDetect *filter = GST_SKIN_DETECT (object);
+
+ switch (prop_id) {
+ case PROP_POSTPROCESS:
+ g_value_set_boolean (value, filter->postprocess);
+ break;
+ case PROP_METHOD:
+ g_value_set_enum (value, filter->method);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/* GstElement vmethod implementations */
+/* this function handles the link with other elements */
+static gboolean
+gst_skin_detect_set_caps (GstOpencvVideoFilter * transform,
+ gint in_width, gint in_height, gint in_depth, gint in_channels,
+ gint out_width, gint out_height, gint out_depth, gint out_channels)
+{
+ GstSkinDetect *filter = GST_SKIN_DETECT (transform);
+ CvSize size = cvSize (in_width, in_height);
+
+ // If cvRGB is already allocated, it means there's a cap modification,
+ // so release first all the images.
+ if (NULL != filter->cvRGB)
+ gst_skin_detect_release_all_images (filter);
+
+
+ filter->cvRGB = cvCreateImageHeader (size, IPL_DEPTH_8U, 3);
+ filter->cvSkin = cvCreateImageHeader (size, IPL_DEPTH_8U, 3);
+ filter->cvChA = cvCreateImage (size, IPL_DEPTH_8U, 1);
+ filter->width = in_width;
+ filter->height = in_height;
+
+ filter->cvHSV = cvCreateImage (size, IPL_DEPTH_8U, 3);
+ filter->cvH = cvCreateImage (size, 8, 1); /* Hue component. */
+ filter->cvH2 = cvCreateImage (size, 8, 1); /* Hue component, 2nd threshold */
+ filter->cvS = cvCreateImage (size, 8, 1); /* Saturation component. */
+ filter->cvV = cvCreateImage (size, 8, 1); /* Brightness component. */
+ filter->cvSkinPixels1 = cvCreateImage (size, 8, 1); /* Greyscale output image */
+
+ filter->cvR = cvCreateImage (size, 8, 1); /* R component. */
+ filter->cvG = cvCreateImage (size, 8, 1); /* G component. */
+ filter->cvB = cvCreateImage (size, 8, 1); /* B component. */
+ filter->cvAll = cvCreateImage (size, IPL_DEPTH_32F, 1); /* (R+G+B) component. */
+ filter->cvR2 = cvCreateImage (size, IPL_DEPTH_32F, 1); /* R component, 32bits */
+ filter->cvRp = cvCreateImage (size, IPL_DEPTH_32F, 1); /* R' and >0.4 */
+ filter->cvGp = cvCreateImage (size, IPL_DEPTH_32F, 1); /* G' and > 0.28 */
+ filter->cvRp2 = cvCreateImage (size, IPL_DEPTH_32F, 1); /* R' <0.6 */
+ filter->cvGp2 = cvCreateImage (size, IPL_DEPTH_32F, 1); /* G' <0.4 */
+ filter->cvSkinPixels2 = cvCreateImage (size, IPL_DEPTH_32F, 1); /* Greyscale output image. */
+ filter->cvdraft = cvCreateImage (size, IPL_DEPTH_8U, 1); /* Greyscale output image. */
+
+ return TRUE;
+}
+
+/* Clean up */
+static gboolean
+gst_skin_detect_stop (GstBaseTransform * basesrc)
+{
+ GstSkinDetect *filter = GST_SKIN_DETECT (basesrc);
+
+ if (filter->cvRGB != NULL)
+ gst_skin_detect_release_all_images (filter);
+ return TRUE;
+}
+
+static void
+gst_skin_detect_release_all_images (GstSkinDetect * filter)
+{
+ cvReleaseImage (&filter->cvRGB);
+ cvReleaseImage (&filter->cvSkin);
+ cvReleaseImage (&filter->cvChA);
+
+ cvReleaseImage (&filter->cvHSV);
+ cvReleaseImage (&filter->cvH);
+ cvReleaseImage (&filter->cvH2);
+ cvReleaseImage (&filter->cvS);
+ cvReleaseImage (&filter->cvV);
+ cvReleaseImage (&filter->cvSkinPixels1);
+
+ cvReleaseImage (&filter->cvR);
+ cvReleaseImage (&filter->cvG);
+ cvReleaseImage (&filter->cvB);
+ cvReleaseImage (&filter->cvAll);
+ cvReleaseImage (&filter->cvR2);
+ cvReleaseImage (&filter->cvRp);
+ cvReleaseImage (&filter->cvGp);
+ cvReleaseImage (&filter->cvRp2);
+ cvReleaseImage (&filter->cvGp2);
+ cvReleaseImage (&filter->cvSkinPixels2);
+ cvReleaseImage (&filter->cvdraft);
+}
+
+static GstFlowReturn
+gst_skin_detect_transform (GstOpencvVideoFilter * base, GstBuffer * buf,
+ IplImage * img, GstBuffer * outbuf, IplImage * outimg)
+{
+ GstSkinDetect *filter = GST_SKIN_DETECT (base);
+
+
+
+ filter->cvRGB->imageData = (char *) img->imageData;
+ filter->cvSkin->imageData = (char *) outimg->imageData;
+
+ /* SKIN COLOUR BLOB DETECTION */
+ if (HSV == filter->method) {
+ cvCvtColor (filter->cvRGB, filter->cvHSV, CV_RGB2HSV);
+ cvCvtPixToPlane (filter->cvHSV, filter->cvH, filter->cvS, filter->cvV, 0); /* Extract the 3 color components. */
+
+ /* Detect which pixels in each of the H, S and V channels are probably skin pixels.
+ Assume that skin has a Hue between 0 to 18 (out of 180), and Saturation above 50, and Brightness above 80. */
+ cvThreshold (filter->cvH, filter->cvH2, 10, UCHAR_MAX, CV_THRESH_BINARY); /* (hue > 10) */
+ cvThreshold (filter->cvH, filter->cvH, 20, UCHAR_MAX, CV_THRESH_BINARY_INV); /* (hue < 20) */
+ cvThreshold (filter->cvS, filter->cvS, 48, UCHAR_MAX, CV_THRESH_BINARY); /* (sat > 48) */
+ cvThreshold (filter->cvV, filter->cvV, 80, UCHAR_MAX, CV_THRESH_BINARY); /* (val > 80) */
+
+ /* erode the HUE to get rid of noise. */
+ cvErode (filter->cvH, filter->cvH, NULL, 1);
+
+ /* Combine all 3 thresholded color components, so that an output pixel will only
+ be white (255) if the H, S and V pixels were also white.
+ imageSkin = (hue > 10) ^ (hue < 20) ^ (sat > 48) ^ (val > 80), where ^ mean pixels-wise AND */
+ cvAnd (filter->cvH, filter->cvS, filter->cvSkinPixels1, NULL);
+ cvAnd (filter->cvSkinPixels1, filter->cvH2, filter->cvSkinPixels1, NULL);
+ cvAnd (filter->cvSkinPixels1, filter->cvV, filter->cvSkinPixels1, NULL);
+
+ cvCvtColor (filter->cvSkinPixels1, filter->cvRGB, CV_GRAY2RGB);
+ } else if (RGB == filter->method) {
+ cvCvtPixToPlane (filter->cvRGB, filter->cvR, filter->cvG, filter->cvB, 0); /* Extract the 3 color components. */
+ cvAdd (filter->cvR, filter->cvG, filter->cvAll, NULL);
+ cvAdd (filter->cvB, filter->cvAll, filter->cvAll, NULL); /* All = R + G + B */
+ cvDiv (filter->cvR, filter->cvAll, filter->cvRp, 1.0); /* R' = R / ( R + G + B) */
+ cvDiv (filter->cvG, filter->cvAll, filter->cvGp, 1.0); /* G' = G / ( R + G + B) */
+
+ cvConvertScale (filter->cvR, filter->cvR2, 1.0, 0.0);
+ cvCopy (filter->cvGp, filter->cvGp2, NULL);
+ cvCopy (filter->cvRp, filter->cvRp2, NULL);
+
+ cvThreshold (filter->cvR2, filter->cvR2, 60, UCHAR_MAX, CV_THRESH_BINARY); /* (R > 60) */
+ cvThreshold (filter->cvRp, filter->cvRp, 0.42, UCHAR_MAX, CV_THRESH_BINARY); /* (R'> 0.4) */
+ cvThreshold (filter->cvRp2, filter->cvRp2, 0.6, UCHAR_MAX, CV_THRESH_BINARY_INV); /* (R'< 0.6) */
+ cvThreshold (filter->cvGp, filter->cvGp, 0.28, UCHAR_MAX, CV_THRESH_BINARY); /* (G'> 0.28) */
+ cvThreshold (filter->cvGp2, filter->cvGp2, 0.4, UCHAR_MAX, CV_THRESH_BINARY_INV); /* (G'< 0.4) */
+
+ /* Combine all 3 thresholded color components, so that an output pixel will only
+ be white (255) if the H, S and V pixels were also white. */
+
+ cvAnd (filter->cvR2, filter->cvRp, filter->cvSkinPixels2, NULL);
+ cvAnd (filter->cvRp, filter->cvSkinPixels2, filter->cvSkinPixels2, NULL);
+ cvAnd (filter->cvRp2, filter->cvSkinPixels2, filter->cvSkinPixels2, NULL);
+ cvAnd (filter->cvGp, filter->cvSkinPixels2, filter->cvSkinPixels2, NULL);
+ cvAnd (filter->cvGp2, filter->cvSkinPixels2, filter->cvSkinPixels2, NULL);
+
+ cvConvertScale (filter->cvSkinPixels2, filter->cvdraft, 1.0, 0.0);
+ cvCvtColor (filter->cvdraft, filter->cvRGB, CV_GRAY2RGB);
+ }
+
+ /* After this we have a RGB Black and white image with the skin, in
+ filter->cvRGB. We can postprocess by applying 1 erode-dilate and 1
+ dilate-erode, or alternatively 1 opening-closing all together, with
+ the goal of removing small (spurious) skin spots and creating large
+ connected areas */
+ if (filter->postprocess) {
+ cvSplit (filter->cvRGB, filter->cvChA, NULL, NULL, NULL);
+
+ cvErode (filter->cvChA, filter->cvChA,
+ cvCreateStructuringElementEx (3, 3, 1, 1, CV_SHAPE_RECT, NULL), 1);
+ cvDilate (filter->cvChA, filter->cvChA,
+ cvCreateStructuringElementEx (3, 3, 1, 1, CV_SHAPE_RECT, NULL), 2);
+ cvErode (filter->cvChA, filter->cvChA,
+ cvCreateStructuringElementEx (3, 3, 1, 1, CV_SHAPE_RECT, NULL), 1);
+
+ cvCvtColor (filter->cvChA, filter->cvRGB, CV_GRAY2RGB);
+ }
+
+ cvCopy (filter->cvRGB, filter->cvSkin, NULL);
+
+ return GST_FLOW_OK;
+}
+
+/* entry point to initialize the plug-in
+ * initialize the plug-in itself
+ * register the element factories and other features
+ */
+gboolean
+gst_skin_detect_plugin_init (GstPlugin * plugin)
+{
+ /* debug category for fltering log messages
+ *
+ */
+ GST_DEBUG_CATEGORY_INIT (gst_skin_detect_debug, "skindetect",
+ 0, "Performs skin detection on videos and images");
+
+ return gst_element_register (plugin, "skindetect", GST_RANK_NONE,
+ GST_TYPE_SKIN_DETECT);
+}
diff --git a/ext/opencv/gstskindetect.h b/ext/opencv/gstskindetect.h
new file mode 100644
index 000000000..978983426
--- /dev/null
+++ b/ext/opencv/gstskindetect.h
@@ -0,0 +1,92 @@
+/*
+ * GStreamer
+ * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
+ * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2008 Michael Sheldon <mike@mikeasoft.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_SKIN_DETECT_H__
+#define __GST_SKIN_DETECT_H__
+
+#include <gst/gst.h>
+#include <cv.h>
+#include <gstopencvvideofilter.h>
+
+G_BEGIN_DECLS
+/* #defines don't like whitespacey bits */
+#define GST_TYPE_SKIN_DETECT \
+ (gst_skin_detect_get_type())
+#define GST_SKIN_DETECT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SKIN_DETECT,GstSkinDetect))
+#define GST_SKIN_DETECT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SKIN_DETECT,GstSkinDetectClass))
+#define GST_IS_SKIN_DETECT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SKIN_DETECT))
+#define GST_IS_SKIN_DETECT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SKIN_DETECT))
+typedef struct _GstSkinDetect GstSkinDetect;
+typedef struct _GstSkinDetectClass GstSkinDetectClass;
+
+struct _GstSkinDetect
+{
+ GstOpencvVideoFilter element;
+
+ gboolean postprocess;
+ gint method;
+ gint width, height;
+
+ IplImage *cvChA, *cvRGB, *cvSkin;
+ IplImage *cvHSV, *cvH, *cvH2, *cvS, *cvV, *cvSkinPixels1;
+ IplImage *cvR, *cvG, *cvB, *cvAll, *cvR2, *cvRp, *cvGp, *cvRp2, *cvGp2,
+ *cvdraft, *cvSkinPixels2;
+};
+
+struct _GstSkinDetectClass
+{
+ GstOpencvVideoFilterClass parent_class;
+};
+
+GType gst_skin_detect_get_type (void);
+
+gboolean gst_skin_detect_plugin_init (GstPlugin * plugin);
+
+G_END_DECLS
+#endif /* __GST_SKIN_DETECT_H__ */