mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-04 01:32:42 +00:00
retinex: Port to GstOpencvVideoFilter base class
This allow reducing slightly the code. It also fixes a bug caused by in-place buffer being mapped and never unmapped.
This commit is contained in:
parent
54aaf84e08
commit
ee940b130f
2 changed files with 37 additions and 50 deletions
|
@ -108,7 +108,7 @@ gst_retinex_method_get_type (void)
|
||||||
return etype;
|
return etype;
|
||||||
}
|
}
|
||||||
|
|
||||||
G_DEFINE_TYPE (GstRetinex, gst_retinex, GST_TYPE_VIDEO_FILTER);
|
G_DEFINE_TYPE (GstRetinex, gst_retinex, GST_TYPE_OPENCV_VIDEO_FILTER);
|
||||||
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
|
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
GST_PAD_SINK,
|
GST_PAD_SINK,
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
|
@ -125,10 +125,11 @@ static void gst_retinex_set_property (GObject * object, guint prop_id,
|
||||||
static void gst_retinex_get_property (GObject * object, guint prop_id,
|
static void gst_retinex_get_property (GObject * object, guint prop_id,
|
||||||
GValue * value, GParamSpec * pspec);
|
GValue * value, GParamSpec * pspec);
|
||||||
|
|
||||||
static GstFlowReturn gst_retinex_transform_ip (GstBaseTransform * btrans,
|
static GstFlowReturn gst_retinex_transform_ip (GstOpencvVideoFilter * filter,
|
||||||
GstBuffer * buf);
|
GstBuffer * buff, IplImage * img);
|
||||||
static gboolean gst_retinex_set_caps (GstBaseTransform * btrans,
|
static gboolean gst_retinex_set_caps (GstOpencvVideoFilter* btrans,
|
||||||
GstCaps * incaps, GstCaps * outcaps);
|
gint in_width, gint in_height, gint in_depth, gint in_channels,
|
||||||
|
gint out_width, gint out_height, gint out_depth, gint out_channels);
|
||||||
|
|
||||||
static void gst_retinex_release_all_images (GstRetinex * filter);
|
static void gst_retinex_release_all_images (GstRetinex * filter);
|
||||||
|
|
||||||
|
@ -141,12 +142,15 @@ gst_retinex_class_init (GstRetinexClass * klass)
|
||||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
GstBaseTransformClass *btrans_class = (GstBaseTransformClass *) klass;
|
GstBaseTransformClass *btrans_class = (GstBaseTransformClass *) klass;
|
||||||
|
GstOpencvVideoFilterClass *cvbasefilter_class =
|
||||||
|
(GstOpencvVideoFilterClass *) klass;
|
||||||
|
|
||||||
gobject_class->set_property = gst_retinex_set_property;
|
gobject_class->set_property = gst_retinex_set_property;
|
||||||
gobject_class->get_property = gst_retinex_get_property;
|
gobject_class->get_property = gst_retinex_get_property;
|
||||||
|
|
||||||
btrans_class->transform_ip = gst_retinex_transform_ip;
|
cvbasefilter_class->cv_trans_ip_func = gst_retinex_transform_ip;
|
||||||
btrans_class->set_caps = gst_retinex_set_caps;
|
cvbasefilter_class->cv_set_caps = gst_retinex_set_caps;
|
||||||
|
|
||||||
btrans_class->stop = gst_retinex_stop;
|
btrans_class->stop = gst_retinex_stop;
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_METHOD,
|
g_object_class_install_property (gobject_class, PROP_METHOD,
|
||||||
|
@ -225,42 +229,33 @@ gst_retinex_get_property (GObject * object, guint prop_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GstElement vmethod implementations */
|
|
||||||
/* this function handles the link with other elements */
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_retinex_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
|
gst_retinex_set_caps (GstOpencvVideoFilter * filter, gint in_width, gint in_height,
|
||||||
GstCaps * outcaps)
|
gint in_depth, gint in_channels, gint out_width, gint out_height,
|
||||||
|
gint out_depth, gint out_channels)
|
||||||
{
|
{
|
||||||
GstRetinex *retinex = GST_RETINEX (btrans);
|
GstRetinex *retinex = GST_RETINEX (filter);
|
||||||
CvSize size;
|
CvSize size;
|
||||||
GstVideoInfo info;
|
|
||||||
gst_video_info_from_caps (&info, incaps);
|
|
||||||
|
|
||||||
size = cvSize (info.width, info.height);
|
size = cvSize (in_width, in_height);
|
||||||
|
|
||||||
/* If cvRGB is already allocated, it means there's a cap modification,
|
if (retinex->cvA)
|
||||||
so release first all the images. */
|
|
||||||
if (NULL != retinex->cvRGBin)
|
|
||||||
gst_retinex_release_all_images (retinex);
|
gst_retinex_release_all_images (retinex);
|
||||||
|
|
||||||
retinex->cvRGBin = cvCreateImageHeader (size, IPL_DEPTH_8U, 3);
|
retinex->cvA = cvCreateImage (size, IPL_DEPTH_32F, in_channels);
|
||||||
retinex->cvRGBout = cvCreateImageHeader (size, IPL_DEPTH_8U, 3);
|
retinex->cvB = cvCreateImage (size, IPL_DEPTH_32F, in_channels);
|
||||||
|
retinex->cvC = cvCreateImage (size, IPL_DEPTH_32F, in_channels);
|
||||||
retinex->cvA = cvCreateImage (size, IPL_DEPTH_32F, 3);
|
retinex->cvD = cvCreateImage (size, IPL_DEPTH_32F, in_channels);
|
||||||
retinex->cvB = cvCreateImage (size, IPL_DEPTH_32F, 3);
|
|
||||||
retinex->cvC = cvCreateImage (size, IPL_DEPTH_32F, 3);
|
|
||||||
retinex->cvD = cvCreateImage (size, IPL_DEPTH_32F, 3);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean up */
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_retinex_stop (GstBaseTransform * basesrc)
|
gst_retinex_stop (GstBaseTransform * basesrc)
|
||||||
{
|
{
|
||||||
GstRetinex *filter = GST_RETINEX (basesrc);
|
GstRetinex *filter = GST_RETINEX (basesrc);
|
||||||
|
|
||||||
if (filter->cvRGBin != NULL)
|
if (filter->cvA != NULL)
|
||||||
gst_retinex_release_all_images (filter);
|
gst_retinex_release_all_images (filter);
|
||||||
|
|
||||||
g_free (filter->weights);
|
g_free (filter->weights);
|
||||||
|
@ -274,9 +269,6 @@ gst_retinex_stop (GstBaseTransform * basesrc)
|
||||||
static void
|
static void
|
||||||
gst_retinex_release_all_images (GstRetinex * filter)
|
gst_retinex_release_all_images (GstRetinex * filter)
|
||||||
{
|
{
|
||||||
cvReleaseImage (&filter->cvRGBin);
|
|
||||||
cvReleaseImage (&filter->cvRGBout);
|
|
||||||
|
|
||||||
cvReleaseImage (&filter->cvA);
|
cvReleaseImage (&filter->cvA);
|
||||||
cvReleaseImage (&filter->cvB);
|
cvReleaseImage (&filter->cvB);
|
||||||
cvReleaseImage (&filter->cvC);
|
cvReleaseImage (&filter->cvC);
|
||||||
|
@ -284,35 +276,30 @@ gst_retinex_release_all_images (GstRetinex * filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_retinex_transform_ip (GstBaseTransform * btrans, GstBuffer * buf)
|
gst_retinex_transform_ip (GstOpencvVideoFilter * filter, GstBuffer * buf,
|
||||||
|
IplImage * img)
|
||||||
{
|
{
|
||||||
GstRetinex *retinex = GST_RETINEX (btrans);
|
GstRetinex *retinex = GST_RETINEX (filter);
|
||||||
GstMapInfo info;
|
|
||||||
double sigma = 14.0;
|
double sigma = 14.0;
|
||||||
int gain = 128;
|
int gain = 128;
|
||||||
int offset = 128;
|
int offset = 128;
|
||||||
int filter_size;
|
int filter_size;
|
||||||
Mat icvD = cvarrToMat(retinex->cvD, false);
|
Mat icvD = cvarrToMat(retinex->cvD, false);
|
||||||
|
|
||||||
if (!gst_buffer_map (buf, &info, (GstMapFlags) GST_MAP_READWRITE)) {
|
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
|
||||||
retinex->cvRGBin->imageData = (char *) info.data;
|
|
||||||
|
|
||||||
/* Basic retinex restoration. The image and a filtered image are converted
|
/* Basic retinex restoration. The image and a filtered image are converted
|
||||||
to the log domain and subtracted.
|
to the log domain and subtracted.
|
||||||
O = Log(I) - Log(H(I))
|
O = Log(I) - Log(H(I))
|
||||||
where O is the output, H is a gaussian 2d filter and I is the input image. */
|
where O is the output, H is a gaussian 2d filter and I is the input image. */
|
||||||
if (METHOD_BASIC == retinex->method) {
|
if (METHOD_BASIC == retinex->method) {
|
||||||
/* Compute log image */
|
/* Compute log image */
|
||||||
cvConvert (retinex->cvRGBin, retinex->cvA);
|
cvConvert (img, retinex->cvA);
|
||||||
cvLog (retinex->cvA, retinex->cvB);
|
cvLog (retinex->cvA, retinex->cvB);
|
||||||
|
|
||||||
/* Compute log of blured image */
|
/* Compute log of blured image */
|
||||||
filter_size = (int) floor (sigma * 6) / 2;
|
filter_size = (int) floor (sigma * 6) / 2;
|
||||||
filter_size = filter_size * 2 + 1;
|
filter_size = filter_size * 2 + 1;
|
||||||
|
|
||||||
cvConvert (retinex->cvRGBin, retinex->cvD);
|
cvConvert (img, retinex->cvD);
|
||||||
GaussianBlur (icvD, icvD, Size (filter_size, filter_size), 0.0, 0.0);
|
GaussianBlur (icvD, icvD, Size (filter_size, filter_size), 0.0, 0.0);
|
||||||
cvLog (retinex->cvD, retinex->cvC);
|
cvLog (retinex->cvD, retinex->cvC);
|
||||||
|
|
||||||
|
@ -320,7 +307,7 @@ gst_retinex_transform_ip (GstBaseTransform * btrans, GstBuffer * buf)
|
||||||
cvSub (retinex->cvB, retinex->cvC, retinex->cvA, NULL);
|
cvSub (retinex->cvB, retinex->cvC, retinex->cvA, NULL);
|
||||||
|
|
||||||
/* Restore */
|
/* Restore */
|
||||||
cvConvertScale (retinex->cvA, retinex->cvRGBin, (float) gain,
|
cvConvertScale (retinex->cvA, img, (float) gain,
|
||||||
(float) offset);
|
(float) offset);
|
||||||
}
|
}
|
||||||
/* Multiscale retinex restoration. The image and a set of filtered images are
|
/* Multiscale retinex restoration. The image and a set of filtered images are
|
||||||
|
@ -349,7 +336,7 @@ gst_retinex_transform_ip (GstBaseTransform * btrans, GstBuffer * buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute log image */
|
/* Compute log image */
|
||||||
cvConvert (retinex->cvRGBin, retinex->cvA);
|
cvConvert (img, retinex->cvA);
|
||||||
cvLog (retinex->cvA, retinex->cvB);
|
cvLog (retinex->cvA, retinex->cvB);
|
||||||
|
|
||||||
/* Filter at each scale */
|
/* Filter at each scale */
|
||||||
|
@ -357,7 +344,7 @@ gst_retinex_transform_ip (GstBaseTransform * btrans, GstBuffer * buf)
|
||||||
filter_size = (int) floor (retinex->sigmas[i] * 6) / 2;
|
filter_size = (int) floor (retinex->sigmas[i] * 6) / 2;
|
||||||
filter_size = filter_size * 2 + 1;
|
filter_size = filter_size * 2 + 1;
|
||||||
|
|
||||||
cvConvert (retinex->cvRGBin, retinex->cvD);
|
cvConvert (img, retinex->cvD);
|
||||||
GaussianBlur (icvD, icvD, Size (filter_size, filter_size), 0.0, 0.0);
|
GaussianBlur (icvD, icvD, Size (filter_size, filter_size), 0.0, 0.0);
|
||||||
cvLog (retinex->cvD, retinex->cvC);
|
cvLog (retinex->cvD, retinex->cvC);
|
||||||
|
|
||||||
|
@ -367,7 +354,7 @@ gst_retinex_transform_ip (GstBaseTransform * btrans, GstBuffer * buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore */
|
/* Restore */
|
||||||
cvConvertScale (retinex->cvB, retinex->cvRGBin, (float) gain,
|
cvConvertScale (retinex->cvB, img, (float) gain,
|
||||||
(float) offset);
|
(float) offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,22 +65,22 @@ typedef struct _GstRetinexClass GstRetinexClass;
|
||||||
|
|
||||||
struct _GstRetinex
|
struct _GstRetinex
|
||||||
{
|
{
|
||||||
GstVideoFilter element;
|
GstOpencvVideoFilter parent;
|
||||||
gint width, height;
|
|
||||||
gint method;
|
gint method;
|
||||||
gint scales, current_scales;
|
gint scales, current_scales;
|
||||||
|
|
||||||
double *weights;
|
double *weights;
|
||||||
double *sigmas;
|
double *sigmas;
|
||||||
|
|
||||||
IplImage *cvRGBin;
|
IplImage *cvA;
|
||||||
IplImage *cvRGBout;
|
IplImage *cvB;
|
||||||
IplImage *cvA, *cvB, *cvC, *cvD;
|
IplImage *cvC;
|
||||||
|
IplImage *cvD;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstRetinexClass
|
struct _GstRetinexClass
|
||||||
{
|
{
|
||||||
GstVideoFilterClass parent_class;
|
GstOpencvVideoFilterClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_retinex_get_type (void);
|
GType gst_retinex_get_type (void);
|
||||||
|
|
Loading…
Reference in a new issue