static gboolean gst_faceblur_set_caps (GstBaseTransform * base, GstCaps * incaps, GstCaps * outcaps) { GstFaceblur *this; GstStructure *structure; gboolean res; this = GST_FACEBLUR (base); GST_DEBUG_OBJECT (this, "set_caps: in %" GST_PTR_FORMAT " out %" GST_PTR_FORMAT, incaps, outcaps); structure = gst_caps_get_structure (incaps, 0); res = gst_structure_get_int (structure, "width", &this->width); res &= gst_structure_get_int (structure, "height", &this->height); if (!res) goto done; this->size = this->width * this->height * 3; done: return res; }
/* Clean up */ static void gst_faceblur_finalize (GObject * obj) { Gstfaceblur *filter = GST_FACEBLUR (obj); if (filter->cvImage) { cvReleaseImage (&filter->cvImage); cvReleaseImage (&filter->cvGray); } g_free (filter->profile); G_OBJECT_CLASS (parent_class)->finalize (obj); }
static void gst_faceblur_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { Gstfaceblur *filter = GST_FACEBLUR (object); switch (prop_id) { case PROP_PROFILE: g_value_set_string (value, filter->profile); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void gst_faceblur_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstFaceblur *faceblur; g_return_if_fail (GST_IS_FACEBLUR (object)); faceblur = GST_FACEBLUR (object); switch (prop_id) { case PROP_FACE_WIDTH: g_value_set_int (value, faceblur->face_width); break; case PROP_FACE_HEIGHT: g_value_set_int (value, faceblur->face_height); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void gst_faceblur_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstFaceblur *faceblur; g_return_if_fail (GST_IS_FACEBLUR (object)); faceblur = GST_FACEBLUR (object); GST_DEBUG ("gst_faceblur_set_property"); switch (prop_id) { case PROP_FACE_WIDTH: faceblur->face_width = g_value_get_int (value); break; case PROP_FACE_HEIGHT: faceblur->face_height = g_value_get_int (value); break; default: break; } }
/* chain function * this function does the actual processing */ static GstFlowReturn gst_faceblur_chain (GstPad * pad, GstBuffer * buf) { Gstfaceblur *filter; CvSeq *faces; int i; filter = GST_FACEBLUR (GST_OBJECT_PARENT (pad)); filter->cvImage->imageData = (char *) GST_BUFFER_DATA (buf); cvCvtColor (filter->cvImage, filter->cvGray, CV_RGB2GRAY); cvClearMemStorage (filter->cvStorage); if (filter->cvCascade) { faces = cvHaarDetectObjects (filter->cvGray, filter->cvCascade, filter->cvStorage, 1.1, 2, 0, cvSize (30, 30) #if (CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >= 2) , cvSize (32, 32) #endif ); if (faces && faces->total > 0) { buf = gst_buffer_make_writable (buf); } for (i = 0; i < (faces ? faces->total : 0); i++) { CvRect *r = (CvRect *) cvGetSeqElem (faces, i); cvSetImageROI (filter->cvImage, *r); 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_pad_push (filter->srcpad, buf); }
/* this function handles the link with other elements */ static gboolean gst_faceblur_set_caps (GstPad * pad, GstCaps * caps) { Gstfaceblur *filter; GstPad *otherpad; gint width, height; GstStructure *structure; filter = GST_FACEBLUR (gst_pad_get_parent (pad)); structure = gst_caps_get_structure (caps, 0); gst_structure_get_int (structure, "width", &width); gst_structure_get_int (structure, "height", &height); filter->cvImage = cvCreateImage (cvSize (width, height), IPL_DEPTH_8U, 3); filter->cvGray = cvCreateImage (cvSize (width, height), IPL_DEPTH_8U, 1); filter->cvStorage = cvCreateMemStorage (0); otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad; gst_object_unref (filter); return gst_pad_set_caps (otherpad, caps); }
static gboolean gst_faceblur_get_unit_size (GstBaseTransform * btrans, GstCaps * caps, guint * size) { GstFaceblur *faceblur; GstStructure *structure; gboolean ret = FALSE; gint width, height; faceblur = GST_FACEBLUR (btrans); structure = gst_caps_get_structure (caps, 0); if (gst_structure_get_int (structure, "width", &width) && gst_structure_get_int (structure, "height", &height)) { *size = width * height * 3; ret = TRUE; GST_DEBUG_OBJECT (faceblur, "our frame size is %d bytes (%dx%d)", *size, width, height); } return ret; }
static GstFlowReturn gst_faceblur_transform (GstBaseTransform * base, GstBuffer * inbuf, GstBuffer * outbuf) { GstFaceblur *faceblur; guint8 *data; guint8 *out; guint size; int i,k,pos,j,R,G,B,a; IplImage *image; //double t; //t = (double)cvGetTickCount(); faceblur = GST_FACEBLUR (base); if (base->passthrough) goto done; data = GST_BUFFER_DATA (inbuf); out = GST_BUFFER_DATA (outbuf); size = GST_BUFFER_SIZE (inbuf); if (size != faceblur->size) goto wrong_size; image = cvCreateImage(cvSize(faceblur->width,faceblur->height), 8, 1 ); for(i=0;i<faceblur->height;i++) for(k=0;k<faceblur->width;k++) { pos = (i * faceblur->width + k) * 3; image->imageData[ pos/3 ] = (data[pos] + data[pos+1] + data[pos+2]) / 3; } CvSeq* faces = cvHaarDetectObjects( image, faceblur->cascade, faceblur->storage, 1.1, 2, 0 |CV_HAAR_FIND_BIGGEST_OBJECT //|CV_HAAR_DO_ROUGH_SEARCH //|CV_HAAR_DO_CANNY_PRUNING //|CV_HAAR_SCALE_IMAGE , cvSize(faceblur->face_width, faceblur->face_height) ); //t = (double)cvGetTickCount() - t; //g_print( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) ); memcpy(out,data,size); for( i = 0; i < (faces ? faces->total : 0); i++ ) { CvRect* r = (CvRect*)cvGetSeqElem( faces, i ); for(k=0;k < r->height;k++) for(j=0;j < r->width;j+=10) { R = 0; G = 0; B = 0; for(a=0;a<10;a++) { pos = ((k+r->y) * faceblur->width + j + r->x + a) * 3; R += out[pos]/10; G += out[pos+1]/10; B += out[pos+2]/10; } for(a=0;a<10;a++) { pos = ((k+r->y) * faceblur->width + j + r->x + a) * 3; out[pos]=R; out[pos+1]=G; out[pos+2]=B; } } } done: return GST_FLOW_OK; /* ERRORS */ wrong_size: { GST_ELEMENT_ERROR (faceblur, STREAM, FORMAT, (NULL), ("Invalid buffer size %d, expected %d", size, faceblur->size)); return GST_FLOW_ERROR; } }