mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 01:45:33 +00:00
faceblur: need to migrate to C++.
The cascade classifier changes its structure on new version of OpenCV 2.4.11. It is need to migrate to C++ to utilize the new load method of OpenCV which allows to load the old and new classifiers. https://bugzilla.gnome.org/show_bug.cgi?id=753994
This commit is contained in:
parent
acdcfedde2
commit
02d8a4f4e8
2 changed files with 29 additions and 25 deletions
|
@ -62,10 +62,12 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "gstopencvutils.h"
|
#include "gstopencvutils.h"
|
||||||
#include "gstfaceblur.h"
|
#include "gstfaceblur.h"
|
||||||
#include <opencv2/imgproc/imgproc_c.h>
|
#include <opencv2/imgproc/imgproc_c.h>
|
||||||
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
|
|
||||||
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
|
||||||
|
@ -79,6 +81,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_face_blur_debug);
|
||||||
#define DEFAULT_MIN_SIZE_WIDTH 30
|
#define DEFAULT_MIN_SIZE_WIDTH 30
|
||||||
#define DEFAULT_MIN_SIZE_HEIGHT 30
|
#define DEFAULT_MIN_SIZE_HEIGHT 30
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
|
@ -153,7 +156,7 @@ static gboolean gst_face_blur_set_caps (GstOpencvVideoFilter * transform,
|
||||||
static GstFlowReturn gst_face_blur_transform_ip (GstOpencvVideoFilter *
|
static GstFlowReturn gst_face_blur_transform_ip (GstOpencvVideoFilter *
|
||||||
transform, GstBuffer * buffer, IplImage * img);
|
transform, GstBuffer * buffer, IplImage * img);
|
||||||
|
|
||||||
static CvHaarClassifierCascade *gst_face_blur_load_profile (GstFaceBlur *
|
static CascadeClassifier *gst_face_blur_load_profile (GstFaceBlur *
|
||||||
filter, gchar * profile);
|
filter, gchar * profile);
|
||||||
|
|
||||||
/* Clean up */
|
/* Clean up */
|
||||||
|
@ -169,7 +172,7 @@ gst_face_blur_finalize (GObject * obj)
|
||||||
cvReleaseMemStorage (&filter->cvStorage);
|
cvReleaseMemStorage (&filter->cvStorage);
|
||||||
|
|
||||||
if (filter->cvCascade)
|
if (filter->cvCascade)
|
||||||
cvReleaseHaarClassifierCascade (&filter->cvCascade);
|
delete filter->cvCascade;
|
||||||
|
|
||||||
g_free (filter->profile);
|
g_free (filter->profile);
|
||||||
|
|
||||||
|
@ -266,7 +269,7 @@ gst_face_blur_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_PROFILE:
|
case PROP_PROFILE:
|
||||||
g_free (filter->profile);
|
g_free (filter->profile);
|
||||||
if (filter->cvCascade)
|
if (filter->cvCascade)
|
||||||
cvReleaseHaarClassifierCascade (&filter->cvCascade);
|
delete filter->cvCascade;
|
||||||
filter->profile = g_value_dup_string (value);
|
filter->profile = g_value_dup_string (value);
|
||||||
filter->cvCascade = gst_face_blur_load_profile (filter, filter->profile);
|
filter->cvCascade = gst_face_blur_load_profile (filter, filter->profile);
|
||||||
filter->sent_profile_load_failed_msg = FALSE;
|
filter->sent_profile_load_failed_msg = FALSE;
|
||||||
|
@ -348,8 +351,8 @@ gst_face_blur_transform_ip (GstOpencvVideoFilter * transform,
|
||||||
GstBuffer * buffer, IplImage * img)
|
GstBuffer * buffer, IplImage * img)
|
||||||
{
|
{
|
||||||
GstFaceBlur *filter = GST_FACE_BLUR (transform);
|
GstFaceBlur *filter = GST_FACE_BLUR (transform);
|
||||||
CvSeq *faces;
|
vector < Rect > faces;
|
||||||
int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (!filter->cvCascade) {
|
if (!filter->cvCascade) {
|
||||||
if (filter->profile != NULL
|
if (filter->profile != NULL
|
||||||
|
@ -359,41 +362,42 @@ gst_face_blur_transform_ip (GstOpencvVideoFilter * transform,
|
||||||
("missing faceblur profile file %s", filter->profile));
|
("missing faceblur profile file %s", filter->profile));
|
||||||
filter->sent_profile_load_failed_msg = TRUE;
|
filter->sent_profile_load_failed_msg = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
cvCvtColor (img, filter->cvGray, CV_RGB2GRAY);
|
cvCvtColor (img, filter->cvGray, CV_RGB2GRAY);
|
||||||
cvClearMemStorage (filter->cvStorage);
|
cvClearMemStorage (filter->cvStorage);
|
||||||
|
|
||||||
faces =
|
Mat image (filter->cvGray, Rect (filter->cvGray->origin,
|
||||||
cvHaarDetectObjects (filter->cvGray, filter->cvCascade,
|
filter->cvGray->origin, filter->cvGray->width,
|
||||||
filter->cvStorage, filter->scale_factor, filter->min_neighbors,
|
filter->cvGray->height));
|
||||||
filter->flags, cvSize (filter->min_size_width, filter->min_size_height),
|
filter->cvCascade->detectMultiScale (image, faces, filter->scale_factor,
|
||||||
cvSize (filter->min_size_width + 2, filter->min_size_height + 2));
|
filter->min_neighbors, filter->flags,
|
||||||
|
cvSize (filter->min_size_width, filter->min_size_height), cvSize (0, 0));
|
||||||
|
|
||||||
for (i = 0; i < (faces ? faces->total : 0); i++) {
|
if (!faces.empty ()) {
|
||||||
CvRect *r = (CvRect *) cvGetSeqElem (faces, i);
|
|
||||||
cvSetImageROI (img, *r);
|
for (i = 0; i < faces.size (); ++i) {
|
||||||
cvSmooth (img, img, CV_BLUR, 11, 11, 0, 0);
|
Rect *r = &faces[i];
|
||||||
cvSmooth (img, img, CV_GAUSSIAN, 11, 11, 0, 0);
|
Mat roi (img, Rect (r->x, r->y, r->width, r->height));
|
||||||
cvResetImageROI (img);
|
blur (roi, roi, Size (11, 11));
|
||||||
|
GaussianBlur (roi, roi, Size (11, 11), 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CascadeClassifier *
|
||||||
static CvHaarClassifierCascade *
|
|
||||||
gst_face_blur_load_profile (GstFaceBlur * filter, gchar * profile)
|
gst_face_blur_load_profile (GstFaceBlur * filter, gchar * profile)
|
||||||
{
|
{
|
||||||
CvHaarClassifierCascade *cascade;
|
CascadeClassifier *cascade;
|
||||||
|
|
||||||
if (profile == NULL)
|
cascade = new CascadeClassifier (profile);
|
||||||
|
if (cascade->empty ()) {
|
||||||
|
GST_ERROR_OBJECT (filter, "Invalid profile file: %s", profile);
|
||||||
|
delete cascade;
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!(cascade = (CvHaarClassifierCascade *) cvLoad (profile, 0, 0, 0))) {
|
|
||||||
GST_WARNING_OBJECT (filter, "Couldn't load Haar classifier cascade: %s.",
|
|
||||||
profile);
|
|
||||||
}
|
}
|
||||||
return cascade;
|
return cascade;
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ struct _GstFaceBlur
|
||||||
gint min_size_height;
|
gint min_size_height;
|
||||||
|
|
||||||
IplImage *cvGray;
|
IplImage *cvGray;
|
||||||
CvHaarClassifierCascade *cvCascade;
|
cv::CascadeClassifier *cvCascade;
|
||||||
CvMemStorage *cvStorage;
|
CvMemStorage *cvStorage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue