mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-06 23:48:53 +00:00
facedetect: code maintenance
Update example to be useful. Draw colored ellipses instead of unicolor circles. Reflow code for more local variables. Improve parameter descriptions.
This commit is contained in:
parent
d746cd7d67
commit
94534a0b83
1 changed files with 39 additions and 33 deletions
|
@ -51,7 +51,7 @@
|
||||||
* <refsect2>
|
* <refsect2>
|
||||||
* <title>Example launch line</title>
|
* <title>Example launch line</title>
|
||||||
* |[
|
* |[
|
||||||
* gst-launch-0.10 videotestsrc ! decodebin ! ffmpegcolorspace ! facedetect ! ffmpegcolorspace ! xvimagesink
|
* gst-launch-0.10 autovideosrc ! decodebin2 ! colorspace ! facedetect ! colorspace ! xvimagesink
|
||||||
* ]|
|
* ]|
|
||||||
* </refsect2>
|
* </refsect2>
|
||||||
*/
|
*/
|
||||||
|
@ -225,7 +225,7 @@ gst_facedetect_class_init (GstfacedetectClass * klass)
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
g_object_class_install_property (gobject_class, PROP_SCALE_FACTOR,
|
g_object_class_install_property (gobject_class, PROP_SCALE_FACTOR,
|
||||||
g_param_spec_double ("scale-factor", "Scale factor",
|
g_param_spec_double ("scale-factor", "Scale factor",
|
||||||
"Factor by which the windows is scaled after each scan",
|
"Factor by which the frame is scaled after each object scan",
|
||||||
1.1, 10.0, DEFAULT_SCALE_FACTOR,
|
1.1, 10.0, DEFAULT_SCALE_FACTOR,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
g_object_class_install_property (gobject_class, PROP_MIN_NEIGHBORS,
|
g_object_class_install_property (gobject_class, PROP_MIN_NEIGHBORS,
|
||||||
|
@ -234,13 +234,13 @@ gst_facedetect_class_init (GstfacedetectClass * klass)
|
||||||
"an object", 0, G_MAXINT, DEFAULT_MIN_NEIGHBORS,
|
"an object", 0, G_MAXINT, DEFAULT_MIN_NEIGHBORS,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
g_object_class_install_property (gobject_class, PROP_MIN_SIZE_WIDTH,
|
g_object_class_install_property (gobject_class, PROP_MIN_SIZE_WIDTH,
|
||||||
g_param_spec_int ("min-size-width", "Minimum size width",
|
g_param_spec_int ("min-size-width", "Minimum face width",
|
||||||
"Minimum window width size", 0, G_MAXINT, DEFAULT_MIN_SIZE_WIDTH,
|
"Minimum area width to be recognized as a face", 0, G_MAXINT,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
DEFAULT_MIN_SIZE_WIDTH, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
g_object_class_install_property (gobject_class, PROP_MIN_SIZE_HEIGHT,
|
g_object_class_install_property (gobject_class, PROP_MIN_SIZE_HEIGHT,
|
||||||
g_param_spec_int ("min-size-height", "Minimum size height",
|
g_param_spec_int ("min-size-height", "Minimum face height",
|
||||||
"Minimum window height size", 0, G_MAXINT, DEFAULT_MIN_SIZE_HEIGHT,
|
"Minimum area height to be recognized as a face", 0, G_MAXINT,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
DEFAULT_MIN_SIZE_HEIGHT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize the new element
|
/* initialize the new element
|
||||||
|
@ -389,18 +389,16 @@ static GstFlowReturn
|
||||||
gst_facedetect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf,
|
gst_facedetect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf,
|
||||||
IplImage * img)
|
IplImage * img)
|
||||||
{
|
{
|
||||||
Gstfacedetect *filter;
|
Gstfacedetect *filter = GST_FACEDETECT (base);
|
||||||
CvSeq *faces;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
filter = GST_FACEDETECT (base);
|
|
||||||
|
|
||||||
cvCvtColor (img, filter->cvGray, CV_RGB2GRAY);
|
|
||||||
cvClearMemStorage (filter->cvStorage);
|
|
||||||
|
|
||||||
if (filter->cvCascade) {
|
if (filter->cvCascade) {
|
||||||
GstMessage *msg = NULL;
|
GstMessage *msg = NULL;
|
||||||
GValue facelist = { 0 };
|
GValue facelist = { 0 };
|
||||||
|
CvSeq *faces;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
cvCvtColor (img, filter->cvGray, CV_RGB2GRAY);
|
||||||
|
cvClearMemStorage (filter->cvStorage);
|
||||||
|
|
||||||
faces =
|
faces =
|
||||||
cvHaarDetectObjects (filter->cvGray, filter->cvCascade,
|
cvHaarDetectObjects (filter->cvGray, filter->cvCascade,
|
||||||
|
@ -419,36 +417,44 @@ gst_facedetect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf,
|
||||||
for (i = 0; i < (faces ? faces->total : 0); i++) {
|
for (i = 0; i < (faces ? faces->total : 0); i++) {
|
||||||
CvRect *r = (CvRect *) cvGetSeqElem (faces, i);
|
CvRect *r = (CvRect *) cvGetSeqElem (faces, i);
|
||||||
GValue value = { 0 };
|
GValue value = { 0 };
|
||||||
|
|
||||||
GstStructure *s = gst_structure_new ("face",
|
GstStructure *s = gst_structure_new ("face",
|
||||||
"x", G_TYPE_UINT, r->x,
|
"x", G_TYPE_UINT, r->x,
|
||||||
"y", G_TYPE_UINT, r->y,
|
"y", G_TYPE_UINT, r->y,
|
||||||
"width", G_TYPE_UINT, r->width,
|
"width", G_TYPE_UINT, r->width,
|
||||||
"height", G_TYPE_UINT, r->height, NULL);
|
"height", G_TYPE_UINT, r->height, NULL);
|
||||||
|
|
||||||
GstMessage *m = gst_message_new_element (GST_OBJECT (filter), s);
|
GST_LOG_OBJECT (filter, "%2d/%2d: x,y = %4u,%4u: w.h = %4u,%4u", i,
|
||||||
|
faces->total, r->x, r->y, r->width, r->height);
|
||||||
|
|
||||||
g_value_init (&value, GST_TYPE_STRUCTURE);
|
g_value_init (&value, GST_TYPE_STRUCTURE);
|
||||||
gst_value_set_structure (&value, s);
|
gst_value_set_structure (&value, s);
|
||||||
gst_value_list_append_value (&facelist, &value);
|
gst_value_list_append_value (&facelist, &value);
|
||||||
g_value_unset (&value);
|
g_value_unset (&value);
|
||||||
|
}
|
||||||
gst_element_post_message (GST_ELEMENT (filter), m);
|
if (filter->display) {
|
||||||
|
if (gst_buffer_is_writable (buf)) {
|
||||||
if (filter->display) {
|
/* draw colored circles for each face */
|
||||||
if (gst_buffer_is_writable (buf)) {
|
for (i = 0; i < (faces ? faces->total : 0); i++) {
|
||||||
|
CvRect *r = (CvRect *) cvGetSeqElem (faces, i);
|
||||||
CvPoint center;
|
CvPoint center;
|
||||||
int radius;
|
CvSize axes;
|
||||||
center.x = cvRound ((r->x + r->width * 0.5));
|
gdouble w = r->width * 0.5;
|
||||||
center.y = cvRound ((r->y + r->height * 0.5));
|
gdouble h = r->height * 0.6; /* tweak for face form */
|
||||||
radius = cvRound ((r->width + r->height) * 0.25);
|
gint cb = 255 - ((i & 3) << 7);
|
||||||
cvCircle (img, center, radius, CV_RGB (255, 32, 32), 3, 8, 0);
|
gint cg = 255 - ((i & 12) << 5);
|
||||||
} else {
|
gint cr = 255 - ((i & 48) << 3);
|
||||||
GST_DEBUG_OBJECT (filter, "Buffer is not writable, not drawing "
|
|
||||||
"circles for faces");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
center.x = cvRound ((r->x + w));
|
||||||
|
center.y = cvRound ((r->y + h));
|
||||||
|
axes.width = w;
|
||||||
|
axes.height = h;
|
||||||
|
cvEllipse (img, center, axes, 0.0, 0.0, 360.0, CV_RGB (cr, cg, cb),
|
||||||
|
3, 8, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GST_LOG_OBJECT (filter, "Buffer is not writable, not drawing "
|
||||||
|
"circles for faces");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg) {
|
if (msg) {
|
||||||
|
|
Loading…
Reference in a new issue