From 78d0c5f01ef8d361c66a346aa670ce35a94c247e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Vanessa=20Chipirr=C3=A1s?= Date: Fri, 31 Jul 2015 13:45:43 +0100 Subject: [PATCH] facedetect: need to migrate to C++ The cascade classifier changes its structure on new version of OpenCV. The need to migrate to C++ to utilize the new load method of OpenCV which allows to load the new classifiers. https://bugzilla.gnome.org/show_bug.cgi?id=748377 --- ext/opencv/Makefile.am | 4 +- ext/opencv/{gstfacedetect.c => gstfacedetect.cpp} | 270 +++++++++++----------- ext/opencv/gstfacedetect.h | 9 +- ext/opencv/{gstopencv.c => gstopencv.cpp} | 2 +- 4 files changed, 146 insertions(+), 139 deletions(-) rename ext/opencv/{gstfacedetect.c => gstfacedetect.cpp} (77%) rename ext/opencv/{gstopencv.c => gstopencv.cpp} (98%) diff --git a/ext/opencv/Makefile.am b/ext/opencv/Makefile.am index 3ba1c34..0d2e1bb 100644 --- a/ext/opencv/Makefile.am +++ b/ext/opencv/Makefile.am @@ -1,7 +1,7 @@ plugin_LTLIBRARIES = libgstopencv.la # sources used to compile this plug-in -libgstopencv_la_SOURCES = gstopencv.c \ +libgstopencv_la_SOURCES = gstopencv.cpp \ gstopencvvideofilter.c \ gstopencvutils.c \ gstcvdilate.c \ @@ -13,7 +13,6 @@ libgstopencv_la_SOURCES = gstopencv.c \ gstcvsobel.c \ gstedgedetect.c \ gstfaceblur.c \ - gstfacedetect.c \ gsthanddetect.c \ gstpyramidsegment.c \ gsttemplatematch.c \ @@ -21,6 +20,7 @@ libgstopencv_la_SOURCES = gstopencv.c \ gstmotioncells.c \ gstskindetect.c \ gstretinex.c \ + gstfacedetect.cpp \ gstsegmentation.cpp \ gstgrabcut.cpp \ gstdisparity.cpp \ diff --git a/ext/opencv/gstfacedetect.c b/ext/opencv/gstfacedetect.cpp similarity index 77% rename from ext/opencv/gstfacedetect.c rename to ext/opencv/gstfacedetect.cpp index ebe8aca..8716128 100644 --- a/ext/opencv/gstfacedetect.c +++ b/ext/opencv/gstfacedetect.cpp @@ -5,7 +5,7 @@ * Copyright (C) 2008 Michael Sheldon * Copyright (C) 2011 Stefan Sauer * Copyright (C) 2014 Robert Jobbagy - * + * * 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 @@ -52,8 +52,8 @@ * If you have high cpu load you need to use videoscale with capsfilter and reduce the video resolution. * * The image is scaled down multiple times using the GstFaceDetect::scale-factor - * until the size is <= GstFaceDetect::min-size-width or - * GstFaceDetect::min-size-height. + * until the size is <= GstFaceDetect::min-size-width or + * GstFaceDetect::min-size-height. * * * Example launch line @@ -62,7 +62,7 @@ * ]| Detect and show faces * |[ * gst-launch-1.0 autovideosrc ! video/x-raw,width=320,height=240 ! videoconvert ! facedetect min-size-width=60 min-size-height=60 ! colorspace ! xvimagesink - * ]| Detect large faces on a smaller image + * ]| Detect large faces on a smaller image * * */ @@ -78,6 +78,7 @@ #include #include +#include #include "gstopencvutils.h" #include "gstfacedetect.h" @@ -100,6 +101,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_face_detect_debug); #define DEFAULT_MIN_SIZE_HEIGHT 30 #define DEFAULT_MIN_STDDEV 0 +using namespace cv; /* Filter signals and args */ enum { @@ -211,7 +213,7 @@ static gboolean gst_face_detect_set_caps (GstOpencvVideoFilter * transform, static GstFlowReturn gst_face_detect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf, IplImage * img); -static CvHaarClassifierCascade *gst_face_detect_load_profile (GstFaceDetect * +static CascadeClassifier *gst_face_detect_load_profile (GstFaceDetect * filter, gchar * profile); /* Clean up */ @@ -221,7 +223,7 @@ gst_face_detect_finalize (GObject * obj) GstFaceDetect *filter = GST_FACE_DETECT (obj); if (filter->cvGray) - cvReleaseImage (&filter->cvGray); + delete (&filter->cvGray); if (filter->cvStorage) cvReleaseMemStorage (&filter->cvStorage); @@ -231,13 +233,13 @@ gst_face_detect_finalize (GObject * obj) g_free (filter->eyes_profile); if (filter->cvFaceDetect) - cvReleaseHaarClassifierCascade (&filter->cvFaceDetect); + delete (&filter->cvFaceDetect); if (filter->cvNoseDetect) - cvReleaseHaarClassifierCascade (&filter->cvNoseDetect); + delete (&filter->cvNoseDetect); if (filter->cvMouthDetect) - cvReleaseHaarClassifierCascade (&filter->cvMouthDetect); + delete (&filter->cvMouthDetect); if (filter->cvEyesDetect) - cvReleaseHaarClassifierCascade (&filter->cvEyesDetect); + delete (&filter->cvEyesDetect); G_OBJECT_CLASS (gst_face_detect_parent_class)->finalize (obj); } @@ -263,60 +265,66 @@ gst_face_detect_class_init (GstFaceDetectClass * klass) g_object_class_install_property (gobject_class, PROP_DISPLAY, g_param_spec_boolean ("display", "Display", "Sets whether the detected faces should be highlighted in the output", - TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + TRUE, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); g_object_class_install_property (gobject_class, PROP_FACE_PROFILE, g_param_spec_string ("profile", "Face profile", "Location of Haar cascade file to use for face detection", - DEFAULT_FACE_PROFILE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + DEFAULT_FACE_PROFILE, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); g_object_class_install_property (gobject_class, PROP_NOSE_PROFILE, g_param_spec_string ("nose-profile", "Nose profile", "Location of Haar cascade file to use for nose detection", - DEFAULT_NOSE_PROFILE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + DEFAULT_NOSE_PROFILE, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); g_object_class_install_property (gobject_class, PROP_MOUTH_PROFILE, g_param_spec_string ("mouth-profile", "Mouth profile", "Location of Haar cascade file to use for mouth detection", - DEFAULT_MOUTH_PROFILE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + DEFAULT_MOUTH_PROFILE, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); g_object_class_install_property (gobject_class, PROP_EYES_PROFILE, g_param_spec_string ("eyes-profile", "Eyes profile", "Location of Haar cascade file to use for eye-pair detection", - DEFAULT_EYES_PROFILE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + DEFAULT_EYES_PROFILE, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); g_object_class_install_property (gobject_class, PROP_FLAGS, g_param_spec_flags ("flags", "Flags", "Flags to cvHaarDetectObjects", GST_TYPE_OPENCV_FACE_DETECT_FLAGS, DEFAULT_FLAGS, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); g_object_class_install_property (gobject_class, PROP_SCALE_FACTOR, g_param_spec_double ("scale-factor", "Scale factor", "Factor by which the frame is scaled after each object scan", 1.1, 10.0, DEFAULT_SCALE_FACTOR, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); g_object_class_install_property (gobject_class, PROP_MIN_NEIGHBORS, g_param_spec_int ("min-neighbors", "Mininum neighbors", "Minimum number (minus 1) of neighbor rectangles that makes up " "an object", 0, G_MAXINT, DEFAULT_MIN_NEIGHBORS, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); g_object_class_install_property (gobject_class, PROP_MIN_SIZE_WIDTH, g_param_spec_int ("min-size-width", "Minimum face width", "Minimum area width to be recognized as a face", 0, G_MAXINT, - DEFAULT_MIN_SIZE_WIDTH, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + DEFAULT_MIN_SIZE_WIDTH, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); g_object_class_install_property (gobject_class, PROP_MIN_SIZE_HEIGHT, g_param_spec_int ("min-size-height", "Minimum face height", "Minimum area height to be recognized as a face", 0, G_MAXINT, - DEFAULT_MIN_SIZE_HEIGHT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + DEFAULT_MIN_SIZE_HEIGHT, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); g_object_class_install_property (gobject_class, PROP_UPDATES, g_param_spec_enum ("updates", "Updates", "When send update bus messages, if at all", GST_TYPE_FACE_DETECT_UPDATES, GST_FACEDETECT_UPDATES_EVERY_FRAME, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); g_object_class_install_property (gobject_class, PROP_MIN_STDDEV, g_param_spec_int ("min-stddev", "Minimum image standard deviation", "Minimum image average standard deviation: on images with standard " "deviation lesser than this value facedetection will not be " "performed. Setting this property help to save cpu and reduce " "false positives not performing face detection on images with " - "little changes", 0, - 255, DEFAULT_MIN_STDDEV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + "little changes", 0, 255, DEFAULT_MIN_STDDEV, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); gst_element_class_set_static_metadata (element_class, "facedetect", @@ -372,7 +380,7 @@ gst_face_detect_set_property (GObject * object, guint prop_id, case PROP_FACE_PROFILE: g_free (filter->face_profile); if (filter->cvFaceDetect) - cvReleaseHaarClassifierCascade (&filter->cvFaceDetect); + delete (&filter->cvFaceDetect); filter->face_profile = g_value_dup_string (value); filter->cvFaceDetect = gst_face_detect_load_profile (filter, filter->face_profile); @@ -380,7 +388,7 @@ gst_face_detect_set_property (GObject * object, guint prop_id, case PROP_NOSE_PROFILE: g_free (filter->nose_profile); if (filter->cvNoseDetect) - cvReleaseHaarClassifierCascade (&filter->cvNoseDetect); + delete (&filter->cvNoseDetect); filter->nose_profile = g_value_dup_string (value); filter->cvNoseDetect = gst_face_detect_load_profile (filter, filter->nose_profile); @@ -388,7 +396,7 @@ gst_face_detect_set_property (GObject * object, guint prop_id, case PROP_MOUTH_PROFILE: g_free (filter->mouth_profile); if (filter->cvMouthDetect) - cvReleaseHaarClassifierCascade (&filter->cvMouthDetect); + delete (&filter->cvMouthDetect); filter->mouth_profile = g_value_dup_string (value); filter->cvMouthDetect = gst_face_detect_load_profile (filter, filter->mouth_profile); @@ -396,7 +404,7 @@ gst_face_detect_set_property (GObject * object, guint prop_id, case PROP_EYES_PROFILE: g_free (filter->eyes_profile); if (filter->cvEyesDetect) - cvReleaseHaarClassifierCascade (&filter->cvEyesDetect); + delete (&filter->cvEyesDetect); filter->eyes_profile = g_value_dup_string (value); filter->cvEyesDetect = gst_face_detect_load_profile (filter, filter->eyes_profile); @@ -493,7 +501,7 @@ gst_face_detect_set_caps (GstOpencvVideoFilter * transform, gint in_width, filter = GST_FACE_DETECT (transform); if (filter->cvGray) - cvReleaseImage (&filter->cvGray); + delete (&filter->cvGray); filter->cvGray = cvCreateImage (cvSize (in_width, in_height), IPL_DEPTH_8U, 1); @@ -527,10 +535,10 @@ gst_face_detect_message_new (GstFaceDetect * filter, GstBuffer * buf) return gst_message_new_element (GST_OBJECT (filter), s); } -static CvSeq * +static void gst_face_detect_run_detector (GstFaceDetect * filter, - CvHaarClassifierCascade * detector, gint min_size_width, - gint min_size_height) + CascadeClassifier * detector, gint min_size_width, + gint min_size_height, Rect r, vector &faces) { double img_stddev = 0; if (filter->min_stddev > 0) { @@ -539,9 +547,10 @@ gst_face_detect_run_detector (GstFaceDetect * filter, img_stddev = stddev.val[0]; } if (img_stddev >= filter->min_stddev) { - return cvHaarDetectObjects (filter->cvGray, detector, - filter->cvStorage, filter->scale_factor, filter->min_neighbors, - filter->flags, cvSize (min_size_width, min_size_height) + Mat roi (filter->cvGray, r); + detector->detectMultiScale (roi, faces, filter->scale_factor, + filter->min_neighbors, filter->flags, cvSize (min_size_width, + min_size_height) #if (CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >= 2) , cvSize (0, 0) #endif @@ -550,7 +559,6 @@ gst_face_detect_run_detector (GstFaceDetect * filter, GST_LOG_OBJECT (filter, "Calculated stddev %f lesser than min_stddev %d, detection not performed", img_stddev, filter->min_stddev); - return cvCreateSeq (0, sizeof (CvSeq), sizeof (CvPoint), filter->cvStorage); } } @@ -568,12 +576,15 @@ gst_face_detect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf, GstStructure *s; GValue facelist = { 0 }; GValue facedata = { 0 }; - CvSeq *faces; - CvSeq *mouth = NULL, *nose = NULL, *eyes = NULL; - gint i; + vector faces; + vector mouth; + vector nose; + vector eyes; gboolean do_display = FALSE; gboolean post_msg = FALSE; + Mat mtxOrg (img, false); + if (filter->display) { if (gst_buffer_is_writable (buf)) { do_display = TRUE; @@ -585,15 +596,17 @@ gst_face_detect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf, cvCvtColor (img, filter->cvGray, CV_RGB2GRAY); cvClearMemStorage (filter->cvStorage); - faces = gst_face_detect_run_detector (filter, filter->cvFaceDetect, - filter->min_size_width, filter->min_size_height); + gst_face_detect_run_detector (filter, filter->cvFaceDetect, + filter->min_size_width, filter->min_size_height, + Rect (filter->cvGray->origin, filter->cvGray->origin, + filter->cvGray->width, filter->cvGray->height), faces); switch (filter->updates) { case GST_FACEDETECT_UPDATES_EVERY_FRAME: post_msg = TRUE; break; case GST_FACEDETECT_UPDATES_ON_CHANGE: - if (faces && faces->total > 0) { + if (!faces.empty () && (faces.size () > 0)) { if (!filter->face_detected) post_msg = TRUE; } else { @@ -603,7 +616,7 @@ gst_face_detect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf, } break; case GST_FACEDETECT_UPDATES_ON_FACE: - if (faces && faces->total > 0) { + if (!faces.empty () && (faces.size () > 0)) { post_msg = TRUE; } else { post_msg = FALSE; @@ -617,15 +630,15 @@ gst_face_detect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf, break; } - filter->face_detected = faces ? faces->total > 0 : FALSE; + filter->face_detected = !faces.empty ()? faces.size () > 0 : FALSE; if (post_msg) { msg = gst_face_detect_message_new (filter, buf); g_value_init (&facelist, GST_TYPE_LIST); } - for (i = 0; i < (faces ? faces->total : 0); i++) { - CvRect *r = (CvRect *) cvGetSeqElem (faces, i); + for (unsigned int i = 0; i < faces.size (); ++i) { + Rect r = faces[i]; guint mw = filter->min_size_width / 8; guint mh = filter->min_size_height / 8; guint rnx = 0, rny = 0, rnw, rnh; @@ -636,87 +649,80 @@ gst_face_detect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf, /* detect face features */ if (filter->cvNoseDetect) { - rnx = r->x + r->width / 4; - rny = r->y + r->height / 4; - rnw = r->width / 2; - rnh = r->height / 2; - cvSetImageROI (filter->cvGray, cvRect (rnx, rny, rnw, rnh)); - nose = - gst_face_detect_run_detector (filter, filter->cvNoseDetect, mw, mh); - have_nose = (nose && nose->total); - cvResetImageROI (filter->cvGray); + rnx = r.x + r.width / 4; + rny = r.y + r.height / 4; + rnw = r.width / 2; + rnh = r.height / 2; + gst_face_detect_run_detector (filter, filter->cvNoseDetect, mw, mh, + Rect (rnx, rny, rnw, rnh), nose); + have_nose = (!nose.empty () && nose.size ()); } else { have_nose = FALSE; } if (filter->cvMouthDetect) { - rmx = r->x; - rmy = r->y + r->height / 2; - rmw = r->width; - rmh = r->height / 2; - cvSetImageROI (filter->cvGray, cvRect (rmx, rmy, rmw, rmh)); - mouth = - gst_face_detect_run_detector (filter, filter->cvMouthDetect, mw, - mh); - have_mouth = (mouth && mouth->total); - cvResetImageROI (filter->cvGray); + rmx = r.x; + rmy = r.y + r.height / 2; + rmw = r.width; + rmh = r.height / 2; + gst_face_detect_run_detector (filter, filter->cvMouthDetect, mw, + mh, Rect (rmx, rmy, rmw, rmh), mouth); + have_mouth = (!mouth.empty () && mouth.size ()); } else { have_mouth = FALSE; } if (filter->cvEyesDetect) { - rex = r->x; - rey = r->y; - rew = r->width; - reh = r->height / 2; - cvSetImageROI (filter->cvGray, cvRect (rex, rey, rew, reh)); - eyes = - gst_face_detect_run_detector (filter, filter->cvEyesDetect, mw, mh); - have_eyes = (eyes && eyes->total); - cvResetImageROI (filter->cvGray); + rex = r.x; + rey = r.y; + rew = r.width; + reh = r.height / 2; + gst_face_detect_run_detector (filter, filter->cvEyesDetect, mw, mh, + Rect (rex, rey, rew, reh), eyes); + have_eyes = (!eyes.empty () && eyes.size ()); } else { have_eyes = FALSE; } GST_LOG_OBJECT (filter, - "%2d/%2d: x,y = %4u,%4u: w.h = %4u,%4u : features(e,n,m) = %d,%d,%d", - i, faces->total, r->x, r->y, r->width, r->height, + "%2d/%2lu: x,y = %4u,%4u: w.h = %4u,%4u : features(e,n,m) = %d,%d,%d", + i, faces.size (), r.x, r.y, r.width, r.height, have_eyes, have_nose, have_mouth); if (post_msg) { s = gst_structure_new ("face", - "x", G_TYPE_UINT, r->x, - "y", G_TYPE_UINT, r->y, - "width", G_TYPE_UINT, r->width, - "height", G_TYPE_UINT, r->height, NULL); + "x", G_TYPE_UINT, r.x, + "y", G_TYPE_UINT, r.y, + "width", G_TYPE_UINT, r.width, + "height", G_TYPE_UINT, r.height, NULL); if (have_nose) { - CvRect *sr = (CvRect *) cvGetSeqElem (nose, 0); - GST_LOG_OBJECT (filter, "nose/%d: x,y = %4u,%4u: w.h = %4u,%4u", - nose->total, rnx + sr->x, rny + sr->y, sr->width, sr->height); + Rect sr = nose[0]; + GST_LOG_OBJECT (filter, "nose/%lu: x,y = %4u,%4u: w.h = %4u,%4u", + nose.size (), rnx + sr.x, rny + sr.y, sr.width, sr.height); gst_structure_set (s, - "nose->x", G_TYPE_UINT, rnx + sr->x, - "nose->y", G_TYPE_UINT, rny + sr->y, - "nose->width", G_TYPE_UINT, sr->width, - "nose->height", G_TYPE_UINT, sr->height, NULL); + "nose->x", G_TYPE_UINT, rnx + sr.x, + "nose->y", G_TYPE_UINT, rny + sr.y, + "nose->width", G_TYPE_UINT, sr.width, + "nose->height", G_TYPE_UINT, sr.height, NULL); } if (have_mouth) { - CvRect *sr = (CvRect *) cvGetSeqElem (mouth, 0); - GST_LOG_OBJECT (filter, "mouth/%d: x,y = %4u,%4u: w.h = %4u,%4u", - mouth->total, rmx + sr->x, rmy + sr->y, sr->width, sr->height); + Rect sr = mouth[0]; + GST_LOG_OBJECT (filter, "mouth/%lu: x,y = %4u,%4u: w.h = %4u,%4u", + mouth.size (), rmx + sr.x, rmy + sr.y, sr.width, sr.height); gst_structure_set (s, - "mouth->x", G_TYPE_UINT, rmx + sr->x, - "mouth->y", G_TYPE_UINT, rmy + sr->y, - "mouth->width", G_TYPE_UINT, sr->width, - "mouth->height", G_TYPE_UINT, sr->height, NULL); + "mouth->x", G_TYPE_UINT, rmx + sr.x, + "mouth->y", G_TYPE_UINT, rmy + sr.y, + "mouth->width", G_TYPE_UINT, sr.width, + "mouth->height", G_TYPE_UINT, sr.height, NULL); } if (have_eyes) { - CvRect *sr = (CvRect *) cvGetSeqElem (eyes, 0); - GST_LOG_OBJECT (filter, "eyes/%d: x,y = %4u,%4u: w.h = %4u,%4u", - eyes->total, rex + sr->x, rey + sr->y, sr->width, sr->height); + Rect sr = eyes[0]; + GST_LOG_OBJECT (filter, "eyes/%ld: x,y = %4u,%4u: w.h = %4u,%4u", + eyes.size (), rex + sr.x, rey + sr.y, sr.width, sr.height); gst_structure_set (s, - "eyes->x", G_TYPE_UINT, rex + sr->x, - "eyes->y", G_TYPE_UINT, rey + sr->y, - "eyes->width", G_TYPE_UINT, sr->width, - "eyes->height", G_TYPE_UINT, sr->height, NULL); + "eyes->x", G_TYPE_UINT, rex + sr.x, + "eyes->y", G_TYPE_UINT, rey + sr.y, + "eyes->width", G_TYPE_UINT, sr.width, + "eyes->height", G_TYPE_UINT, sr.height, NULL); } g_value_init (&facedata, GST_TYPE_STRUCTURE); @@ -728,60 +734,59 @@ gst_face_detect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf, if (do_display) { CvPoint center; - CvSize axes; + Size axes; gdouble w, h; gint cb = 255 - ((i & 3) << 7); gint cg = 255 - ((i & 12) << 5); gint cr = 255 - ((i & 48) << 3); - w = r->width / 2; - h = r->height / 2; - center.x = cvRound ((r->x + w)); - center.y = cvRound ((r->y + h)); + w = r.width / 2; + h = r.height / 2; + center.x = cvRound ((r.x + w)); + center.y = cvRound ((r.y + h)); axes.width = w; axes.height = h * 1.25; /* tweak for face form */ - cvEllipse (img, center, axes, 0.0, 0.0, 360.0, CV_RGB (cr, cg, cb), - 3, 8, 0); + ellipse (mtxOrg, center, axes, 0, 0, 360, Scalar (cr, cg, cb), 3, 8, 0); if (have_nose) { - CvRect *sr = (CvRect *) cvGetSeqElem (nose, 0); + Rect sr = nose[0]; - w = sr->width / 2; - h = sr->height / 2; - center.x = cvRound ((rnx + sr->x + w)); - center.y = cvRound ((rny + sr->y + h)); + w = sr.width / 2; + h = sr.height / 2; + center.x = cvRound ((rnx + sr.x + w)); + center.y = cvRound ((rny + sr.y + h)); axes.width = w; axes.height = h * 1.25; /* tweak for nose form */ - cvEllipse (img, center, axes, 0.0, 0.0, 360.0, CV_RGB (cr, cg, cb), - 1, 8, 0); + ellipse (mtxOrg, center, axes, 0, 0, 360, Scalar (cr, cg, cb), 1, 8, + 0); } if (have_mouth) { - CvRect *sr = (CvRect *) cvGetSeqElem (mouth, 0); + Rect sr = mouth[0]; - w = sr->width / 2; - h = sr->height / 2; - center.x = cvRound ((rmx + sr->x + w)); - center.y = cvRound ((rmy + sr->y + h)); + w = sr.width / 2; + h = sr.height / 2; + center.x = cvRound ((rmx + sr.x + w)); + center.y = cvRound ((rmy + sr.y + h)); axes.width = w * 1.5; /* tweak for mouth form */ axes.height = h; - cvEllipse (img, center, axes, 0.0, 0.0, 360.0, CV_RGB (cr, cg, cb), - 1, 8, 0); + ellipse (mtxOrg, center, axes, 0, 0, 360, Scalar (cr, cg, cb), 1, 8, + 0); } if (have_eyes) { - CvRect *sr = (CvRect *) cvGetSeqElem (eyes, 0); + Rect sr = eyes[0]; - w = sr->width / 2; - h = sr->height / 2; - center.x = cvRound ((rex + sr->x + w)); - center.y = cvRound ((rey + sr->y + h)); + w = sr.width / 2; + h = sr.height / 2; + center.x = cvRound ((rex + sr.x + w)); + center.y = cvRound ((rey + sr.y + h)); axes.width = w * 1.5; /* tweak for eyes form */ axes.height = h; - cvEllipse (img, center, axes, 0.0, 0.0, 360.0, CV_RGB (cr, cg, cb), - 1, 8, 0); + ellipse (mtxOrg, center, axes, 0, 0, 360, Scalar (cr, cg, cb), 1, 8, + 0); } } gst_buffer_add_video_region_of_interest_meta (buf, "face", - (guint) r->x, (guint) r->y, (guint) r->width, (guint) r->height); + (guint) r.x, (guint) r.y, (guint) r.width, (guint) r.height); } if (post_msg) { @@ -790,20 +795,21 @@ gst_face_detect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf, g_value_unset (&facelist); gst_element_post_message (GST_ELEMENT (filter), msg); } + mtxOrg.release (); } return GST_FLOW_OK; } -static CvHaarClassifierCascade * +static CascadeClassifier * gst_face_detect_load_profile (GstFaceDetect * filter, gchar * profile) { - CvHaarClassifierCascade *cascade; + CascadeClassifier *cascade = new CascadeClassifier (profile); if (profile == NULL) return NULL; - if (!(cascade = (CvHaarClassifierCascade *) cvLoad (profile, 0, 0, 0))) { + if (!cascade) { GST_WARNING_OBJECT (filter, "Couldn't load Haar classifier cascade: %s.", profile); } diff --git a/ext/opencv/gstfacedetect.h b/ext/opencv/gstfacedetect.h index 6db7033..f5ad14d 100644 --- a/ext/opencv/gstfacedetect.h +++ b/ext/opencv/gstfacedetect.h @@ -50,6 +50,7 @@ #include #include +#include #include "gstopencvvideofilter.h" #if (CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >= 2) @@ -107,10 +108,10 @@ struct _GstFaceDetect gint updates; IplImage *cvGray; - CvHaarClassifierCascade *cvFaceDetect; - CvHaarClassifierCascade *cvNoseDetect; - CvHaarClassifierCascade *cvMouthDetect; - CvHaarClassifierCascade *cvEyesDetect; + cv::CascadeClassifier *cvFaceDetect; + cv::CascadeClassifier *cvNoseDetect; + cv::CascadeClassifier *cvMouthDetect; + cv::CascadeClassifier *cvEyesDetect; CvMemStorage *cvStorage; }; diff --git a/ext/opencv/gstopencv.c b/ext/opencv/gstopencv.cpp similarity index 98% rename from ext/opencv/gstopencv.c rename to ext/opencv/gstopencv.cpp index 3184518..4077ba6 100644 --- a/ext/opencv/gstopencv.c +++ b/ext/opencv/gstopencv.cpp @@ -1,7 +1,7 @@ /* GStreamer * Copyright (C) <2009> Kapil Agrawal * - * gstopencv.c: plugin registering + * gstopencv.cpp: plugin registering * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public -- 2.7.4