/* 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);
}
Beispiel #2
0
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;
  }
}