/* Clean up */ static void gst_face_detect_finalize (GObject * obj) { GstFaceDetect *filter = GST_FACE_DETECT (obj); if (filter->cvGray) cvReleaseImage (&filter->cvGray); if (filter->cvStorage) cvReleaseMemStorage (&filter->cvStorage); g_free (filter->face_profile); g_free (filter->nose_profile); g_free (filter->mouth_profile); g_free (filter->eyes_profile); if (filter->cvFaceDetect) cvReleaseHaarClassifierCascade (&filter->cvFaceDetect); if (filter->cvNoseDetect) cvReleaseHaarClassifierCascade (&filter->cvNoseDetect); if (filter->cvMouthDetect) cvReleaseHaarClassifierCascade (&filter->cvMouthDetect); if (filter->cvEyesDetect) cvReleaseHaarClassifierCascade (&filter->cvEyesDetect); G_OBJECT_CLASS (gst_face_detect_parent_class)->finalize (obj); }
static void gst_face_detect_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstFaceDetect *filter = GST_FACE_DETECT (object); switch (prop_id) { case PROP_FACE_PROFILE: g_value_set_string (value, filter->face_profile); break; case PROP_NOSE_PROFILE: g_value_set_string (value, filter->nose_profile); break; case PROP_MOUTH_PROFILE: g_value_set_string (value, filter->mouth_profile); break; case PROP_EYES_PROFILE: g_value_set_string (value, filter->eyes_profile); break; case PROP_DISPLAY: g_value_set_boolean (value, filter->display); break; case PROP_SCALE_FACTOR: g_value_set_double (value, filter->scale_factor); break; case PROP_MIN_NEIGHBORS: g_value_set_int (value, filter->min_neighbors); break; case PROP_MIN_SIZE_WIDTH: g_value_set_int (value, filter->min_size_width); break; case PROP_MIN_SIZE_HEIGHT: g_value_set_int (value, filter->min_size_height); break; case PROP_MIN_STDDEV: g_value_set_int (value, filter->min_stddev); break; case PROP_FLAGS: g_value_set_flags (value, filter->flags); break; case PROP_UPDATES: g_value_set_enum (value, filter->updates); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
/* this function handles the link with other elements */ static gboolean gst_face_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) { GstFaceDetect *filter; filter = GST_FACE_DETECT (transform); if (filter->cvGray) cvReleaseImage (&filter->cvGray); filter->cvGray = cvCreateImage (cvSize (in_width, in_height), IPL_DEPTH_8U, 1); if (!filter->cvStorage) filter->cvStorage = cvCreateMemStorage (0); else cvClearMemStorage (filter->cvStorage); return TRUE; }
/* * Performs the face detection */ static GstFlowReturn gst_face_detect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf, IplImage * img) { GstFaceDetect *filter = GST_FACE_DETECT (base); if (filter->cvFaceDetect) { GstMessage *msg = NULL; GstStructure *s; GValue facelist = { 0 }; GValue facedata = { 0 }; CvSeq *faces; CvSeq *mouth = NULL, *nose = NULL, *eyes = NULL; gint i; gboolean do_display = FALSE; if (filter->display) { if (gst_buffer_is_writable (buf)) { do_display = TRUE; } else { GST_LOG_OBJECT (filter, "Buffer is not writable, not drawing faces."); } } 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); 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); guint mw = filter->min_size_width / 8; guint mh = filter->min_size_height / 8; guint rnx = 0, rny = 0, rnw, rnh; guint rmx = 0, rmy = 0, rmw, rmh; guint rex = 0, rey = 0, rew, reh; gboolean have_nose, have_mouth, have_eyes; /* 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); } 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); } 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); } 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, have_eyes, have_nose, have_mouth); 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); 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); 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); } 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); 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); } 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); 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); } g_value_init (&facedata, GST_TYPE_STRUCTURE); g_value_take_boxed (&facedata, s); gst_value_list_append_value (&facelist, &facedata); g_value_unset (&facedata); s = NULL; if (do_display) { CvPoint center; CvSize 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)); 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); if (have_nose) { CvRect *sr = (CvRect *) cvGetSeqElem (nose, 0); 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); } if (have_mouth) { CvRect *sr = (CvRect *) cvGetSeqElem (mouth, 0); 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); } if (have_eyes) { CvRect *sr = (CvRect *) cvGetSeqElem (eyes, 0); 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); } } } gst_structure_set_value ((GstStructure *) gst_message_get_structure (msg), "faces", &facelist); g_value_unset (&facelist); gst_element_post_message (GST_ELEMENT (filter), msg); } return GST_FLOW_OK; }
static void gst_face_detect_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstFaceDetect *filter = GST_FACE_DETECT (object); switch (prop_id) { case PROP_FACE_PROFILE: g_free (filter->face_profile); if (filter->cvFaceDetect) cvReleaseHaarClassifierCascade (&filter->cvFaceDetect); filter->face_profile = g_value_dup_string (value); filter->cvFaceDetect = gst_face_detect_load_profile (filter, filter->face_profile); break; case PROP_NOSE_PROFILE: g_free (filter->nose_profile); if (filter->cvNoseDetect) cvReleaseHaarClassifierCascade (&filter->cvNoseDetect); filter->nose_profile = g_value_dup_string (value); filter->cvNoseDetect = gst_face_detect_load_profile (filter, filter->nose_profile); break; case PROP_MOUTH_PROFILE: g_free (filter->mouth_profile); if (filter->cvMouthDetect) cvReleaseHaarClassifierCascade (&filter->cvMouthDetect); filter->mouth_profile = g_value_dup_string (value); filter->cvMouthDetect = gst_face_detect_load_profile (filter, filter->mouth_profile); break; case PROP_EYES_PROFILE: g_free (filter->eyes_profile); if (filter->cvEyesDetect) cvReleaseHaarClassifierCascade (&filter->cvEyesDetect); filter->eyes_profile = g_value_dup_string (value); filter->cvEyesDetect = gst_face_detect_load_profile (filter, filter->eyes_profile); break; case PROP_DISPLAY: filter->display = g_value_get_boolean (value); break; case PROP_SCALE_FACTOR: filter->scale_factor = g_value_get_double (value); break; case PROP_MIN_NEIGHBORS: filter->min_neighbors = g_value_get_int (value); break; case PROP_MIN_SIZE_WIDTH: filter->min_size_width = g_value_get_int (value); break; case PROP_MIN_SIZE_HEIGHT: filter->min_size_height = g_value_get_int (value); break; case PROP_FLAGS: filter->flags = g_value_get_flags (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }