From d28f11998deadc8036bb63aa5bdc80beb1a9fbe4 Mon Sep 17 00:00:00 2001 From: Vivek R <123vivekr@gmail.com> Date: Sun, 24 May 2020 23:37:25 +0530 Subject: opencv: add cvtracker plugin This adds an object tracker plugin. Tracker implementations from https://docs.opencv.org/3.4/d0/d0a/classcv_1_1Tracker.html Part-of: --- ext/opencv/gstcvtracker.cpp | 393 ++++++++++++++++++++++++++++++++++++++++++++ ext/opencv/gstcvtracker.h | 114 +++++++++++++ ext/opencv/gstopencv.cpp | 2 + ext/opencv/meson.build | 7 +- 4 files changed, 514 insertions(+), 2 deletions(-) create mode 100644 ext/opencv/gstcvtracker.cpp create mode 100644 ext/opencv/gstcvtracker.h (limited to 'ext') diff --git a/ext/opencv/gstcvtracker.cpp b/ext/opencv/gstcvtracker.cpp new file mode 100644 index 000000000..829d9a2c6 --- /dev/null +++ b/ext/opencv/gstcvtracker.cpp @@ -0,0 +1,393 @@ +/* + * GStreamer + * Copyright (C) 2020 Vivek R <123vivekr@gmail.com> + * Copyright (C) 2021 Cesar Fabian Orccon Chipana + * + * 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-cvtracker + * + * Performs object tracking on videos and stores it in video buffer metadata. + * + * ## Example launch line + * + * ``` + * gst-launch-1.0 v4l2src ! videoconvert ! cvtracker box-x=50 box-y=50 box-wdith=50 box-height=50 ! videoconvert ! xvimagesink + * ``` + * + * Since: 1.20 + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gstcvtracker.h" + +GST_DEBUG_CATEGORY_STATIC (gst_cvtracker_debug); +#define GST_CAT_DEFAULT gst_cvtracker_debug + +#define DEFAULT_PROP_INITIAL_X 50 +#define DEFAULT_PROP_INITIAL_Y 50 +#define DEFAULT_PROP_INITIAL_WIDTH 50 +#define DEFAULT_PROP_INITIAL_HEIGHT 50 + +enum +{ + PROP_0, + PROP_INITIAL_X, + PROP_INITIAL_Y, + PROP_INITIAL_WIDTH, + PROP_INITIAL_HEIGHT, + PROP_ALGORITHM, +}; + +#define GST_OPENCV_TRACKER_ALGORITHM (tracker_algorithm_get_type ()) + +/** + * GstOpenCVTrackerAlgorithm: + * + * Since: 1.20 + */ +static GType +tracker_algorithm_get_type (void) +{ + static GType algorithm = 0; + static const GEnumValue algorithms[] = { + {GST_OPENCV_TRACKER_ALGORITHM_BOOSTING, "the Boosting tracker", "Boosting"}, + {GST_OPENCV_TRACKER_ALGORITHM_CSRT, "the CSRT tracker", "CSRT"}, + {GST_OPENCV_TRACKER_ALGORITHM_KCF, + "the KCF (Kernelized Correlation Filter) tracker", + "KCF"}, + {GST_OPENCV_TRACKER_ALGORITHM_MEDIANFLOW, "the Median Flow tracker", + "MedianFlow"}, + {GST_OPENCV_TRACKER_ALGORITHM_MIL, "the MIL tracker", "MIL"}, + {GST_OPENCV_TRACKER_ALGORITHM_MOSSE, + "the MOSSE (Minimum Output Sum of Squared Error) tracker", "MOSSE"}, + {GST_OPENCV_TRACKER_ALGORITHM_TLD, + "the TLD (Tracking, learning and detection) tracker", + "TLD"}, + {0, NULL, NULL}, + }; + + if (!algorithm) { + algorithm = + g_enum_register_static ("GstOpenCVTrackerAlgorithm", algorithms); + } + return algorithm; +} + +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB")) + ); + +static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB")) + ); + +G_DEFINE_TYPE_WITH_CODE (GstCVTracker, gst_cvtracker, + GST_TYPE_OPENCV_VIDEO_FILTER, + GST_DEBUG_CATEGORY_INIT (gst_cvtracker_debug, "cvtracker", 0, + "Performs object tracking on videos and stores it in video buffer " + "metadata")); +GST_ELEMENT_REGISTER_DEFINE (cvtracker, "cvtracker", GST_RANK_NONE, + GST_TYPE_OPENCV_TRACKER); + +static void gst_cvtracker_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_cvtracker_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstFlowReturn gst_cvtracker_transform_ip (GstOpencvVideoFilter + * filter, GstBuffer * buf, cv::Mat img); + +static void +gst_cvtracker_finalize (GObject * obj) +{ + GstCVTracker *filter = GST_OPENCV_TRACKER (obj); + + filter->tracker.release (); + filter->roi.release (); + + G_OBJECT_CLASS (gst_cvtracker_parent_class)->finalize (obj); +} + +static void +gst_cvtracker_class_init (GstCVTrackerClass * klass) +{ + GObjectClass *gobject_class; + GstOpencvVideoFilterClass *gstopencvbasefilter_class; + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gobject_class = (GObjectClass *) klass; + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_cvtracker_finalize); + gstopencvbasefilter_class = (GstOpencvVideoFilterClass *) klass; + + gstopencvbasefilter_class->cv_trans_ip_func = gst_cvtracker_transform_ip; + + gobject_class->set_property = gst_cvtracker_set_property; + gobject_class->get_property = gst_cvtracker_get_property; + + /* + * Tracker API in versions older than OpenCV 4.5.1 worked with a ROI based + * on Rect. However newer versions use Rect. Running the same + * tracker type on different versions may lead to round up errors. + * To avoid inconsistencies from the GStreamer side depending on the OpenCV + * version, use integer properties independently on the OpenCV. + **/ + g_object_class_install_property (gobject_class, PROP_INITIAL_X, + g_param_spec_uint ("object-initial-x", "Initial X coordinate", + "Track object box's initial X coordinate", 0, G_MAXUINT, + DEFAULT_PROP_INITIAL_X, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (gobject_class, PROP_INITIAL_Y, + g_param_spec_uint ("object-initial-y", "Initial Y coordinate", + "Track object box's initial Y coordinate", 0, G_MAXUINT, + DEFAULT_PROP_INITIAL_Y, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (gobject_class, PROP_INITIAL_WIDTH, + g_param_spec_uint ("object-initial-width", "Object Initial Width", + "Track object box's initial width", 0, G_MAXUINT, + DEFAULT_PROP_INITIAL_WIDTH, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (gobject_class, PROP_INITIAL_HEIGHT, + g_param_spec_uint ("object-initial-height", "Object Initial Height", + "Track object box's initial height", 0, G_MAXUINT, + DEFAULT_PROP_INITIAL_HEIGHT, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (gobject_class, PROP_ALGORITHM, + g_param_spec_enum ("algorithm", "Algorithm", + "Algorithm for tracking objects", GST_OPENCV_TRACKER_ALGORITHM, + GST_OPENCV_TRACKER_ALGORITHM_MEDIANFLOW, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + gst_element_class_set_static_metadata (element_class, + "cvtracker", + "Filter/Effect/Video", + "Performs object tracking on videos and stores it in video buffer metadata.", + "Vivek R <123vivekr@gmail.com>"); + + gst_element_class_add_static_pad_template (element_class, &src_factory); + gst_element_class_add_static_pad_template (element_class, &sink_factory); + + gst_type_mark_as_plugin_api (GST_OPENCV_TRACKER_ALGORITHM, + (GstPluginAPIFlags) 0); +} + +static void +gst_cvtracker_init (GstCVTracker * filter) +{ + filter->x = DEFAULT_PROP_INITIAL_X; + filter->y = DEFAULT_PROP_INITIAL_Y; + filter->width = DEFAULT_PROP_INITIAL_WIDTH; + filter->height = DEFAULT_PROP_INITIAL_HEIGHT; +#if CV_VERSION_MAJOR == 4 && CV_VERSION_MINOR >= 5 && CV_VERSION_REVISION >= 1 + filter->tracker = cv::legacy::upgradeTrackingAPI( + cv::legacy::TrackerMedianFlow::create()); +#else + filter->tracker = cv::TrackerMedianFlow::create(); +#endif + filter->post_debug_info = TRUE; + + gst_opencv_video_filter_set_in_place (GST_OPENCV_VIDEO_FILTER_CAST (filter), + TRUE); + filter->algorithm = GST_OPENCV_TRACKER_ALGORITHM_MEDIANFLOW; +} + +static void +gst_cvtracker_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstCVTracker *filter = GST_OPENCV_TRACKER (object); + + switch (prop_id) { + case PROP_INITIAL_X: + filter->x = g_value_get_uint (value); + break; + case PROP_INITIAL_Y: + filter->y = g_value_get_uint (value); + break; + case PROP_INITIAL_WIDTH: + filter->width = g_value_get_uint (value); + break; + case PROP_INITIAL_HEIGHT: + filter->height = g_value_get_uint (value); + break; + case PROP_ALGORITHM: + filter->algorithm = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +create_cvtracker (GstCVTracker * filter) +{ + switch (filter->algorithm) { + case GST_OPENCV_TRACKER_ALGORITHM_BOOSTING: +#if CV_VERSION_MAJOR == 4 && CV_VERSION_MINOR >= 5 && CV_VERSION_REVISION >= 1 + filter->tracker = cv::legacy::upgradeTrackingAPI( + cv::legacy::TrackerBoosting::create()); +#else + filter->tracker = cv::TrackerBoosting::create(); +#endif + break; + case GST_OPENCV_TRACKER_ALGORITHM_CSRT: + filter->tracker = cv::TrackerCSRT::create (); + break; + case GST_OPENCV_TRACKER_ALGORITHM_KCF: + filter->tracker = cv::TrackerKCF::create (); + break; + case GST_OPENCV_TRACKER_ALGORITHM_MEDIANFLOW: +#if CV_VERSION_MAJOR == 4 && CV_VERSION_MINOR >= 5 && CV_VERSION_REVISION >= 1 + filter->tracker = cv::legacy::upgradeTrackingAPI( + cv::legacy::TrackerMedianFlow::create()); +#else + filter->tracker = cv::TrackerMedianFlow::create(); +#endif + break; + case GST_OPENCV_TRACKER_ALGORITHM_MIL: + filter->tracker = cv::TrackerMIL::create (); + break; + case GST_OPENCV_TRACKER_ALGORITHM_MOSSE: +#if CV_VERSION_MAJOR == 4 && CV_VERSION_MINOR >= 5 && CV_VERSION_REVISION >= 1 + filter->tracker = cv::legacy::upgradeTrackingAPI( + cv::legacy::TrackerMOSSE::create()); +#else + filter->tracker = cv::TrackerMOSSE::create (); +#endif + break; + case GST_OPENCV_TRACKER_ALGORITHM_TLD: +#if CV_VERSION_MAJOR == 4 && CV_VERSION_MINOR >= 5 && CV_VERSION_REVISION >= 1 + filter->tracker = cv::legacy::upgradeTrackingAPI( + cv::legacy::TrackerTLD::create()); +#else + filter->tracker = cv::TrackerTLD::create(); +#endif + break; + } +} + +static void +gst_cvtracker_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstCVTracker *filter = GST_OPENCV_TRACKER (object); + + switch (prop_id) { + case PROP_INITIAL_X: + g_value_set_uint (value, filter->x); + break; + case PROP_INITIAL_Y: + g_value_set_uint (value, filter->y); + break; + case PROP_INITIAL_WIDTH: + g_value_set_uint (value, filter->width); + break; + case PROP_INITIAL_HEIGHT: + g_value_set_uint (value, filter->height); + break; + case PROP_ALGORITHM: + g_value_set_enum (value, filter->algorithm); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstFlowReturn +gst_cvtracker_transform_ip (GstOpencvVideoFilter * base, + GstBuffer * buf, cv::Mat img) +{ + GstCVTracker *filter = GST_OPENCV_TRACKER (base); + GstStructure *s; + GstMessage *msg; + + if (filter->roi.empty ()) { +#if CV_VERSION_MAJOR == 4 && CV_VERSION_MINOR >= 5 && CV_VERSION_REVISION >= 1 + filter->roi = new (cv::Rect); +#else + filter->roi = new (cv::Rect2d); +#endif + filter->roi->x = filter->x; + filter->roi->y = filter->y; + filter->roi->width = filter->width; + filter->roi->height = filter->height; + create_cvtracker (filter); + filter->tracker->init (img, *filter->roi); + } else if (filter->tracker->update (img, *filter->roi)) { +#if (!(CV_VERSION_MAJOR == 4 && CV_VERSION_MINOR >= 5 && CV_VERSION_REVISION >= 1)) + /* Round values to avoid inconsistencies depending on the OpenCV version. */ + filter->roi->x = cvRound (filter->roi->x); + filter->roi->y = cvRound (filter->roi->y); + filter->roi->width = cvRound (filter->roi->width); + filter->roi->height = cvRound (filter->roi->height); +#endif + s = gst_structure_new ("object", + "x", G_TYPE_UINT, (guint) filter->roi->x, + "y", G_TYPE_UINT, (guint) filter->roi->y, + "width", G_TYPE_UINT, (guint) filter->roi->width, + "height", G_TYPE_UINT, (guint) filter->roi->height, NULL); + msg = gst_message_new_element (GST_OBJECT (filter), s); + gst_buffer_add_video_region_of_interest_meta (buf, "object", + filter->roi->x, filter->roi->y, filter->roi->width, + filter->roi->height); + gst_element_post_message (GST_ELEMENT (filter), msg); + if (!(filter->post_debug_info)) + filter->post_debug_info = TRUE; + } else if (filter->post_debug_info) { + GST_DEBUG_OBJECT (filter, "tracker lost"); + filter->post_debug_info = FALSE; + } + + return GST_FLOW_OK; +} diff --git a/ext/opencv/gstcvtracker.h b/ext/opencv/gstcvtracker.h new file mode 100644 index 000000000..b817c86b8 --- /dev/null +++ b/ext/opencv/gstcvtracker.h @@ -0,0 +1,114 @@ +/* + * GStreamer + * Copyright (C) 2020 Vivek R <123vivekr@gmail.com> + * Copyright (C) 2021 Cesar Fabian Orccon Chipana + * + * 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_CVTRACKER_H__ +#define __GST_CVTRACKER_H__ + +#include +#include +#include +#include +#include +#if CV_VERSION_MAJOR == 4 && CV_VERSION_MINOR >= 5 && CV_VERSION_REVISION >= 1 +#include +#endif + +G_BEGIN_DECLS + +/* #defines don't like whitespacey bits */ +#define GST_TYPE_OPENCV_TRACKER \ + (gst_cvtracker_get_type()) +#define GST_OPENCV_TRACKER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OPENCV_TRACKER,GstCVTracker)) +#define GST_OPENCV_TRACKER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OPENCV_TRACKER,GstCVTrackerClass)) +#define GST_IS_OPENCV_TRACKER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OPENCV_TRACKER)) +#define GST_IS_OPENCV_TRACKER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OPENCV_TRACKER)) + +typedef struct _GstCVTracker GstCVTracker; +typedef struct _GstCVTrackerClass GstCVTrackerClass; + +struct _GstCVTracker +{ + GstOpencvVideoFilter element; + + guint x; + guint y; + guint width; + guint height; + gint algorithm; + gboolean post_debug_info; + + cv::Ptr tracker; +#if CV_VERSION_MAJOR == 4 && CV_VERSION_MINOR >= 5 && CV_VERSION_REVISION >= 1 + cv::Ptr roi; +#else + cv::Ptr roi; +#endif +}; + +typedef enum { + GST_OPENCV_TRACKER_ALGORITHM_BOOSTING, + GST_OPENCV_TRACKER_ALGORITHM_CSRT, + GST_OPENCV_TRACKER_ALGORITHM_KCF, + GST_OPENCV_TRACKER_ALGORITHM_MEDIANFLOW, + GST_OPENCV_TRACKER_ALGORITHM_MIL, + GST_OPENCV_TRACKER_ALGORITHM_MOSSE, + GST_OPENCV_TRACKER_ALGORITHM_TLD, +} GstOpenCVTrackerAlgorithm; + +struct _GstCVTrackerClass +{ + GstOpencvVideoFilterClass parent_class; +}; + +GType gst_cvtracker_get_type (void); + +GST_ELEMENT_REGISTER_DECLARE (cvtracker); + +G_END_DECLS + +#endif /* __GST_CVTRACKER_H__ */ diff --git a/ext/opencv/gstopencv.cpp b/ext/opencv/gstopencv.cpp index aee54c35b..5407a5a99 100644 --- a/ext/opencv/gstopencv.cpp +++ b/ext/opencv/gstopencv.cpp @@ -44,6 +44,7 @@ #include "gstdewarp.h" #include "gstcameracalibrate.h" #include "gstcameraundistort.h" +#include "gstcvtracker.h" static gboolean @@ -72,6 +73,7 @@ plugin_init (GstPlugin * plugin) ret |= GST_ELEMENT_REGISTER (dewarp, plugin); ret |= GST_ELEMENT_REGISTER (cameracalibrate, plugin); ret |= GST_ELEMENT_REGISTER (cameraundistort, plugin); + ret |= GST_ELEMENT_REGISTER (cvtracker, plugin); return ret; } diff --git a/ext/opencv/meson.build b/ext/opencv/meson.build index f69ea5966..b0bd54e80 100644 --- a/ext/opencv/meson.build +++ b/ext/opencv/meson.build @@ -30,7 +30,8 @@ gstopencv_sources = [ 'camerautils.cpp', 'cameraevent.cpp', 'gstcameracalibrate.cpp', - 'gstcameraundistort.cpp' + 'gstcameraundistort.cpp', + 'gstcvtracker.cpp' ] libopencv_headers = [ @@ -41,6 +42,7 @@ libopencv_headers = [ 'opencv2/objdetect.hpp', 'opencv2/opencv.hpp', 'opencv2/video.hpp', + 'opencv2/tracking.hpp', ] libopencv4_headers = [ @@ -51,6 +53,7 @@ libopencv4_headers = [ 'opencv4/opencv2/objdetect.hpp', 'opencv4/opencv2/opencv.hpp', 'opencv4/opencv2/video.hpp', + 'opencv4/opencv2/tracking.hpp', ] gstopencv_cargs = ['-DGST_HAAR_CASCADES_DIR="@0@"'] @@ -115,7 +118,7 @@ if opencv_found gstopencv = library('gstopencv', gstopencv_sources, cpp_args : gst_plugins_bad_args + gstopencv_cargs + [ '-DGST_USE_UNSTABLE_API' ], - link_args : noseh_link_args, + link_args : [noseh_link_args, '-lopencv_tracking'], include_directories : [configinc, libsinc], dependencies : [gstbase_dep, gstvideo_dep, opencv_dep, gstopencv_dep], install : true, -- cgit v1.2.1