mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
grabcut: Add GrabCut segmentation element
https://bugzilla.gnome.org/show_bug.cgi?id=702722
This commit is contained in:
parent
ff495342f2
commit
7c2177b19f
5 changed files with 566 additions and 0 deletions
|
@ -22,6 +22,7 @@ libgstopencv_la_SOURCES = gstopencv.c \
|
|||
gstskindetect.c \
|
||||
gstretinex.c \
|
||||
gstsegmentation.cpp \
|
||||
gstgrabcut.cpp \
|
||||
motioncells_wrapper.cpp \
|
||||
MotionCells.cpp
|
||||
|
||||
|
@ -63,6 +64,7 @@ noinst_HEADERS = gstopencvvideofilter.h gstopencvutils.h \
|
|||
gstskindetect.h \
|
||||
gstretinex.h \
|
||||
gstsegmentation.h \
|
||||
gstgrabcut.h \
|
||||
gstmotioncells.h \
|
||||
motioncells_wrapper.h \
|
||||
MotionCells.h
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/gstvideometa.h>
|
||||
|
||||
#include "gstopencvutils.h"
|
||||
#include "gstfacedetect.h"
|
||||
|
@ -669,6 +670,8 @@ gst_face_detect_transform_ip (GstOpencvVideoFilter * base, GstBuffer * buf,
|
|||
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);
|
||||
}
|
||||
|
||||
gst_structure_set_value ((GstStructure *) gst_message_get_structure (msg),
|
||||
|
|
454
ext/opencv/gstgrabcut.cpp
Normal file
454
ext/opencv/gstgrabcut.cpp
Normal file
|
@ -0,0 +1,454 @@
|
|||
/*
|
||||
* GStreamer
|
||||
* Copyright (C) 2013 Miguel Casas-Sanchez <miguelecasassanchez@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* GNU Lesser General Public License Version 2.1 (the "LGPL"), in
|
||||
* which case the following provisions apply instead of the ones
|
||||
* mentioned above:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:element-grabcut
|
||||
*
|
||||
*
|
||||
* This element is a wrapper around OpenCV grabcut implementation. GrabCut is an
|
||||
* image segmentation method based on graph cuts technique. It can be seen as a
|
||||
* way of fine-grain segmenting the image from some FG and BG "seed" areas. The
|
||||
* OpenCV implementation follows the article [1].
|
||||
* The "seed" areas are taken in this element from either an input bounding box
|
||||
* coming from a face detection, or from alpha channel values. The input box is
|
||||
* taken from a "face" event such as the one generated from the 'facedetect'
|
||||
* element. The Alpha channel values should be one of the following (cv.hpp):
|
||||
* enum{
|
||||
* GC_BGD = 0, //!< background
|
||||
* GC_FGD = 1, //!< foreground
|
||||
* GC_PR_BGD = 2, //!< most probably background
|
||||
* GC_PR_FGD = 3 //!< most probably foreground
|
||||
* };
|
||||
* with values over GC_PR_FGD interpreted as GC_PR_FGD. IN CASE OF no alpha mask
|
||||
* input (all 0's or all 1's), the 'GstOpenCvFaceDetect-face' downstream event
|
||||
* is used to create a bbox of PR_FG elements. If both foreground alpha
|
||||
* is not specified and there is no face detection, nothing is done.
|
||||
*
|
||||
* [1] C. Rother, V. Kolmogorov, and A. Blake, "GrabCut: Interactive foreground
|
||||
* extraction using iterated graph cuts, ACM Trans. Graph., vol. 23, pp. 309–314,
|
||||
* 2004.
|
||||
*
|
||||
* <refsect2>
|
||||
* <title>Example launch line</title>
|
||||
* |[
|
||||
* gst-launch-1.0 --gst-debug=grabcut=4 v4l2src device=/dev/video0 ! videoconvert ! grabcut ! videoconvert ! video/x-raw,width=320,height=240 ! ximagesink
|
||||
* ]|
|
||||
* Another example launch line
|
||||
* |[
|
||||
* gst-launch-1.0 --gst-debug=grabcut=4 v4l2src device=/dev/video0 ! videoconvert ! facedetect display=0 ! videoconvert ! grabcut test-mode=true ! videoconvert ! video/x-raw,width=320,height=240 ! ximagesink
|
||||
* ]|
|
||||
* </refsect2>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include "gstgrabcut.h"
|
||||
extern "C"
|
||||
{
|
||||
#include <gst/video/gstvideometa.h>
|
||||
}
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_grabcut_debug);
|
||||
#define GST_CAT_DEFAULT gst_grabcut_debug
|
||||
|
||||
/* Filter signals and args */
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_TEST_MODE,
|
||||
PROP_SCALE
|
||||
};
|
||||
|
||||
#define DEFAULT_TEST_MODE FALSE
|
||||
#define DEFAULT_SCALE 1.6
|
||||
|
||||
G_DEFINE_TYPE (GstGrabcut, gst_grabcut, GST_TYPE_VIDEO_FILTER);
|
||||
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGBA")));
|
||||
|
||||
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGBA")));
|
||||
|
||||
|
||||
static void gst_grabcut_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_grabcut_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static GstFlowReturn gst_grabcut_transform_ip (GstVideoFilter * btrans,
|
||||
GstVideoFrame * frame);
|
||||
static gboolean gst_grabcut_set_info (GstVideoFilter * filter,
|
||||
GstCaps * incaps, GstVideoInfo * in_info,
|
||||
GstCaps * outcaps, GstVideoInfo * out_info);
|
||||
|
||||
static void gst_grabcut_release_all_pointers (GstGrabcut * filter);
|
||||
|
||||
static gboolean gst_grabcut_stop (GstBaseTransform * basesrc);
|
||||
static void compose_matrix_from_image (CvMat * output, IplImage * input);
|
||||
|
||||
static int initialise_grabcut (struct grabcut_params *GC, IplImage * image_c,
|
||||
CvMat * mask_c);
|
||||
static int run_grabcut_iteration (struct grabcut_params *GC,
|
||||
IplImage * image_c, CvMat * mask_c, CvRect * bbox);
|
||||
static int run_grabcut_iteration2 (struct grabcut_params *GC,
|
||||
IplImage * image_c, CvMat * mask_c, CvRect * bbox);
|
||||
static int finalise_grabcut (struct grabcut_params *GC);
|
||||
|
||||
/* initialize the grabcut's class */
|
||||
static void
|
||||
gst_grabcut_class_init (GstGrabcutClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
GstBaseTransformClass *btrans_class = (GstBaseTransformClass *) klass;
|
||||
GstVideoFilterClass *video_class = (GstVideoFilterClass *) klass;
|
||||
|
||||
gobject_class->set_property = gst_grabcut_set_property;
|
||||
gobject_class->get_property = gst_grabcut_get_property;
|
||||
|
||||
btrans_class->stop = gst_grabcut_stop;
|
||||
btrans_class->passthrough_on_same_caps = TRUE;
|
||||
|
||||
video_class->transform_frame_ip = gst_grabcut_transform_ip;
|
||||
video_class->set_info = gst_grabcut_set_info;
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_TEST_MODE,
|
||||
g_param_spec_boolean ("test-mode", "test-mode",
|
||||
"If true, the output RGB is overwritten with the segmented foreground. Alpha channel same as normal case ",
|
||||
DEFAULT_TEST_MODE, (GParamFlags)
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_SCALE,
|
||||
g_param_spec_float ("scale", "scale",
|
||||
"Grow factor for the face bounding box, if present", 1.0,
|
||||
4.0, DEFAULT_SCALE,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||
|
||||
gst_element_class_set_static_metadata (element_class,
|
||||
"Grabcut-based image FG/BG segmentation", "Filter/Effect/Video",
|
||||
"Runs Grabcut algorithm on input alpha. Values: BG=0, FG=1, PR_BG=2, PR_FGD=3; \
|
||||
NOTE: larger values of alpha (notably 255) are interpreted as PR_FGD too. \n\
|
||||
IN CASE OF no alpha mask input (all 0's or all 1's), the 'face' \
|
||||
downstream event is used to create a bbox of PR_FG elements.\n\
|
||||
IF nothing is present, then nothing is done.", "Miguel Casas-Sanchez <miguelecasassanchez@gmail.com>");
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&src_factory));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&sink_factory));
|
||||
}
|
||||
|
||||
|
||||
/* initialize the new element
|
||||
* instantiate pads and add them to element
|
||||
* set pad calback functions
|
||||
* initialize instance structure
|
||||
*/
|
||||
static void
|
||||
gst_grabcut_init (GstGrabcut * filter)
|
||||
{
|
||||
filter->test_mode = DEFAULT_TEST_MODE;
|
||||
filter->scale = DEFAULT_SCALE;
|
||||
gst_base_transform_set_in_place (GST_BASE_TRANSFORM (filter), FALSE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gst_grabcut_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstGrabcut *grabcut = GST_GRABCUT (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_TEST_MODE:
|
||||
grabcut->test_mode = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_SCALE:
|
||||
grabcut->scale = g_value_get_float (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_grabcut_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstGrabcut *filter = GST_GRABCUT (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_TEST_MODE:
|
||||
g_value_set_boolean (value, filter->test_mode);
|
||||
break;
|
||||
case PROP_SCALE:
|
||||
g_value_set_float (value, filter->scale);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* GstElement vmethod implementations */
|
||||
/* this function handles the link with other elements */
|
||||
static gboolean
|
||||
gst_grabcut_set_info (GstVideoFilter * filter,
|
||||
GstCaps * incaps, GstVideoInfo * in_info,
|
||||
GstCaps * outcaps, GstVideoInfo * out_info)
|
||||
{
|
||||
GstGrabcut *grabcut = GST_GRABCUT (filter);
|
||||
CvSize size;
|
||||
|
||||
size = cvSize (in_info->width, in_info->height);
|
||||
/* If cvRGBA is already allocated, it means there's a cap modification,
|
||||
so release first all the images. */
|
||||
if (NULL != grabcut->cvRGBAin)
|
||||
gst_grabcut_release_all_pointers (grabcut);
|
||||
|
||||
grabcut->cvRGBAin = cvCreateImageHeader (size, IPL_DEPTH_8U, 4);
|
||||
grabcut->cvRGBin = cvCreateImage (size, IPL_DEPTH_8U, 3);
|
||||
|
||||
grabcut->cvA = cvCreateImage (size, IPL_DEPTH_8U, 1);
|
||||
grabcut->cvB = cvCreateImage (size, IPL_DEPTH_8U, 1);
|
||||
grabcut->cvC = cvCreateImage (size, IPL_DEPTH_8U, 1);
|
||||
grabcut->cvD = cvCreateImage (size, IPL_DEPTH_8U, 1);
|
||||
|
||||
grabcut->grabcut_mask = cvCreateMat (size.height, size.width, CV_8UC1);
|
||||
cvZero (grabcut->grabcut_mask);
|
||||
initialise_grabcut (&(grabcut->GC), grabcut->cvRGBin, grabcut->grabcut_mask);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
static gboolean
|
||||
gst_grabcut_stop (GstBaseTransform * basesrc)
|
||||
{
|
||||
GstGrabcut *filter = GST_GRABCUT (basesrc);
|
||||
|
||||
if (filter->cvRGBAin != NULL)
|
||||
gst_grabcut_release_all_pointers (filter);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_grabcut_release_all_pointers (GstGrabcut * filter)
|
||||
{
|
||||
cvReleaseImage (&filter->cvRGBAin);
|
||||
cvReleaseImage (&filter->cvRGBin);
|
||||
|
||||
cvReleaseImage (&filter->cvA);
|
||||
cvReleaseImage (&filter->cvB);
|
||||
cvReleaseImage (&filter->cvC);
|
||||
cvReleaseImage (&filter->cvD);
|
||||
|
||||
finalise_grabcut (&(filter->GC));
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_grabcut_transform_ip (GstVideoFilter * btrans, GstVideoFrame * frame)
|
||||
{
|
||||
GstGrabcut *gc = GST_GRABCUT (btrans);
|
||||
gint alphapixels;
|
||||
|
||||
GstVideoRegionOfInterestMeta *meta;
|
||||
meta = gst_buffer_get_video_region_of_interest_meta (frame->buffer);
|
||||
if (meta) {
|
||||
gc->facepos.x = (meta->x) - ((gc->scale - 1) * meta->w / 2);
|
||||
gc->facepos.y = (meta->y) - ((gc->scale - 1) * meta->h / 2);
|
||||
gc->facepos.width = meta->w * gc->scale * 0.9;
|
||||
gc->facepos.height = meta->h * gc->scale * 1.1;
|
||||
} else {
|
||||
memset (&(gc->facepos), 0, sizeof (gc->facepos));
|
||||
}
|
||||
|
||||
gc->cvRGBAin->imageData = (char *) GST_VIDEO_FRAME_COMP_DATA (frame, 0);
|
||||
|
||||
/* normally input should be RGBA */
|
||||
cvSplit (gc->cvRGBAin, gc->cvA, gc->cvB, gc->cvC, gc->cvD);
|
||||
cvCvtColor (gc->cvRGBAin, gc->cvRGBin, CV_BGRA2BGR);
|
||||
compose_matrix_from_image (gc->grabcut_mask, gc->cvD);
|
||||
|
||||
/* Pass cvD to grabcut_mask for the graphcut stuff but that only if
|
||||
really there is something in the mask! otherwise -->input bbox is
|
||||
what we use */
|
||||
alphapixels = cvCountNonZero (gc->cvD);
|
||||
if ((0 < alphapixels) && (alphapixels < (gc->width * gc->height))) {
|
||||
GST_INFO ("running on mask");
|
||||
run_grabcut_iteration (&(gc->GC), gc->cvRGBin, gc->grabcut_mask, NULL);
|
||||
} else {
|
||||
|
||||
if ((abs (gc->facepos.width) > 2) && (abs (gc->facepos.height) > 2)) {
|
||||
GST_INFO ("running on bbox (%d,%d),(%d,%d)", gc->facepos.x, gc->facepos.y,
|
||||
gc->facepos.width, gc->facepos.height);
|
||||
run_grabcut_iteration2 (&(gc->GC), gc->cvRGBin, gc->grabcut_mask,
|
||||
&(gc->facepos));
|
||||
} else {
|
||||
GST_WARNING ("No face info present, skipping frame.");
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* if we want to display, just overwrite the output */
|
||||
if (gc->test_mode) {
|
||||
/* get only FG, PR_FG */
|
||||
cvAndS (gc->grabcut_mask, cvRealScalar (1), gc->grabcut_mask, NULL);
|
||||
/* (saturated) FG, PR_FG --> 255 */
|
||||
cvConvertScale (gc->grabcut_mask, gc->grabcut_mask, 255.0, 0.0);
|
||||
|
||||
cvAnd (gc->grabcut_mask, gc->cvA, gc->cvA, NULL);
|
||||
cvAnd (gc->grabcut_mask, gc->cvB, gc->cvB, NULL);
|
||||
cvAnd (gc->grabcut_mask, gc->cvC, gc->cvC, NULL);
|
||||
}
|
||||
|
||||
cvMerge (gc->cvA, gc->cvB, gc->cvC, gc->cvD, gc->cvRGBAin);
|
||||
|
||||
if (gc->test_mode) {
|
||||
cvRectangle (gc->cvRGBAin,
|
||||
cvPoint (gc->facepos.x, gc->facepos.y),
|
||||
cvPoint (gc->facepos.x + gc->facepos.width,
|
||||
gc->facepos.y + gc->facepos.height), CV_RGB (255, 0, 255), 1, 8, 0);
|
||||
}
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
/* entry point to initialize the plug-in
|
||||
* initialize the plug-in itself
|
||||
* register the element factories and other features
|
||||
*/
|
||||
gboolean
|
||||
gst_grabcut_plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
/* debug category for fltering log messages
|
||||
*
|
||||
*/
|
||||
GST_DEBUG_CATEGORY_INIT (gst_grabcut_debug, "grabcut",
|
||||
0,
|
||||
"Grabcut image segmentation on either input alpha or input bounding box");
|
||||
|
||||
return gst_element_register (plugin, "grabcut", GST_RANK_NONE,
|
||||
GST_TYPE_GRABCUT);
|
||||
}
|
||||
|
||||
void
|
||||
compose_matrix_from_image (CvMat * output, IplImage * input)
|
||||
{
|
||||
|
||||
int x, y;
|
||||
for (x = 0; x < output->cols; x++) {
|
||||
for (y = 0; y < output->rows; y++) {
|
||||
CV_MAT_ELEM (*output, uchar, y, x) =
|
||||
(cvGetReal2D (input, y, x) <= cv::GC_PR_FGD) ? cvGetReal2D (input, y,
|
||||
x) : cv::GC_PR_FGD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
initialise_grabcut (struct grabcut_params *GC, IplImage * image_c,
|
||||
CvMat * mask_c)
|
||||
{
|
||||
GC->image = (void *) new cv::Mat (image_c, false); /* "true" refers to copydata */
|
||||
GC->mask = (void *) new cv::Mat (mask_c, false);
|
||||
GC->bgdModel = (void *) new cv::Mat (); /* "true" refers to copydata */
|
||||
GC->fgdModel = (void *) new cv::Mat ();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
run_grabcut_iteration (struct grabcut_params *GC, IplImage * image_c,
|
||||
CvMat * mask_c, CvRect * bbox)
|
||||
{
|
||||
((cv::Mat *) GC->image)->data = (uchar *) image_c->imageData;
|
||||
((cv::Mat *) GC->mask)->data = mask_c->data.ptr;
|
||||
|
||||
if (cvCountNonZero (mask_c))
|
||||
grabCut (*((cv::Mat *) GC->image), *((cv::Mat *) GC->mask), cv::Rect (),
|
||||
*((cv::Mat *) GC->bgdModel), *((cv::Mat *) GC->fgdModel), 1,
|
||||
cv::GC_INIT_WITH_MASK);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
run_grabcut_iteration2 (struct grabcut_params *GC, IplImage * image_c,
|
||||
CvMat * mask_c, CvRect * bbox)
|
||||
{
|
||||
((cv::Mat *) GC->image)->data = (uchar *) image_c->imageData;
|
||||
((cv::Mat *) GC->mask)->data = mask_c->data.ptr;
|
||||
|
||||
grabCut (*((cv::Mat *) GC->image), *((cv::Mat *) GC->mask), *(bbox),
|
||||
*((cv::Mat *) GC->bgdModel), *((cv::Mat *) GC->fgdModel), 1,
|
||||
cv::GC_INIT_WITH_RECT);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
finalise_grabcut (struct grabcut_params *GC)
|
||||
{
|
||||
delete ((cv::Mat *) GC->image);
|
||||
delete ((cv::Mat *) GC->mask);
|
||||
delete ((cv::Mat *) GC->bgdModel);
|
||||
delete ((cv::Mat *) GC->fgdModel);
|
||||
|
||||
return (0);
|
||||
}
|
103
ext/opencv/gstgrabcut.h
Normal file
103
ext/opencv/gstgrabcut.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* GStreamer
|
||||
* Copyright (C) 2013 Miguel Casas-Sanchez <miguelecasassanchez@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* GNU Lesser General Public License Version 2.1 (the "LGPL"), in
|
||||
* which case the following provisions apply instead of the ones
|
||||
* mentioned above:
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_GRABCUT_H__
|
||||
#define __GST_GRABCUT_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/video/gstvideofilter.h>
|
||||
|
||||
#include <cv.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
/* #defines don't like whitespacey bits */
|
||||
#define GST_TYPE_GRABCUT \
|
||||
(gst_grabcut_get_type())
|
||||
#define GST_GRABCUT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GRABCUT,GstGrabcut))
|
||||
#define GST_GRABCUT_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GRABCUT,GstGrabcutClass))
|
||||
#define GST_IS_GRABCUT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GRABCUT))
|
||||
#define GST_IS_GRABCUT_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GRABCUT))
|
||||
typedef struct _GstGrabcut GstGrabcut;
|
||||
typedef struct _GstGrabcutClass GstGrabcutClass;
|
||||
|
||||
|
||||
struct grabcut_params
|
||||
{
|
||||
void *bgdModel;
|
||||
void *fgdModel;
|
||||
void *image;
|
||||
void *mask;
|
||||
};
|
||||
|
||||
struct _GstGrabcut
|
||||
{
|
||||
GstVideoFilter element;
|
||||
gint width, height;
|
||||
gboolean test_mode;
|
||||
gdouble scale; // grow multiplier to apply to input bbox
|
||||
|
||||
IplImage *cvRGBAin, *cvRGBin;
|
||||
IplImage *cvA, *cvB, *cvC, *cvD;
|
||||
|
||||
|
||||
CvMat *grabcut_mask; // mask created by graphcut
|
||||
struct grabcut_params GC;
|
||||
CvRect facepos;
|
||||
};
|
||||
|
||||
struct _GstGrabcutClass
|
||||
{
|
||||
GstVideoFilterClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_grabcut_get_type (void);
|
||||
|
||||
gboolean gst_grabcut_plugin_init (GstPlugin * plugin);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* __GST_GRABCUT_H__ */
|
|
@ -40,6 +40,7 @@
|
|||
#include "gstskindetect.h"
|
||||
#include "gstretinex.h"
|
||||
#include "gstsegmentation.h"
|
||||
#include "gstgrabcut.h"
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
|
@ -95,6 +96,9 @@ plugin_init (GstPlugin * plugin)
|
|||
if (!gst_segmentation_plugin_init (plugin))
|
||||
return FALSE;
|
||||
|
||||
if (!gst_grabcut_plugin_init (plugin))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue