diff --git a/modules/tracking/include/opencv2/tracking/tracker.hpp b/modules/tracking/include/opencv2/tracking/tracker.hpp index 09ef94f66..326daad86 100644 --- a/modules/tracking/include/opencv2/tracking/tracker.hpp +++ b/modules/tracking/include/opencv2/tracking/tracker.hpp @@ -49,6 +49,7 @@ #include "onlineBoosting.hpp" #include + #define BOILERPLATE_CODE(name,classname) \ static Ptr createTracker(const classname::Params ¶meters=classname::Params());\ virtual ~classname(){}; @@ -576,6 +577,7 @@ class CV_EXPORTS_W Tracker : public virtual Algorithm Ptr model; }; + /************************************ Specific TrackerStateEstimator Classes ************************************/ /** @brief TrackerStateEstimator based on Boosting @@ -1243,6 +1245,28 @@ class CV_EXPORTS_W TrackerKCF : public Tracker BOILERPLATE_CODE("KCF",TrackerKCF); }; +/************************************ Multi-Tracker Classes ************************************/ + +class CV_EXPORTS_W MultiTracker +{ +public: + + bool addTarget(const Mat& image, const Rect2d& boundingBox, char* tracker_algorithm_name); + + bool update(const Mat& image); + + int targetNum = 0; + std::vector > trackers; + std::vector boundingBoxes; + std::vector colors; +}; + +class CV_EXPORTS_W MultiTrackerTLD : public MultiTracker +{ +public: + bool update(const Mat& image); +}; + //! @} } /* namespace cv */ diff --git a/modules/tracking/samples/multiTracker_test.cpp b/modules/tracking/samples/multiTracker_test.cpp new file mode 100644 index 000000000..ac3c37382 --- /dev/null +++ b/modules/tracking/samples/multiTracker_test.cpp @@ -0,0 +1,227 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#include +#include +#include +#include +#include + +using namespace std; +using namespace cv; + +#define NUM_TEST_FRAMES 100 +#define TEST_VIDEO_INDEX 7 //TLD Dataset Video Index from 1-10 +//#define RECORD_VIDEO_FLG + +static Mat image; +static bool paused; +static bool selectObject = false; +static bool startSelection = false; +Rect2d boundingBox; + +static void onMouse(int event, int x, int y, int, void*) +{ + if (!selectObject) + { + switch (event) + { + case EVENT_LBUTTONDOWN: + //set origin of the bounding box + startSelection = true; + boundingBox.x = x; + boundingBox.y = y; + boundingBox.width = boundingBox.height = 0; + break; + case EVENT_LBUTTONUP: + //sei with and height of the bounding box + boundingBox.width = std::abs(x - boundingBox.x); + boundingBox.height = std::abs(y - boundingBox.y); + paused = false; + selectObject = true; + break; + case EVENT_MOUSEMOVE: + + if (startSelection && !selectObject) + { + //draw the bounding box + Mat currentFrame; + image.copyTo(currentFrame); + rectangle(currentFrame, Point((int)boundingBox.x, (int)boundingBox.y), Point(x, y), Scalar(255, 0, 0), 2, 1); + imshow("Tracking API", currentFrame); + } + break; + } + } +} + +int main() +{ + // + // "MIL", "BOOSTING", "MEDIANFLOW", "TLD" + // + char* tracker_algorithm_name = "TLD"; + + Mat frame; + paused = false; + namedWindow("Tracking API", 0); + setMouseCallback("Tracking API", onMouse, 0); + + MultiTrackerTLD mt; + + //Get the first frame + ////Open the capture + // VideoCapture cap(0); + // if( !cap.isOpened() ) + // { + // cout << "Video stream error"; + // return; + // } + //cap >> frame; + + //From TLD dataset + selectObject = true; + Rect2d boundingBox1 = tld::tld_InitDataset(TEST_VIDEO_INDEX, "D:/opencv/TLD_dataset"); + Rect2d boundingBox2; + boundingBox2.x = 280; + boundingBox2.y = 60; + boundingBox2.width = 40; + boundingBox2.height = 60; + + frame = tld::tld_getNextDatasetFrame(); + frame.copyTo(image); + + // Setup output video +#ifdef RECORD_VIDEO_FLG + String outputFilename = "test.avi"; + VideoWriter outputVideo; + outputVideo.open(outputFilename, -1, 30, Size(image.cols, image.rows)); + + if (!outputVideo.isOpened()) + { + std::cout << "!!! Output video could not be opened" << std::endl; + getchar(); + return; + } +#endif + + rectangle(image, boundingBox, Scalar(255, 0, 0), 2, 1); + imshow("Tracking API", image); + + + bool initialized = false; + int frameCounter = 0; + + //Time measurment + int64 e3 = getTickCount(); + + for (;;) + { + //Time measurment + int64 e1 = getTickCount(); + //Frame num + frameCounter++; + if (frameCounter == NUM_TEST_FRAMES) break; + + char c = (char)waitKey(2); + if (c == 'q' || c == 27) + break; + if (c == 'p') + paused = !paused; + + if (!paused) + { + //cap >> frame; + frame = tld::tld_getNextDatasetFrame(); + if (frame.empty()) + { + break; + } + frame.copyTo(image); + + if (selectObject) + { + if (!initialized) + { + //initializes the tracker + mt.addTarget(frame, boundingBox1, tracker_algorithm_name); + rectangle(image, boundingBox1, mt.colors[0], 2, 1); + + + mt.addTarget(frame, boundingBox2, tracker_algorithm_name); + rectangle(image, boundingBox2, mt.colors[1], 2, 1); + initialized = true; + } + else + { + //updates the tracker + if (mt.update(frame)) + for (int i=0; i < mt.targetNum; i++) + rectangle(image, mt.boundingBoxes[i], mt.colors[i], 2, 1); + } + } + imshow("Tracking API", image); + +#ifdef RECORD_VIDEO_FLG + outputVideo << image; +#endif + + + //Time measurment + int64 e2 = getTickCount(); + double t1 = (e2 - e1) / getTickFrequency(); + cout << frameCounter << "\tframe : " << t1 * 1000.0 << "ms" << endl; + + waitKey(0); + } + } + + //Time measurment + int64 e4 = getTickCount(); + double t2 = (e4 - e3) / getTickFrequency(); + cout << "Average Time for Frame: " << t2 * 1000.0 / frameCounter << "ms" << endl; + cout << "Average FPS: " << 1.0 / t2*frameCounter << endl; + + + waitKey(0); + + return 0; +} \ No newline at end of file diff --git a/modules/tracking/src/multiTracker.cpp b/modules/tracking/src/multiTracker.cpp new file mode 100644 index 000000000..0ce6e55ca --- /dev/null +++ b/modules/tracking/src/multiTracker.cpp @@ -0,0 +1,49 @@ +#include + +namespace cv +{ + //Multitracker + bool MultiTracker::addTarget(const Mat& image, const Rect2d& boundingBox, char* tracker_algorithm_name) + { + Ptr tracker = Tracker::create(tracker_algorithm_name); + if (tracker == NULL) + return false; + + if (!tracker->init(image, boundingBox)) + return false; + + //Add BB of target + boundingBoxes.push_back(boundingBox); + + //Add Tracker to stack + trackers.push_back(tracker); + + //Assign a random color to target + colors.push_back(Scalar(rand() % 256, rand() % 256, rand() % 256)); + + //Target counter + targetNum++; + + return true; + } + + bool MultiTracker::update(const Mat& image) + { + for (int i = 0; i < trackers.size(); i++) + if (!trackers[i]->update(image, boundingBoxes[i])) + return false; + + return true; + } + + //Multitracker TLD + /*Optimized update method for TLD Multitracker */ + bool MultiTrackerTLD::update(const Mat& image) + { + for (int i = 0; i < trackers.size(); i++) + if (!trackers[i]->update(image, boundingBoxes[i])) + return false; + + return true; + } +} \ No newline at end of file diff --git a/modules/tracking/src/tldDetector.cpp b/modules/tracking/src/tldDetector.cpp index cbb783ece..900761bef 100644 --- a/modules/tracking/src/tldDetector.cpp +++ b/modules/tracking/src/tldDetector.cpp @@ -219,7 +219,7 @@ namespace cv // 2 -> Pos&Neg size_t globSize = 2 * numOfPatches*MAX_EXAMPLES_IN_MODEL; //e3 = getTickCount(); - if (!k.run(1, &globSize, NULL, false)) + if (!k.run(1, &globSize, NULL, true)) printf("Kernel Run Error!!!"); //e4 = getTickCount(); //t = (e4 - e3) / getTickFrequency()*1000.0;