faceblur: Port to OpencvVideoFilter base class
This fixes issue whit black frames when special memory, like GlMemory is in used. https://bugzilla.gnome.org/show_bug.cgi?id=732756
This commit is contained in:
parent
42a83d2c64
commit
34e23c2e21
@ -68,15 +68,9 @@
|
|||||||
GST_DEBUG_CATEGORY_STATIC (gst_face_blur_debug);
|
GST_DEBUG_CATEGORY_STATIC (gst_face_blur_debug);
|
||||||
#define GST_CAT_DEFAULT gst_face_blur_debug
|
#define GST_CAT_DEFAULT gst_face_blur_debug
|
||||||
|
|
||||||
#define HAAR_CASCADES_DIR OPENCV_PREFIX "/share/opencv/haarcascades/"
|
#define DEFAULT_PROFILE OPENCV_PREFIX G_DIR_SEPARATOR_S "share" \
|
||||||
#define DEFAULT_PROFILE HAAR_CASCADES_DIR "haarcascade_frontalface_default.xml"
|
G_DIR_SEPARATOR_S "opencv" G_DIR_SEPARATOR_S "haarcascades" \
|
||||||
|
G_DIR_SEPARATOR_S "haarcascade_frontalface_default.xml"
|
||||||
/* Filter signals and args */
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
/* FILL ME */
|
|
||||||
LAST_SIGNAL
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -98,17 +92,19 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
|
|||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB"))
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB"))
|
||||||
);
|
);
|
||||||
|
|
||||||
G_DEFINE_TYPE (GstFaceBlur, gst_face_blur, GST_TYPE_ELEMENT);
|
G_DEFINE_TYPE (GstFaceBlur, gst_face_blur, GST_TYPE_OPENCV_VIDEO_FILTER);
|
||||||
|
|
||||||
static void gst_face_blur_set_property (GObject * object, guint prop_id,
|
static void gst_face_blur_set_property (GObject * object, guint prop_id,
|
||||||
const GValue * value, GParamSpec * pspec);
|
const GValue * value, GParamSpec * pspec);
|
||||||
static void gst_face_blur_get_property (GObject * object, guint prop_id,
|
static void gst_face_blur_get_property (GObject * object, guint prop_id,
|
||||||
GValue * value, GParamSpec * pspec);
|
GValue * value, GParamSpec * pspec);
|
||||||
|
|
||||||
static gboolean gst_face_blur_handle_sink_event (GstPad * pad,
|
|
||||||
GstObject * parent, GstEvent * event);
|
static gboolean gst_face_blur_set_caps (GstOpencvVideoFilter * transform,
|
||||||
static GstFlowReturn gst_face_blur_chain (GstPad * pad, GstObject * parent,
|
gint in_width, gint in_height, gint in_depth, gint in_channels,
|
||||||
GstBuffer * buf);
|
gint out_width, gint out_height, gint out_depth, gint out_channels);
|
||||||
|
static GstFlowReturn gst_face_blur_transform_ip (GstOpencvVideoFilter *
|
||||||
|
transform, GstBuffer * buffer, IplImage * img);
|
||||||
|
|
||||||
static void gst_face_blur_load_profile (GstFaceBlur * filter);
|
static void gst_face_blur_load_profile (GstFaceBlur * filter);
|
||||||
|
|
||||||
@ -118,11 +114,12 @@ gst_face_blur_finalize (GObject * obj)
|
|||||||
{
|
{
|
||||||
GstFaceBlur *filter = GST_FACE_BLUR (obj);
|
GstFaceBlur *filter = GST_FACE_BLUR (obj);
|
||||||
|
|
||||||
if (filter->cvImage) {
|
if (filter->cvGray)
|
||||||
cvReleaseImage (&filter->cvImage);
|
|
||||||
cvReleaseImage (&filter->cvGray);
|
cvReleaseImage (&filter->cvGray);
|
||||||
|
|
||||||
|
if (filter->cvStorage)
|
||||||
cvReleaseMemStorage (&filter->cvStorage);
|
cvReleaseMemStorage (&filter->cvStorage);
|
||||||
}
|
|
||||||
if (filter->cvCascade)
|
if (filter->cvCascade)
|
||||||
cvReleaseHaarClassifierCascade (&filter->cvCascade);
|
cvReleaseHaarClassifierCascade (&filter->cvCascade);
|
||||||
|
|
||||||
@ -137,9 +134,14 @@ static void
|
|||||||
gst_face_blur_class_init (GstFaceBlurClass * klass)
|
gst_face_blur_class_init (GstFaceBlurClass * klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class;
|
GObjectClass *gobject_class;
|
||||||
|
GstOpencvVideoFilterClass *gstopencvbasefilter_class;
|
||||||
|
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
gobject_class = (GObjectClass *) klass;
|
gobject_class = (GObjectClass *) klass;
|
||||||
|
gstopencvbasefilter_class = (GstOpencvVideoFilterClass *) klass;
|
||||||
|
|
||||||
|
gstopencvbasefilter_class->cv_trans_ip_func = gst_face_blur_transform_ip;
|
||||||
|
gstopencvbasefilter_class->cv_set_caps = gst_face_blur_set_caps;
|
||||||
|
|
||||||
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_face_blur_finalize);
|
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_face_blur_finalize);
|
||||||
gobject_class->set_property = gst_face_blur_set_property;
|
gobject_class->set_property = gst_face_blur_set_property;
|
||||||
@ -170,20 +172,11 @@ gst_face_blur_class_init (GstFaceBlurClass * klass)
|
|||||||
static void
|
static void
|
||||||
gst_face_blur_init (GstFaceBlur * filter)
|
gst_face_blur_init (GstFaceBlur * filter)
|
||||||
{
|
{
|
||||||
filter->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
|
|
||||||
GST_PAD_SET_PROXY_CAPS (filter->sinkpad);
|
|
||||||
gst_pad_set_event_function (filter->sinkpad,
|
|
||||||
GST_DEBUG_FUNCPTR (gst_face_blur_handle_sink_event));
|
|
||||||
gst_pad_set_chain_function (filter->sinkpad,
|
|
||||||
GST_DEBUG_FUNCPTR (gst_face_blur_chain));
|
|
||||||
|
|
||||||
filter->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
|
|
||||||
GST_PAD_SET_PROXY_CAPS (filter->srcpad);
|
|
||||||
|
|
||||||
gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
|
|
||||||
gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
|
|
||||||
filter->profile = g_strdup (DEFAULT_PROFILE);
|
filter->profile = g_strdup (DEFAULT_PROFILE);
|
||||||
gst_face_blur_load_profile (filter);
|
gst_face_blur_load_profile (filter);
|
||||||
|
|
||||||
|
gst_opencv_video_filter_set_in_place (GST_OPENCV_VIDEO_FILTER_CAST (filter),
|
||||||
|
TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -220,94 +213,57 @@ gst_face_blur_get_property (GObject * object, guint prop_id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GstElement vmethod implementations */
|
|
||||||
|
|
||||||
/* this function handles the link with other elements */
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_face_blur_handle_sink_event (GstPad * pad, GstObject * parent,
|
gst_face_blur_set_caps (GstOpencvVideoFilter * transform,
|
||||||
GstEvent * event)
|
gint in_width, gint in_height, gint in_depth, gint in_channels,
|
||||||
|
gint out_width, gint out_height, gint out_depth, gint out_channels)
|
||||||
{
|
{
|
||||||
GstFaceBlur *filter;
|
GstFaceBlur *filter = GST_FACE_BLUR (transform);
|
||||||
gint width, height;
|
|
||||||
GstStructure *structure;
|
|
||||||
gboolean res = TRUE;
|
|
||||||
|
|
||||||
filter = GST_FACE_BLUR (parent);
|
if (filter->cvGray)
|
||||||
|
cvReleaseImage (&filter->cvGray);
|
||||||
|
filter->cvGray =
|
||||||
|
cvCreateImage (cvSize (in_width, in_height), IPL_DEPTH_8U, 1);
|
||||||
|
|
||||||
switch (GST_EVENT_TYPE (event)) {
|
if (filter->cvStorage)
|
||||||
case GST_EVENT_CAPS:
|
cvClearMemStorage (filter->cvStorage);
|
||||||
{
|
else
|
||||||
GstCaps *caps;
|
filter->cvStorage = cvCreateMemStorage (0);
|
||||||
gst_event_parse_caps (event, &caps);
|
|
||||||
|
|
||||||
structure = gst_caps_get_structure (caps, 0);
|
return TRUE;
|
||||||
gst_structure_get_int (structure, "width", &width);
|
|
||||||
gst_structure_get_int (structure, "height", &height);
|
|
||||||
|
|
||||||
if (filter->cvImage) {
|
|
||||||
cvReleaseImage (&filter->cvImage);
|
|
||||||
cvReleaseImage (&filter->cvGray);
|
|
||||||
cvReleaseMemStorage (&filter->cvStorage);
|
|
||||||
}
|
|
||||||
|
|
||||||
filter->cvImage = cvCreateImage (cvSize (width, height), IPL_DEPTH_8U, 3);
|
|
||||||
filter->cvGray = cvCreateImage (cvSize (width, height), IPL_DEPTH_8U, 1);
|
|
||||||
filter->cvStorage = cvCreateMemStorage (0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = gst_pad_event_default (pad, parent, event);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* chain function
|
|
||||||
* this function does the actual processing
|
|
||||||
*/
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_face_blur_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
gst_face_blur_transform_ip (GstOpencvVideoFilter * transform,
|
||||||
|
GstBuffer * buffer, IplImage * img)
|
||||||
{
|
{
|
||||||
GstFaceBlur *filter;
|
GstFaceBlur *filter = GST_FACE_BLUR (transform);
|
||||||
CvSeq *faces;
|
CvSeq *faces;
|
||||||
GstMapInfo info;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
filter = GST_FACE_BLUR (GST_OBJECT_PARENT (pad));
|
if (!filter->cvCascade)
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
buf = gst_buffer_make_writable (buf);
|
cvCvtColor (img, filter->cvGray, CV_RGB2GRAY);
|
||||||
gst_buffer_map (buf, &info, GST_MAP_READWRITE);
|
|
||||||
filter->cvImage->imageData = (char *) info.data;
|
|
||||||
|
|
||||||
cvCvtColor (filter->cvImage, filter->cvGray, CV_RGB2GRAY);
|
|
||||||
cvClearMemStorage (filter->cvStorage);
|
cvClearMemStorage (filter->cvStorage);
|
||||||
|
|
||||||
if (filter->cvCascade) {
|
faces =
|
||||||
faces =
|
cvHaarDetectObjects (filter->cvGray, filter->cvCascade,
|
||||||
cvHaarDetectObjects (filter->cvGray, filter->cvCascade,
|
filter->cvStorage, 1.1, 2, 0, cvSize (30, 30)
|
||||||
filter->cvStorage, 1.1, 2, 0, cvSize (30, 30)
|
|
||||||
#if (CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >= 2)
|
#if (CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >= 2)
|
||||||
, cvSize (0, 0)
|
, cvSize (0, 0)
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
|
||||||
if (faces && faces->total > 0) {
|
for (i = 0; i < (faces ? faces->total : 0); i++) {
|
||||||
buf = gst_buffer_make_writable (buf);
|
CvRect *r = (CvRect *) cvGetSeqElem (faces, i);
|
||||||
}
|
cvSetImageROI (img, *r);
|
||||||
for (i = 0; i < (faces ? faces->total : 0); i++) {
|
cvSmooth (img, img, CV_BLUR, 11, 11, 0, 0);
|
||||||
CvRect *r = (CvRect *) cvGetSeqElem (faces, i);
|
cvSmooth (img, img, CV_GAUSSIAN, 11, 11, 0, 0);
|
||||||
cvSetImageROI (filter->cvImage, *r);
|
cvResetImageROI (img);
|
||||||
cvSmooth (filter->cvImage, filter->cvImage, CV_BLUR, 11, 11, 0, 0);
|
|
||||||
cvSmooth (filter->cvImage, filter->cvImage, CV_GAUSSIAN, 11, 11, 0, 0);
|
|
||||||
cvResetImageROI (filter->cvImage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* these filters operate in place, so we push the same buffer */
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
return gst_pad_push (filter->srcpad, buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -318,9 +274,8 @@ gst_face_blur_load_profile (GstFaceBlur * filter)
|
|||||||
cvReleaseHaarClassifierCascade (&filter->cvCascade);
|
cvReleaseHaarClassifierCascade (&filter->cvCascade);
|
||||||
filter->cvCascade =
|
filter->cvCascade =
|
||||||
(CvHaarClassifierCascade *) cvLoad (filter->profile, 0, 0, 0);
|
(CvHaarClassifierCascade *) cvLoad (filter->profile, 0, 0, 0);
|
||||||
if (!filter->cvCascade) {
|
if (!filter->cvCascade)
|
||||||
GST_WARNING ("Couldn't load Haar classifier cascade: %s.", filter->profile);
|
GST_WARNING ("Couldn't load Haar classifier cascade: %s.", filter->profile);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,6 +49,8 @@
|
|||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <cv.h>
|
#include <cv.h>
|
||||||
|
|
||||||
|
#include "gstopencvvideofilter.h"
|
||||||
|
|
||||||
#if (CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >= 2)
|
#if (CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >= 2)
|
||||||
#include <opencv2/objdetect/objdetect.hpp>
|
#include <opencv2/objdetect/objdetect.hpp>
|
||||||
#endif
|
#endif
|
||||||
@ -70,22 +72,20 @@ typedef struct _GstFaceBlurClass GstFaceBlurClass;
|
|||||||
|
|
||||||
struct _GstFaceBlur
|
struct _GstFaceBlur
|
||||||
{
|
{
|
||||||
GstElement element;
|
GstOpencvVideoFilter element;
|
||||||
|
|
||||||
GstPad *sinkpad, *srcpad;
|
|
||||||
|
|
||||||
gboolean display;
|
gboolean display;
|
||||||
|
|
||||||
gchar *profile;
|
gchar *profile;
|
||||||
|
|
||||||
IplImage *cvImage, *cvGray;
|
IplImage *cvGray;
|
||||||
CvHaarClassifierCascade *cvCascade;
|
CvHaarClassifierCascade *cvCascade;
|
||||||
CvMemStorage *cvStorage;
|
CvMemStorage *cvStorage;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstFaceBlurClass
|
struct _GstFaceBlurClass
|
||||||
{
|
{
|
||||||
GstElementClass parent_class;
|
GstOpencvVideoFilterClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_face_blur_get_type (void);
|
GType gst_face_blur_get_type (void);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user