From 36e83661ec1ae62fcc6aa3ab557185ca9b3afbd2 Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Mon, 25 Jan 2016 11:43:59 +0000 Subject: [PATCH] opencv: fix cvlaplace cvlaplace was also affected by the silent change in OpenCV API, same as cvsobel. It hasn't been working for a while. It would return a plain black image. This commit updates the usage of cvLaplace by using cvCvtColor to create the grayscale intermediate image to process. This also means there is no need anymore to use GstBaseTransform's transform_caps, since the pads are RGB. --- ext/opencv/gstcvlaplace.cpp | 170 +++++++++++++++--------------------- ext/opencv/gstcvlaplace.h | 3 + 2 files changed, 72 insertions(+), 101 deletions(-) diff --git a/ext/opencv/gstcvlaplace.cpp b/ext/opencv/gstcvlaplace.cpp index 04cd575ae5..1081a575de 100644 --- a/ext/opencv/gstcvlaplace.cpp +++ b/ext/opencv/gstcvlaplace.cpp @@ -67,22 +67,14 @@ GST_DEBUG_CATEGORY_STATIC (gst_cv_laplace_debug); static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("GRAY8")) + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB")) ); -#if G_BYTE_ORDER == G_BIG_ENDIAN static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("GRAY16_BE")) + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB")) ); -#else -static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("GRAY16_LE")) - ); -#endif /* Filter signals and args */ enum @@ -109,8 +101,8 @@ static void gst_cv_laplace_set_property (GObject * object, guint prop_id, static void gst_cv_laplace_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static GstCaps *gst_cv_laplace_transform_caps (GstBaseTransform * trans, - GstPadDirection dir, GstCaps * caps, GstCaps * filter); +static gboolean gst_cv_laplace_handle_sink_event (GstPad * pad, + GstObject * parent, GstEvent * event); static GstFlowReturn gst_cv_laplace_transform (GstOpencvVideoFilter * filter, GstBuffer * buf, IplImage * img, GstBuffer * outbuf, IplImage * outimg); @@ -125,8 +117,12 @@ gst_cv_laplace_finalize (GObject * obj) { GstCvLaplace *filter = GST_CV_LAPLACE (obj); - if (filter->intermediary_img) + if (filter->intermediary_img) { cvReleaseImage (&filter->intermediary_img); + cvReleaseImage (&filter->cvGray); + cvReleaseImage (&filter->Laplace); + cvReleaseImage (&filter->CLaplace); + } G_OBJECT_CLASS (gst_cv_laplace_parent_class)->finalize (obj); } @@ -136,20 +132,16 @@ static void gst_cv_laplace_class_init (GstCvLaplaceClass * klass) { GObjectClass *gobject_class; - GstBaseTransformClass *gstbasetransform_class; GstOpencvVideoFilterClass *gstopencvbasefilter_class; GstElementClass *element_class = GST_ELEMENT_CLASS (klass); gobject_class = (GObjectClass *) klass; - gstbasetransform_class = (GstBaseTransformClass *) klass; gstopencvbasefilter_class = (GstOpencvVideoFilterClass *) klass; gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_cv_laplace_finalize); gobject_class->set_property = gst_cv_laplace_set_property; gobject_class->get_property = gst_cv_laplace_get_property; - gstbasetransform_class->transform_caps = gst_cv_laplace_transform_caps; - gstopencvbasefilter_class->cv_trans_func = gst_cv_laplace_transform; gstopencvbasefilter_class->cv_set_caps = gst_cv_laplace_cv_set_caps; @@ -181,6 +173,9 @@ gst_cv_laplace_class_init (GstCvLaplaceClass * klass) static void gst_cv_laplace_init (GstCvLaplace * filter) { + gst_pad_set_event_function (GST_BASE_TRANSFORM_SINK_PAD (filter), + GST_DEBUG_FUNCPTR (gst_cv_laplace_handle_sink_event)); + filter->aperture_size = DEFAULT_APERTURE_SIZE; filter->scale = DEFAULT_SCALE_FACTOR; filter->shift = DEFAULT_SHIFT; @@ -195,97 +190,17 @@ gst_cv_laplace_cv_set_caps (GstOpencvVideoFilter * trans, gint in_width, gint out_height, gint out_depth, gint out_channels) { GstCvLaplace *filter = GST_CV_LAPLACE (trans); - gint intermediary_depth; - /* cvLaplace needs an signed output, so we create our intermediary step - * image here */ - switch (out_depth) { - case IPL_DEPTH_16U: - intermediary_depth = IPL_DEPTH_16S; - break; - default: - GST_WARNING_OBJECT (filter, "Unsupported output depth %d", out_depth); - return FALSE; - } if (filter->intermediary_img) { cvReleaseImage (&filter->intermediary_img); } - filter->intermediary_img = cvCreateImage (cvSize (out_width, out_height), - intermediary_depth, out_channels); + filter->intermediary_img = + cvCreateImage (cvSize (out_width, out_height), IPL_DEPTH_16S, 1); return TRUE; } -static GstCaps * -gst_cv_laplace_transform_caps (GstBaseTransform * trans, GstPadDirection dir, - GstCaps * caps, GstCaps * filter) -{ - GstCaps *to, *ret; - GstCaps *templ; - GstStructure *structure; - GstPad *other; - guint i; - - to = gst_caps_new_empty (); - - for (i = 0; i < gst_caps_get_size (caps); i++) { - const GValue *v; - GValue list = { 0, }; - GValue val = { 0, }; - - structure = gst_structure_copy (gst_caps_get_structure (caps, i)); - - g_value_init (&list, GST_TYPE_LIST); - - g_value_init (&val, G_TYPE_STRING); - g_value_set_string (&val, "GRAY8"); - gst_value_list_append_value (&list, &val); - g_value_unset (&val); - - g_value_init (&val, G_TYPE_STRING); -#if G_BYTE_ORDER == G_BIG_ENDIAN - g_value_set_string (&val, "GRAY16_BE"); -#else - g_value_set_string (&val, "GRAY16_LE"); -#endif - gst_value_list_append_value (&list, &val); - g_value_unset (&val); - - v = gst_structure_get_value (structure, "format"); - - gst_value_list_merge (&val, v, &list); - gst_structure_set_value (structure, "format", &val); - g_value_unset (&val); - g_value_unset (&list); - - gst_structure_remove_field (structure, "colorimetry"); - gst_structure_remove_field (structure, "chroma-site"); - - gst_caps_append_structure (to, structure); - - } - - /* filter against set allowed caps on the pad */ - other = (dir == GST_PAD_SINK) ? trans->srcpad : trans->sinkpad; - templ = gst_pad_get_pad_template_caps (other); - ret = gst_caps_intersect (to, templ); - gst_caps_unref (to); - gst_caps_unref (templ); - - if (ret && filter) { - GstCaps *intersection; - - intersection = - gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST); - gst_caps_unref (ret); - ret = intersection; - } - - return ret; - -} - static void gst_cv_laplace_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -336,17 +251,70 @@ gst_cv_laplace_get_property (GObject * object, guint prop_id, } } +static gboolean +gst_cv_laplace_handle_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event) +{ + GstCvLaplace *filter; + gint width, height; + GstStructure *structure; + gboolean res = TRUE; + + filter = GST_CV_LAPLACE (parent); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CAPS: + { + GstCaps *caps; + gst_event_parse_caps (event, &caps); + + structure = gst_caps_get_structure (caps, 0); + gst_structure_get_int (structure, "width", &width); + gst_structure_get_int (structure, "height", &height); + + if (filter->intermediary_img != NULL) { + cvReleaseImage (&filter->intermediary_img); + cvReleaseImage (&filter->CLaplace); + cvReleaseImage (&filter->cvGray); + cvReleaseImage (&filter->Laplace); + } + + filter->CLaplace = + cvCreateImage (cvSize (width, height), IPL_DEPTH_8U, 3); + filter->intermediary_img = + cvCreateImage (cvSize (width, height), IPL_DEPTH_16S, 1); + filter->cvGray = cvCreateImage (cvSize (width, height), IPL_DEPTH_8U, 1); + filter->Laplace = cvCreateImage (cvSize (width, height), IPL_DEPTH_8U, 1); + break; + } + default: + break; + } + + res = gst_pad_event_default (pad, parent, event); + + return res; +} + static GstFlowReturn gst_cv_laplace_transform (GstOpencvVideoFilter * base, GstBuffer * buf, IplImage * img, GstBuffer * outbuf, IplImage * outimg) { GstCvLaplace *filter = GST_CV_LAPLACE (base); + GstMapInfo out_info; g_assert (filter->intermediary_img); - cvLaplace (img, filter->intermediary_img, filter->aperture_size); - cvConvertScale (filter->intermediary_img, outimg, filter->scale, + cvCvtColor (img, filter->cvGray, CV_RGB2GRAY); + cvLaplace (filter->cvGray, filter->intermediary_img, filter->aperture_size); + cvConvertScale (filter->intermediary_img, filter->Laplace, filter->scale, filter->shift); + cvZero (filter->CLaplace); + cvCvtColor (filter->Laplace, filter->CLaplace, CV_GRAY2RGB); + + gst_buffer_map (outbuf, &out_info, GST_MAP_WRITE); + memcpy (out_info.data, filter->CLaplace->imageData, + gst_buffer_get_size (outbuf)); return GST_FLOW_OK; } diff --git a/ext/opencv/gstcvlaplace.h b/ext/opencv/gstcvlaplace.h index 7ac91720a6..8590964331 100644 --- a/ext/opencv/gstcvlaplace.h +++ b/ext/opencv/gstcvlaplace.h @@ -72,6 +72,9 @@ struct _GstCvLaplace gdouble shift; IplImage *intermediary_img; + IplImage *cvGray; + IplImage *Laplace; + IplImage *CLaplace; }; struct _GstCvLaplaceClass