Commit 3ac9e242 authored by Vladislav Sovrasov's avatar Vladislav Sovrasov

tracking: improve public API

Use ROI selector in python samples
parent 4317e27d
...@@ -47,12 +47,6 @@ ...@@ -47,12 +47,6 @@
#include "feature.hpp" #include "feature.hpp"
#include "onlineMIL.hpp" #include "onlineMIL.hpp"
#include "onlineBoosting.hpp" #include "onlineBoosting.hpp"
#include <iostream>
#define BOILERPLATE_CODE(name,classname) \
static Ptr<classname> createTracker(const classname::Params &parameters=classname::Params());\
virtual ~classname(){};
/* /*
* Partially based on: * Partially based on:
...@@ -539,7 +533,7 @@ class CV_EXPORTS_W Tracker : public virtual Algorithm ...@@ -539,7 +533,7 @@ class CV_EXPORTS_W Tracker : public virtual Algorithm
@return True if initialization went succesfully, false otherwise @return True if initialization went succesfully, false otherwise
*/ */
CV_WRAP bool init( const Mat& image, const Rect2d& boundingBox ); CV_WRAP bool init( InputArray image, const Rect2d& boundingBox );
/** @brief Update the tracker, find the new most likely bounding box for the target /** @brief Update the tracker, find the new most likely bounding box for the target
@param image The current frame @param image The current frame
...@@ -550,17 +544,7 @@ class CV_EXPORTS_W Tracker : public virtual Algorithm ...@@ -550,17 +544,7 @@ class CV_EXPORTS_W Tracker : public virtual Algorithm
current frame. Note, that latter *does not* imply that tracker has failed, maybe target is indeed current frame. Note, that latter *does not* imply that tracker has failed, maybe target is indeed
missing from the frame (say, out of sight) missing from the frame (say, out of sight)
*/ */
CV_WRAP bool update( const Mat& image, CV_OUT Rect2d& boundingBox ); CV_WRAP bool update( InputArray image, CV_OUT Rect2d& boundingBox );
/** @brief Creates a tracker by its name.
@param trackerType Tracker type
The following detector types are supported:
- "MIL" -- TrackerMIL
- "BOOSTING" -- TrackerBoosting
*/
CV_WRAP static Ptr<Tracker> create( const String& trackerType );
virtual void read( const FileNode& fn )=0; virtual void read( const FileNode& fn )=0;
virtual void write( FileStorage& fs ) const=0; virtual void write( FileStorage& fs ) const=0;
...@@ -1078,7 +1062,7 @@ based on @cite MIL . ...@@ -1078,7 +1062,7 @@ based on @cite MIL .
Original code can be found here <http://vision.ucsd.edu/~bbabenko/project_miltrack.shtml> Original code can be found here <http://vision.ucsd.edu/~bbabenko/project_miltrack.shtml>
*/ */
class CV_EXPORTS TrackerMIL : public Tracker class CV_EXPORTS_W TrackerMIL : public Tracker
{ {
public: public:
struct CV_EXPORTS Params struct CV_EXPORTS Params
...@@ -1100,7 +1084,11 @@ class CV_EXPORTS TrackerMIL : public Tracker ...@@ -1100,7 +1084,11 @@ class CV_EXPORTS TrackerMIL : public Tracker
/** @brief Constructor /** @brief Constructor
@param parameters MIL parameters TrackerMIL::Params @param parameters MIL parameters TrackerMIL::Params
*/ */
BOILERPLATE_CODE("MIL",TrackerMIL); static Ptr<TrackerMIL> create(const TrackerMIL::Params &parameters);
CV_WRAP static Ptr<TrackerMIL> create();
virtual ~TrackerMIL() {}
}; };
/** @brief This is a real-time object tracking based on a novel on-line version of the AdaBoost algorithm. /** @brief This is a real-time object tracking based on a novel on-line version of the AdaBoost algorithm.
...@@ -1108,7 +1096,7 @@ class CV_EXPORTS TrackerMIL : public Tracker ...@@ -1108,7 +1096,7 @@ class CV_EXPORTS TrackerMIL : public Tracker
The classifier uses the surrounding background as negative examples in update step to avoid the The classifier uses the surrounding background as negative examples in update step to avoid the
drifting problem. The implementation is based on @cite OLB . drifting problem. The implementation is based on @cite OLB .
*/ */
class CV_EXPORTS TrackerBoosting : public Tracker class CV_EXPORTS_W TrackerBoosting : public Tracker
{ {
public: public:
struct CV_EXPORTS Params struct CV_EXPORTS Params
...@@ -1133,7 +1121,11 @@ class CV_EXPORTS TrackerBoosting : public Tracker ...@@ -1133,7 +1121,11 @@ class CV_EXPORTS TrackerBoosting : public Tracker
/** @brief Constructor /** @brief Constructor
@param parameters BOOSTING parameters TrackerBoosting::Params @param parameters BOOSTING parameters TrackerBoosting::Params
*/ */
BOILERPLATE_CODE("BOOSTING",TrackerBoosting); static Ptr<TrackerBoosting> create(const TrackerBoosting::Params &parameters);
CV_WRAP static Ptr<TrackerBoosting> create();
virtual ~TrackerBoosting() {}
}; };
/** @brief Median Flow tracker implementation. /** @brief Median Flow tracker implementation.
...@@ -1146,7 +1138,7 @@ by authors to outperform MIL). During the implementation period the code at ...@@ -1146,7 +1138,7 @@ by authors to outperform MIL). During the implementation period the code at
<http://www.aonsquared.co.uk/node/5>, the courtesy of the author Arthur Amarra, was used for the <http://www.aonsquared.co.uk/node/5>, the courtesy of the author Arthur Amarra, was used for the
reference purpose. reference purpose.
*/ */
class CV_EXPORTS TrackerMedianFlow : public Tracker class CV_EXPORTS_W TrackerMedianFlow : public Tracker
{ {
public: public:
struct CV_EXPORTS Params struct CV_EXPORTS Params
...@@ -1168,7 +1160,11 @@ class CV_EXPORTS TrackerMedianFlow : public Tracker ...@@ -1168,7 +1160,11 @@ class CV_EXPORTS TrackerMedianFlow : public Tracker
/** @brief Constructor /** @brief Constructor
@param parameters Median Flow parameters TrackerMedianFlow::Params @param parameters Median Flow parameters TrackerMedianFlow::Params
*/ */
BOILERPLATE_CODE("MEDIANFLOW",TrackerMedianFlow); static Ptr<TrackerMedianFlow> create(const TrackerMedianFlow::Params &parameters);
CV_WRAP static Ptr<TrackerMedianFlow> create();
virtual ~TrackerMedianFlow() {}
}; };
/** @brief TLD is a novel tracking framework that explicitly decomposes the long-term tracking task into /** @brief TLD is a novel tracking framework that explicitly decomposes the long-term tracking task into
...@@ -1182,7 +1178,7 @@ The Median Flow algorithm (see cv::TrackerMedianFlow) was chosen as a tracking c ...@@ -1182,7 +1178,7 @@ The Median Flow algorithm (see cv::TrackerMedianFlow) was chosen as a tracking c
implementation, following authors. Tracker is supposed to be able to handle rapid motions, partial implementation, following authors. Tracker is supposed to be able to handle rapid motions, partial
occlusions, object absence etc. occlusions, object absence etc.
*/ */
class CV_EXPORTS TrackerTLD : public Tracker class CV_EXPORTS_W TrackerTLD : public Tracker
{ {
public: public:
struct CV_EXPORTS Params struct CV_EXPORTS Params
...@@ -1195,7 +1191,11 @@ class CV_EXPORTS TrackerTLD : public Tracker ...@@ -1195,7 +1191,11 @@ class CV_EXPORTS TrackerTLD : public Tracker
/** @brief Constructor /** @brief Constructor
@param parameters TLD parameters TrackerTLD::Params @param parameters TLD parameters TrackerTLD::Params
*/ */
BOILERPLATE_CODE("TLD",TrackerTLD); static Ptr<TrackerTLD> create(const TrackerTLD::Params &parameters);
CV_WRAP static Ptr<TrackerTLD> create();
virtual ~TrackerTLD() {}
}; };
/** @brief KCF is a novel tracking framework that utilizes properties of circulant matrix to enhance the processing speed. /** @brief KCF is a novel tracking framework that utilizes properties of circulant matrix to enhance the processing speed.
...@@ -1204,7 +1204,7 @@ class CV_EXPORTS TrackerTLD : public Tracker ...@@ -1204,7 +1204,7 @@ class CV_EXPORTS TrackerTLD : public Tracker
* as well as the matlab implementation. For more information about KCF with color-names features, please refer to * as well as the matlab implementation. For more information about KCF with color-names features, please refer to
* <http://www.cvl.isy.liu.se/research/objrec/visualtracking/colvistrack/index.html>. * <http://www.cvl.isy.liu.se/research/objrec/visualtracking/colvistrack/index.html>.
*/ */
class CV_EXPORTS TrackerKCF : public Tracker class CV_EXPORTS_W TrackerKCF : public Tracker
{ {
public: public:
/** /**
...@@ -1251,12 +1251,16 @@ public: ...@@ -1251,12 +1251,16 @@ public:
int desc_npca; //!< non-compressed descriptors of TrackerKCF::MODE int desc_npca; //!< non-compressed descriptors of TrackerKCF::MODE
}; };
virtual void setFeatureExtractor(void(*)(const Mat, const Rect, Mat&), bool pca_func = false); virtual void setFeatureExtractor(void(*)(const Mat, const Rect, Mat&), bool pca_func = false) = 0;
/** @brief Constructor /** @brief Constructor
@param parameters KCF parameters TrackerKCF::Params @param parameters KCF parameters TrackerKCF::Params
*/ */
BOILERPLATE_CODE("KCF", TrackerKCF); static Ptr<TrackerKCF> create(const TrackerKCF::Params &parameters);
CV_WRAP static Ptr<TrackerKCF> create();
virtual ~TrackerKCF() {}
}; };
/** @brief GOTURN (@cite GOTURN) is kind of trackers based on Convolutional Neural Networks (CNN). While taking all advantages of CNN trackers, /** @brief GOTURN (@cite GOTURN) is kind of trackers based on Convolutional Neural Networks (CNN). While taking all advantages of CNN trackers,
...@@ -1272,7 +1276,7 @@ public: ...@@ -1272,7 +1276,7 @@ public:
* <https://github.com/Auron-X/GOTURN_Training_Toolkit> * <https://github.com/Auron-X/GOTURN_Training_Toolkit>
* GOTURN architecture goturn.prototxt and trained model goturn.caffemodel are accessible on opencv_extra GitHub repository. * GOTURN architecture goturn.prototxt and trained model goturn.caffemodel are accessible on opencv_extra GitHub repository.
*/ */
class CV_EXPORTS TrackerGOTURN : public Tracker class CV_EXPORTS_W TrackerGOTURN : public Tracker
{ {
public: public:
struct CV_EXPORTS Params struct CV_EXPORTS Params
...@@ -1285,7 +1289,11 @@ public: ...@@ -1285,7 +1289,11 @@ public:
/** @brief Constructor /** @brief Constructor
@param parameters GOTURN parameters TrackerGOTURN::Params @param parameters GOTURN parameters TrackerGOTURN::Params
*/ */
BOILERPLATE_CODE("GOTURN", TrackerGOTURN); static Ptr<TrackerGOTURN> create(const TrackerGOTURN::Params &parameters);
CV_WRAP static Ptr<TrackerGOTURN> create();
virtual ~TrackerGOTURN() {}
}; };
/************************************ MultiTracker Class ---By Laksono Kurnianggoro---) ************************************/ /************************************ MultiTracker Class ---By Laksono Kurnianggoro---) ************************************/
...@@ -1293,16 +1301,14 @@ public: ...@@ -1293,16 +1301,14 @@ public:
* The MultiTracker is naive implementation of multiple object tracking. * The MultiTracker is naive implementation of multiple object tracking.
* It process the tracked objects independently without any optimization accross the tracked objects. * It process the tracked objects independently without any optimization accross the tracked objects.
*/ */
class CV_EXPORTS_W MultiTracker class CV_EXPORTS_W MultiTracker : public Algorithm
{ {
public: public:
/** /**
* \brief Constructor. * \brief Constructor.
* In the case of trackerType is given, it will be set as the default algorithm for all trackers.
* @param trackerType the name of the tracker algorithm to be used
*/ */
CV_WRAP MultiTracker(const String& trackerType = ""); CV_WRAP MultiTracker();
/** /**
* \brief Destructor * \brief Destructor
...@@ -1311,58 +1317,51 @@ public: ...@@ -1311,58 +1317,51 @@ public:
/** /**
* \brief Add a new object to be tracked. * \brief Add a new object to be tracked.
* The defaultAlgorithm will be used the newly added tracker. *
* @param image input image * @param newTracker tracking algorithm to be used
* @param boundingBox a rectangle represents ROI of the tracked object
*/
CV_WRAP bool add(const Mat& image, const Rect2d& boundingBox);
/**
* \brief Add a new object to be tracked.
* @param trackerType the name of the tracker algorithm to be used
* @param image input image * @param image input image
* @param boundingBox a rectangle represents ROI of the tracked object * @param boundingBox a rectangle represents ROI of the tracked object
*/ */
CV_WRAP bool add(const String& trackerType, const Mat& image, const Rect2d& boundingBox); CV_WRAP bool add(Ptr<Tracker> newTracker, InputArray image, const Rect2d& boundingBox);
/** /**
* \brief Add a set of objects to be tracked. * \brief Add a set of objects to be tracked.
* @param trackerType the name of the tracker algorithm to be used * @param newTrackers list of tracking algorithms to be used
* @param image input image * @param image input image
* @param boundingBox list of the tracked objects * @param boundingBox list of the tracked objects
*/ */
CV_WRAP bool add(const String& trackerType, const Mat& image, std::vector<Rect2d> boundingBox); bool add(std::vector<Ptr<Tracker> > newTrackers, InputArray image, std::vector<Rect2d> boundingBox);
/** /**
* \brief Add a set of objects to be tracked using the defaultAlgorithm tracker. * \brief Update the current tracking status.
* The result will be saved in the internal storage.
* @param image input image * @param image input image
* @param boundingBox list of the tracked objects
*/ */
CV_WRAP bool add(const Mat& image, std::vector<Rect2d> boundingBox); bool update(InputArray image);
/** /**
* \brief Update the current tracking status. * \brief Update the current tracking status.
* The result will be saved in the internal storage.
* @param image input image * @param image input image
* @param boundingBox the tracking result, represent a list of ROIs of the tracked objects.
*/ */
bool update(const Mat& image); CV_WRAP bool update(InputArray image, CV_OUT std::vector<Rect2d> & boundingBox);
//!< storage for the tracked objects, each object corresponds to one tracker algorithm. /**
std::vector<Rect2d> objects; * \brief Returns a reference to a storage for the tracked objects, each object corresponds to one tracker algorithm
*/
CV_WRAP const std::vector<Rect2d>& getObjects() const;
/** /**
* \brief Update the current tracking status. * \brief Returns a pointer to a new instance of MultiTracker
* @param image input image
* @param boundingBox the tracking result, represent a list of ROIs of the tracked objects.
*/ */
CV_WRAP bool update(const Mat& image, CV_OUT std::vector<Rect2d> & boundingBox); CV_WRAP static Ptr<MultiTracker> create();
protected: protected:
//!< storage for the tracker algorithms. //!< storage for the tracker algorithms.
std::vector< Ptr<Tracker> > trackerList; std::vector< Ptr<Tracker> > trackerList;
//!< default algorithm for the tracking method. //!< storage for the tracked objects, each object corresponds to one tracker algorithm.
String defaultAlgorithm; std::vector<Rect2d> objects;
}; };
/************************************ Multi-Tracker Classes ---By Tyan Vladimir---************************************/ /************************************ Multi-Tracker Classes ---By Tyan Vladimir---************************************/
...@@ -1384,11 +1383,11 @@ public: ...@@ -1384,11 +1383,11 @@ public:
/** @brief Add a new target to a tracking-list and initialize the tracker with a know bounding box that surrounding the target /** @brief Add a new target to a tracking-list and initialize the tracker with a know bounding box that surrounding the target
@param image The initial frame @param image The initial frame
@param boundingBox The initial boundig box of target @param boundingBox The initial boundig box of target
@param tracker_algorithm_name Multi-tracker algorithm name @param tracker_algorithm Multi-tracker algorithm
@return True if new target initialization went succesfully, false otherwise @return True if new target initialization went succesfully, false otherwise
*/ */
bool addTarget(const Mat& image, const Rect2d& boundingBox, String tracker_algorithm_name); bool addTarget(InputArray image, const Rect2d& boundingBox, Ptr<Tracker> tracker_algorithm);
/** @brief Update all trackers from the tracking-list, find a new most likely bounding boxes for the targets /** @brief Update all trackers from the tracking-list, find a new most likely bounding boxes for the targets
@param image The current frame @param image The current frame
...@@ -1397,7 +1396,7 @@ public: ...@@ -1397,7 +1396,7 @@ public:
current frame. Note, that latter *does not* imply that tracker has failed, maybe target is indeed current frame. Note, that latter *does not* imply that tracker has failed, maybe target is indeed
missing from the frame (say, out of sight) missing from the frame (say, out of sight)
*/ */
bool update(const Mat& image); bool update(InputArray image);
/** @brief Current number of targets in tracking-list /** @brief Current number of targets in tracking-list
*/ */
...@@ -1441,7 +1440,7 @@ public: ...@@ -1441,7 +1440,7 @@ public:
current frame. Note, that latter *does not* imply that tracker has failed, maybe target is indeed current frame. Note, that latter *does not* imply that tracker has failed, maybe target is indeed
missing from the frame (say, out of sight) missing from the frame (say, out of sight)
*/ */
bool update_opt(const Mat& image); bool update_opt(InputArray image);
}; };
//! @} //! @}
......
...@@ -155,7 +155,7 @@ PERF_TEST_P(tracking, mil, testing::Combine(TESTSET_NAMES, SEGMENTS)) ...@@ -155,7 +155,7 @@ PERF_TEST_P(tracking, mil, testing::Combine(TESTSET_NAMES, SEGMENTS))
bool initialized = false; bool initialized = false;
vector<Rect> bbs; vector<Rect> bbs;
Ptr<Tracker> tracker = Tracker::create( "MIL" ); Ptr<Tracker> tracker = TrackerMIL::create();
string folder = TRACKING_DIR + "/" + video + "/" + FOLDER_IMG; string folder = TRACKING_DIR + "/" + video + "/" + FOLDER_IMG;
int numSegments = ( sizeof ( SEGMENTS)/sizeof(int) ); int numSegments = ( sizeof ( SEGMENTS)/sizeof(int) );
int endFrame = 0; int endFrame = 0;
...@@ -226,7 +226,7 @@ PERF_TEST_P(tracking, boosting, testing::Combine(TESTSET_NAMES, SEGMENTS)) ...@@ -226,7 +226,7 @@ PERF_TEST_P(tracking, boosting, testing::Combine(TESTSET_NAMES, SEGMENTS))
bool initialized = false; bool initialized = false;
vector<Rect> bbs; vector<Rect> bbs;
Ptr<Tracker> tracker = Tracker::create( "BOOSTING" ); Ptr<Tracker> tracker = TrackerBoosting::create();
string folder = TRACKING_DIR + "/" + video + "/" + FOLDER_IMG; string folder = TRACKING_DIR + "/" + video + "/" + FOLDER_IMG;
int numSegments = ( sizeof ( SEGMENTS)/sizeof(int) ); int numSegments = ( sizeof ( SEGMENTS)/sizeof(int) );
int endFrame = 0; int endFrame = 0;
...@@ -296,7 +296,7 @@ PERF_TEST_P(tracking, tld, testing::Combine(TESTSET_NAMES, SEGMENTS)) ...@@ -296,7 +296,7 @@ PERF_TEST_P(tracking, tld, testing::Combine(TESTSET_NAMES, SEGMENTS))
bool initialized = false; bool initialized = false;
vector<Rect> bbs; vector<Rect> bbs;
Ptr<Tracker> tracker = Tracker::create( "TLD" ); Ptr<Tracker> tracker = TrackerTLD::create();
string folder = TRACKING_DIR + "/" + video + "/" + FOLDER_IMG; string folder = TRACKING_DIR + "/" + video + "/" + FOLDER_IMG;
int numSegments = ( sizeof ( SEGMENTS)/sizeof(int) ); int numSegments = ( sizeof ( SEGMENTS)/sizeof(int) );
int endFrame = 0; int endFrame = 0;
...@@ -366,7 +366,7 @@ PERF_TEST_P(tracking, GOTURN, testing::Combine(TESTSET_NAMES, SEGMENTS)) ...@@ -366,7 +366,7 @@ PERF_TEST_P(tracking, GOTURN, testing::Combine(TESTSET_NAMES, SEGMENTS))
bool initialized = false; bool initialized = false;
vector<Rect> bbs; vector<Rect> bbs;
Ptr<Tracker> tracker = Tracker::create("GOTURN"); Ptr<Tracker> tracker = TrackerGOTURN::create();
string folder = TRACKING_DIR + "/" + video + "/" + FOLDER_IMG; string folder = TRACKING_DIR + "/" + video + "/" + FOLDER_IMG;
int numSegments = (sizeof(SEGMENTS) / sizeof(int)); int numSegments = (sizeof(SEGMENTS) / sizeof(int));
int endFrame = 0; int endFrame = 0;
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "opencv2/tracking.hpp" #include "opencv2/tracking.hpp"
#include "opencv2/videoio.hpp" #include "opencv2/videoio.hpp"
#include "opencv2/plot.hpp" #include "opencv2/plot.hpp"
#include "samples_utility.hpp"
#include <fstream> #include <fstream>
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
...@@ -75,10 +76,11 @@ const int LTRC_COUNT = 100; ...@@ -75,10 +76,11 @@ const int LTRC_COUNT = 100;
struct AlgoWrap struct AlgoWrap
{ {
AlgoWrap(const string &name_) AlgoWrap(const string &name_)
: tracker(Tracker::create(name_)), lastState(NotFound), name(name_), color(getNextColor()), : lastState(NotFound), name(name_), color(getNextColor()),
numTotal(0), numResponse(0), numPresent(0), numCorrect_0(0), numCorrect_0_5(0), numTotal(0), numResponse(0), numPresent(0), numCorrect_0(0), numCorrect_0_5(0),
timeTotal(0), auc(LTRC_COUNT + 1, 0) timeTotal(0), auc(LTRC_COUNT + 1, 0)
{ {
tracker = createTrackerByName(name);
} }
enum State enum State
......
...@@ -140,7 +140,7 @@ int main(int argc, char *argv[]) ...@@ -140,7 +140,7 @@ int main(int argc, char *argv[])
setMouseCallback("GOTURN Tracking", onMouse, 0); setMouseCallback("GOTURN Tracking", onMouse, 0);
//Create GOTURN tracker //Create GOTURN tracker
Ptr<Tracker> tracker = Tracker::create("GOTURN"); Ptr<Tracker> tracker = TrackerGOTURN::create();
//Load and init full ALOV300++ dataset with a given datasetID, as alternative you can use loadAnnotatedOnly(..) //Load and init full ALOV300++ dataset with a given datasetID, as alternative you can use loadAnnotatedOnly(..)
//to load only frames with labled ground truth ~ every 5-th frame //to load only frames with labled ground truth ~ every 5-th frame
......
...@@ -52,7 +52,7 @@ int main( int argc, char** argv ){ ...@@ -52,7 +52,7 @@ int main( int argc, char** argv ){
BoxExtractor box; BoxExtractor box;
// create the tracker // create the tracker
Ptr<Tracker> tracker = Tracker::create( "KCF" ); Ptr<Tracker> tracker = TrackerKCF::create();
// set input video // set input video
std::string video = argv[1]; std::string video = argv[1];
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include <opencv2/tracking.hpp> #include <opencv2/tracking.hpp>
#include <opencv2/videoio.hpp> #include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp> #include <opencv2/highgui.hpp>
#include "samples_utility.hpp"
#include <iostream> #include <iostream>
using namespace std; using namespace std;
...@@ -184,7 +185,7 @@ int main(int argc, char *argv[]) ...@@ -184,7 +185,7 @@ int main(int argc, char *argv[])
//Initialize the tracker and add targets //Initialize the tracker and add targets
for (int i = 0; i < (int)boundingBoxes.size(); i++) for (int i = 0; i < (int)boundingBoxes.size(); i++)
{ {
if (!mt.addTarget(frame, boundingBoxes[i], tracker_algorithm)) if (!mt.addTarget(frame, boundingBoxes[i], createTrackerByName(tracker_algorithm)))
{ {
cout << "Trackers Init Error!!!"; cout << "Trackers Init Error!!!";
return 0; return 0;
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <iostream> #include <iostream>
#include <cstring> #include <cstring>
#include <ctime> #include <ctime>
#include "roiSelector.hpp" #include "samples_utility.hpp"
#ifdef HAVE_OPENCV #ifdef HAVE_OPENCV
#include <opencv2/flann.hpp> #include <opencv2/flann.hpp>
...@@ -62,38 +62,46 @@ int main( int argc, char** argv ){ ...@@ -62,38 +62,46 @@ int main( int argc, char** argv ){
// for showing the speed // for showing the speed
double fps; double fps;
std::string text; String text;
char buffer [50]; char buffer [50];
// set the default tracking algorithm // set the default tracking algorithm
std::string trackingAlg = "KCF"; String trackingAlg = "KCF";
// set the tracking algorithm from parameter // set the tracking algorithm from parameter
if(argc>2) if(argc>2)
trackingAlg = argv[2]; trackingAlg = argv[2];
// create the tracker // create the tracker
MultiTracker trackers(trackingAlg); MultiTracker trackers;
// container of the tracked objects // container of the tracked objects
vector<Rect> ROIs;
vector<Rect2d> objects; vector<Rect2d> objects;
// set input video // set input video
std::string video = argv[1]; String video = argv[1];
VideoCapture cap(video); VideoCapture cap(video);
Mat frame; Mat frame;
// get bounding box // get bounding box
cap >> frame; cap >> frame;
selectROI("tracker",frame,objects); selectROIs("tracker",frame,ROIs);
//quit when the tracked object(s) is not provided //quit when the tracked object(s) is not provided
if(objects.size()<1) if(objects.size()<1)
return 0; return 0;
std::vector<Ptr<Tracker> > algorithms;
for (size_t i = 0; i < ROIs.size(); i++)
{
algorithms.push_back(createTrackerByName(trackingAlg));
objects.push_back(ROIs[i]);
}
// initialize the tracker // initialize the tracker
trackers.add(frame,objects); trackers.add(algorithms,frame,objects);
// do the tracking // do the tracking
printf(GREEN "Start the tracking process, press ESC to quit.\n" RESET); printf(GREEN "Start the tracking process, press ESC to quit.\n" RESET);
...@@ -128,8 +136,8 @@ int main( int argc, char** argv ){ ...@@ -128,8 +136,8 @@ int main( int argc, char** argv ){
#endif #endif
// draw the tracked object // draw the tracked object
for(unsigned i=0;i<trackers.objects.size();i++) for(unsigned i=0;i<trackers.getObjects().size();i++)
rectangle( frame, trackers.objects[i], Scalar( 255, 0, 0 ), 2, 1 ); rectangle( frame, trackers.getObjects()[i], Scalar( 255, 0, 0 ), 2, 1 );
// draw the processing speed // draw the processing speed
sprintf (buffer, "speed: %.0f fps", fps); sprintf (buffer, "speed: %.0f fps", fps);
......
import numpy as np import numpy as np
import cv2 import cv2
import sys
if len(sys.argv) != 2:
print('Input video name is missing')
exit()
print('Select 3 tracking targets')
cv2.namedWindow("tracking") cv2.namedWindow("tracking")
camera = cv2.VideoCapture("E:/code/opencv/samples/data/768x576.avi") camera = cv2.VideoCapture(sys.argv[1])
tracker = cv2.MultiTracker("MIL") tracker = cv2.MultiTracker_create()
bbox1 = (638.0,230.0,56.0,101.0)
bbox2 = (240.0,210.0,60.0,104.0)
bbox3 = (486.0,149.0,54.0,83.0)
init_once = False init_once = False
ok, image=camera.read()
if not ok:
print('Failed to read video')
exit()
bbox1 = cv2.selectROI('tracking', image)
bbox2 = cv2.selectROI('tracking', image)
bbox3 = cv2.selectROI('tracking', image)
while camera.isOpened(): while camera.isOpened():
ok, image=camera.read() ok, image=camera.read()
if not ok: if not ok:
print 'no image read' print 'no image to read'
break break
if not init_once: if not init_once:
# add a list of boxes: ok = tracker.add(cv2.TrackerMIL_create(), image, bbox1)
ok = tracker.add(image, (bbox1,bbox2)) ok = tracker.add(cv2.TrackerMIL_create(), image, bbox2)
# or add single box: ok = tracker.add(cv2.TrackerMIL_create(), image, bbox3)
ok = tracker.add(image, bbox3)
init_once = True init_once = True
ok, boxes = tracker.update(image) ok, boxes = tracker.update(image)
...@@ -30,6 +42,6 @@ while camera.isOpened(): ...@@ -30,6 +42,6 @@ while camera.isOpened():
p2 = (int(newbox[0] + newbox[2]), int(newbox[1] + newbox[3])) p2 = (int(newbox[0] + newbox[2]), int(newbox[1] + newbox[3]))
cv2.rectangle(image, p1, p2, (200,0,0)) cv2.rectangle(image, p1, p2, (200,0,0))
cv2.imshow("tracking", image) cv2.imshow('tracking', image)
k = cv2.waitKey(1) & 0xff k = cv2.waitKey(1)
if k == 27 : break # esc pressed if k == 27 : break # esc pressed
#ifndef _ROISELECTOR_HPP_
#define _ROISELECTOR_HPP_
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
cv::Rect2d selectROI(cv::Mat img, bool fromCenter = true);
cv::Rect2d selectROI(const cv::String& windowName, cv::Mat img, bool showCrossair = true, bool fromCenter = true);
void selectROI(const cv::String& windowName, cv::Mat img, std::vector<cv::Rect2d> & boundingBox, bool fromCenter = true);
//==================================================================================================
class ROISelector
{
public:
cv::Rect2d select(cv::Mat img, bool fromCenter = true)
{
return select("ROI selector", img, fromCenter);
}
cv::Rect2d select(const cv::String &windowName, cv::Mat img, bool showCrossair = true, bool fromCenter = true)
{
key = 0;
// set the drawing mode
selectorParams.drawFromCenter = fromCenter;
// show the image and give feedback to user
cv::imshow(windowName, img);
// copy the data, rectangle should be drawn in the fresh image
selectorParams.image = img.clone();
// select the object
cv::setMouseCallback(windowName, mouseHandler, (void *)&selectorParams);
// end selection process on SPACE (32) ESC (27) or ENTER (13)
while (!(key == 32 || key == 27 || key == 13))
{
// draw the selected object
cv::rectangle(selectorParams.image, selectorParams.box, cv::Scalar(255, 0, 0), 2, 1);
// draw cross air in the middle of bounding box
if (showCrossair)
{
// horizontal line
cv::line(selectorParams.image,
cv::Point((int)selectorParams.box.x,
(int)(selectorParams.box.y + selectorParams.box.height / 2)),
cv::Point((int)(selectorParams.box.x + selectorParams.box.width),
(int)(selectorParams.box.y + selectorParams.box.height / 2)),
cv::Scalar(255, 0, 0), 2, 1);
// vertical line
cv::line(selectorParams.image,
cv::Point((int)(selectorParams.box.x + selectorParams.box.width / 2),
(int)selectorParams.box.y),
cv::Point((int)(selectorParams.box.x + selectorParams.box.width / 2),
(int)(selectorParams.box.y + selectorParams.box.height)),
cv::Scalar(255, 0, 0), 2, 1);
}
// show the image bouding box
cv::imshow(windowName, selectorParams.image);
// reset the image
selectorParams.image = img.clone();
// get keyboard event, extract lower 8 bits for scancode comparison
key = cv::waitKey(1) & 0xFF;
}
return selectorParams.box;
}
void select(const cv::String &windowName, cv::Mat img, std::vector<cv::Rect2d> &boundingBox, bool fromCenter = true)
{
std::vector<cv::Rect2d> box;
cv::Rect2d temp;
key = 0;
// show notice to user
printf("Select an object to track and then press SPACE or ENTER button!\n");
printf("Finish the selection process by pressing ESC button!\n");
// while key is not ESC (27)
for (;;)
{
temp = select(windowName, img, true, fromCenter);
if (key == 27)
break;
if (temp.width > 0 && temp.height > 0)
box.push_back(temp);
}
boundingBox = box;
}
struct handlerT
{
// basic parameters
bool isDrawing;
cv::Rect2d box;
cv::Mat image;
// parameters for drawing from the center
bool drawFromCenter;
cv::Point2f center;
// initializer list
handlerT() : isDrawing(false), drawFromCenter(true){};
} selectorParams;
// to store the tracked objects
std::vector<handlerT> objects;
private:
static void mouseHandler(int event, int x, int y, int flags, void *param)
{
ROISelector *self = static_cast<ROISelector *>(param);
self->opencv_mouse_callback(event, x, y, flags, param);
}
void opencv_mouse_callback(int event, int x, int y, int, void *param)
{
handlerT *data = (handlerT *)param;
switch (event)
{
// update the selected bounding box
case cv::EVENT_MOUSEMOVE:
if (data->isDrawing)
{
if (data->drawFromCenter)
{
data->box.width = 2 * (x - data->center.x) /*data->box.x*/;
data->box.height = 2 * (y - data->center.y) /*data->box.y*/;
data->box.x = data->center.x - data->box.width / 2.0;
data->box.y = data->center.y - data->box.height / 2.0;
}
else
{
data->box.width = x - data->box.x;
data->box.height = y - data->box.y;
}
}
break;
// start to select the bounding box
case cv::EVENT_LBUTTONDOWN:
data->isDrawing = true;
data->box = cv::Rect2d(x, y, 0, 0);
data->center = cv::Point2f((float)x, (float)y);
break;
// cleaning up the selected bounding box
case cv::EVENT_LBUTTONUP:
data->isDrawing = false;
if (data->box.width < 0)
{
data->box.x += data->box.width;
data->box.width *= -1;
}
if (data->box.height < 0)
{
data->box.y += data->box.height;
data->box.height *= -1;
}
break;
}
}
// save the keypressed characted
int key;
};
//==================================================================================================
static ROISelector _selector;
cv::Rect2d selectROI(cv::Mat img, bool fromCenter)
{
return _selector.select("ROI selector", img, true, fromCenter);
};
cv::Rect2d selectROI(const cv::String &windowName, cv::Mat img, bool showCrossair, bool fromCenter)
{
printf("Select an object to track and then press SPACE or ENTER button!\n");
return _selector.select(windowName, img, showCrossair, fromCenter);
};
void selectROI(const cv::String &windowName, cv::Mat img, std::vector<cv::Rect2d> &boundingBox, bool fromCenter)
{
return _selector.select(windowName, img, boundingBox, fromCenter);
}
#endif // _ROISELECTOR_HPP_
#ifndef _SAMPLES_UTILITY_HPP_
#define _SAMPLES_UTILITY_HPP_
#include <opencv2/tracking.hpp>
inline cv::Ptr<cv::Tracker> createTrackerByName(cv::String name)
{
cv::Ptr<cv::Tracker> tracker;
if (name == "KCF")
tracker = cv::TrackerKCF::create();
else if (name == "TLD")
tracker = cv::TrackerTLD::create();
else if (name == "BOOSTING")
tracker = cv::TrackerBoosting::create();
else if (name == "MEDIAN_FLOW")
tracker = cv::TrackerMedianFlow::create();
else if (name == "MIL")
tracker = cv::TrackerMIL::create();
else if (name == "GOTURN")
tracker = cv::TrackerGOTURN::create();
else
CV_Error(cv::Error::StsBadArg, "Invalid tracking algorithm name\n");
return tracker;
}
#endif
...@@ -4,56 +4,17 @@ ...@@ -4,56 +4,17 @@
#include <opencv2/highgui.hpp> #include <opencv2/highgui.hpp>
#include <iostream> #include <iostream>
#include <cstring> #include <cstring>
#include "samples_utility.hpp"
using namespace std; using namespace std;
using namespace cv; using namespace cv;
static Mat image;
static Rect2d boundingBox;
static bool paused;
static bool selectObject = false;
static bool startSelection = false;
static const char* keys = static const char* keys =
{ "{@tracker_algorithm | | Tracker algorithm }" { "{@tracker_algorithm | | Tracker algorithm }"
"{@video_name | | video name }" "{@video_name | | video name }"
"{@start_frame |0| Start frame }" "{@start_frame |0| Start frame }"
"{@bounding_frame |0,0,0,0| Initial bounding frame}"}; "{@bounding_frame |0,0,0,0| Initial bounding frame}"};
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;
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;
}
}
}
static void help() static void help()
{ {
cout << "\nThis example shows the functionality of \"Long-term optical tracking API\"" cout << "\nThis example shows the functionality of \"Long-term optical tracking API\""
...@@ -124,12 +85,14 @@ int main( int argc, char** argv ){ ...@@ -124,12 +85,14 @@ int main( int argc, char** argv ){
} }
Mat frame; Mat frame;
paused = true;
namedWindow( "Tracking API", 1 ); namedWindow( "Tracking API", 1 );
setMouseCallback( "Tracking API", onMouse, 0 );
Mat image;
Rect2d boundingBox;
bool paused = false;
//instantiates the specific Tracker //instantiates the specific Tracker
Ptr<Tracker> tracker = Tracker::create( tracker_algorithm ); Ptr<Tracker> tracker = createTrackerByName(tracker_algorithm);
if( tracker == NULL ) if( tracker == NULL )
{ {
cout << "***Error in the instantiation of the tracker...***\n"; cout << "***Error in the instantiation of the tracker...***\n";
...@@ -140,8 +103,6 @@ int main( int argc, char** argv ){ ...@@ -140,8 +103,6 @@ int main( int argc, char** argv ){
cap >> frame; cap >> frame;
frame.copyTo( image ); frame.copyTo( image );
if(initBoxWasGivenInCommandLine){ if(initBoxWasGivenInCommandLine){
selectObject=true;
paused=false;
boundingBox.x = coords[0]; boundingBox.x = coords[0];
boundingBox.y = coords[1]; boundingBox.y = coords[1];
boundingBox.width = std::abs( coords[2] - coords[0] ); boundingBox.width = std::abs( coords[2] - coords[0] );
...@@ -149,6 +110,9 @@ int main( int argc, char** argv ){ ...@@ -149,6 +110,9 @@ int main( int argc, char** argv ){
printf("bounding box with vertices (%d,%d) and (%d,%d) was given in command line\n",coords[0],coords[1],coords[2],coords[3]); printf("bounding box with vertices (%d,%d) and (%d,%d) was given in command line\n",coords[0],coords[1],coords[2],coords[3]);
rectangle( image, boundingBox, Scalar( 255, 0, 0 ), 2, 1 ); rectangle( image, boundingBox, Scalar( 255, 0, 0 ), 2, 1 );
} }
else
boundingBox = selectROI("Tracking API", image);
imshow( "Tracking API", image ); imshow( "Tracking API", image );
bool initialized = false; bool initialized = false;
...@@ -166,7 +130,7 @@ int main( int argc, char** argv ){ ...@@ -166,7 +130,7 @@ int main( int argc, char** argv ){
frame.copyTo( image ); frame.copyTo( image );
} }
if( !initialized && selectObject ) if( !initialized )
{ {
//initializes the tracker //initializes the tracker
if( !tracker->init( frame, boundingBox ) ) if( !tracker->init( frame, boundingBox ) )
...@@ -193,7 +157,6 @@ int main( int argc, char** argv ){ ...@@ -193,7 +157,6 @@ int main( int argc, char** argv ){
break; break;
if( c == 'p' ) if( c == 'p' )
paused = !paused; paused = !paused;
} }
return 0; return 0;
......
import numpy as np import numpy as np
import cv2 import cv2
import sys
if len(sys.argv) != 2:
print('Input video name is missing')
exit()
cv2.namedWindow("tracking") cv2.namedWindow("tracking")
camera = cv2.VideoCapture("E:/code/opencv/samples/data/768x576.avi") camera = cv2.VideoCapture(sys.argv[1])
bbox = (638.0,230.0,56.0,101.0) ok, image=camera.read()
tracker = cv2.Tracker_create("MIL") if not ok:
print('Failed to read video')
exit()
bbox = cv2.selectROI("tracking", image)
tracker = cv2.TrackerMIL_create()
init_once = False init_once = False
while camera.isOpened(): while camera.isOpened():
ok, image=camera.read() ok, image=camera.read()
if not ok: if not ok:
print 'no image read' print 'no image to read'
break break
if not init_once: if not init_once:
...@@ -27,4 +36,4 @@ while camera.isOpened(): ...@@ -27,4 +36,4 @@ while camera.isOpened():
cv2.imshow("tracking", image) cv2.imshow("tracking", image)
k = cv2.waitKey(1) & 0xff k = cv2.waitKey(1) & 0xff
if k == 27 : break # esc pressed if k == 27 : break # esc pressed
\ No newline at end of file
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
#include <opencv2/videoio.hpp> #include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp> #include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp> #include <opencv2/imgproc.hpp>
#include "samples_utility.hpp"
#include <iostream> #include <iostream>
...@@ -143,7 +144,7 @@ int main(int argc, char *argv[]) ...@@ -143,7 +144,7 @@ int main(int argc, char *argv[])
setMouseCallback("Tracking API", onMouse, 0); setMouseCallback("Tracking API", onMouse, 0);
//Create Tracker //Create Tracker
Ptr<Tracker> tracker = Tracker::create(tracker_algorithm); Ptr<Tracker> tracker = createTrackerByName(tracker_algorithm);
if (tracker == NULL) if (tracker == NULL)
{ {
cout << "***Error in the instantiation of the tracker...***\n"; cout << "***Error in the instantiation of the tracker...***\n";
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#include <opencv2/highgui.hpp> #include <opencv2/highgui.hpp>
#include <iostream> #include <iostream>
#include <cstring> #include <cstring>
#include "roiSelector.hpp" #include "samples_utility.hpp"
using namespace std; using namespace std;
using namespace cv; using namespace cv;
...@@ -38,7 +38,7 @@ int main( int argc, char** argv ){ ...@@ -38,7 +38,7 @@ int main( int argc, char** argv ){
// create a tracker object // create a tracker object
//! [create] //! [create]
Ptr<TrackerKCF> tracker = TrackerKCF::createTracker(param); Ptr<TrackerKCF> tracker = TrackerKCF::create(param);
//! [create] //! [create]
//! [setextractor] //! [setextractor]
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#include <opencv2/highgui.hpp> #include <opencv2/highgui.hpp>
#include <iostream> #include <iostream>
#include <cstring> #include <cstring>
#include "roiSelector.hpp"
using namespace std; using namespace std;
using namespace cv; using namespace cv;
...@@ -31,7 +30,7 @@ int main( int argc, char** argv ){ ...@@ -31,7 +30,7 @@ int main( int argc, char** argv ){
// create a tracker object // create a tracker object
//! [create] //! [create]
Ptr<Tracker> tracker = Tracker::create( "KCF" ); Ptr<Tracker> tracker = TrackerKCF::create();
//! [create] //! [create]
// set input video // set input video
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#include <iostream> #include <iostream>
#include <cstring> #include <cstring>
#include <ctime> #include <ctime>
#include "roiSelector.hpp" #include "samples_utility.hpp"
using namespace std; using namespace std;
using namespace cv; using namespace cv;
...@@ -40,7 +40,7 @@ int main( int argc, char** argv ){ ...@@ -40,7 +40,7 @@ int main( int argc, char** argv ){
// create the tracker // create the tracker
//! [create] //! [create]
MultiTracker trackers(trackingAlg); MultiTracker trackers;
//! [create] //! [create]
// container of the tracked objects // container of the tracked objects
...@@ -57,7 +57,8 @@ int main( int argc, char** argv ){ ...@@ -57,7 +57,8 @@ int main( int argc, char** argv ){
// get bounding box // get bounding box
cap >> frame; cap >> frame;
//! [selectmulti] //! [selectmulti]
selectROI("tracker",frame,objects); vector<Rect> ROIs;
selectROIs("tracker",frame,ROIs);
//! [selectmulti] //! [selectmulti]
//quit when the tracked object(s) is not provided //quit when the tracked object(s) is not provided
...@@ -66,7 +67,14 @@ int main( int argc, char** argv ){ ...@@ -66,7 +67,14 @@ int main( int argc, char** argv ){
// initialize the tracker // initialize the tracker
//! [init] //! [init]
trackers.add(frame,objects); std::vector<Ptr<Tracker> > algorithms;
for (size_t i = 0; i < objects.size(); i++)
{
algorithms.push_back(createTrackerByName(trackingAlg));
objects.push_back(ROIs[i]);
}
trackers.add(algorithms,frame,objects);
//! [init] //! [init]
// do the tracking // do the tracking
...@@ -86,8 +94,8 @@ int main( int argc, char** argv ){ ...@@ -86,8 +94,8 @@ int main( int argc, char** argv ){
//! [result] //! [result]
// draw the tracked object // draw the tracked object
for(unsigned i=0;i<trackers.objects.size();i++) for(unsigned i=0;i<trackers.getObjects().size();i++)
rectangle( frame, trackers.objects[i], Scalar( 255, 0, 0 ), 2, 1 ); rectangle( frame, trackers.getObjects()[i], Scalar( 255, 0, 0 ), 2, 1 );
//! [result] //! [result]
// show image with the tracked object // show image with the tracked object
......
...@@ -52,7 +52,7 @@ void TrackerGOTURN::Params::read(const cv::FileNode& /*fn*/){} ...@@ -52,7 +52,7 @@ void TrackerGOTURN::Params::read(const cv::FileNode& /*fn*/){}
void TrackerGOTURN::Params::write(cv::FileStorage& /*fs*/) const {} void TrackerGOTURN::Params::write(cv::FileStorage& /*fs*/) const {}
Ptr<TrackerGOTURN> TrackerGOTURN::createTracker(const TrackerGOTURN::Params &parameters) Ptr<TrackerGOTURN> TrackerGOTURN::create(const TrackerGOTURN::Params &parameters)
{ {
#ifdef HAVE_OPENCV_DNN #ifdef HAVE_OPENCV_DNN
return Ptr<gtr::TrackerGOTURNImpl>(new gtr::TrackerGOTURNImpl(parameters)); return Ptr<gtr::TrackerGOTURNImpl>(new gtr::TrackerGOTURNImpl(parameters));
...@@ -61,6 +61,10 @@ Ptr<TrackerGOTURN> TrackerGOTURN::createTracker(const TrackerGOTURN::Params &par ...@@ -61,6 +61,10 @@ Ptr<TrackerGOTURN> TrackerGOTURN::createTracker(const TrackerGOTURN::Params &par
CV_ErrorNoReturn(cv::Error::StsNotImplemented , "to use GOTURN, the tracking module needs to be built with opencv_dnn !"); CV_ErrorNoReturn(cv::Error::StsNotImplemented , "to use GOTURN, the tracking module needs to be built with opencv_dnn !");
#endif #endif
} }
Ptr<TrackerGOTURN> TrackerGOTURN::create()
{
return TrackerGOTURN::create(TrackerGOTURN::Params());
}
#ifdef HAVE_OPENCV_DNN #ifdef HAVE_OPENCV_DNN
......
...@@ -44,9 +44,9 @@ ...@@ -44,9 +44,9 @@
namespace cv namespace cv
{ {
//Multitracker //Multitracker
bool MultiTracker_Alt::addTarget(const Mat& image, const Rect2d& boundingBox, String tracker_algorithm_name) bool MultiTracker_Alt::addTarget(InputArray image, const Rect2d& boundingBox, Ptr<Tracker> tracker_algorithm)
{ {
Ptr<Tracker> tracker = Tracker::create(tracker_algorithm_name); Ptr<Tracker> tracker = tracker_algorithm;
if (tracker == NULL) if (tracker == NULL)
return false; return false;
...@@ -73,7 +73,7 @@ namespace cv ...@@ -73,7 +73,7 @@ namespace cv
return true; return true;
} }
bool MultiTracker_Alt::update(const Mat& image) bool MultiTracker_Alt::update(InputArray image)
{ {
for (int i = 0; i < (int)trackers.size(); i++) for (int i = 0; i < (int)trackers.size(); i++)
if (!trackers[i]->update(image, boundingBoxes[i])) if (!trackers[i]->update(image, boundingBoxes[i]))
...@@ -84,8 +84,9 @@ namespace cv ...@@ -84,8 +84,9 @@ namespace cv
//Multitracker TLD //Multitracker TLD
/*Optimized update method for TLD Multitracker */ /*Optimized update method for TLD Multitracker */
bool MultiTrackerTLD::update_opt(const Mat& image) bool MultiTrackerTLD::update_opt(InputArray _image)
{ {
Mat image = _image.getMat();
//Get parameters from first object //Get parameters from first object
//TLD Tracker data extraction //TLD Tracker data extraction
Tracker* trackerPtr = trackers[0]; Tracker* trackerPtr = trackers[0];
...@@ -99,7 +100,7 @@ namespace cv ...@@ -99,7 +100,7 @@ namespace cv
cvtColor(image, image_gray, COLOR_BGR2GRAY); cvtColor(image, image_gray, COLOR_BGR2GRAY);
if (scale > 1.0) if (scale > 1.0)
resize(image_gray, imageForDetector, Size(cvRound(image.cols*scale), cvRound(image.rows*scale)), 0, 0, tld::DOWNSCALE_MODE); resize(image_gray, imageForDetector, Size(cvRound(image_gray.cols*scale), cvRound(image_gray.rows*scale)), 0, 0, tld::DOWNSCALE_MODE);
else else
imageForDetector = image_gray; imageForDetector = image_gray;
GaussianBlur(imageForDetector, image_blurred, tld::GaussBlurKernelSize, 0.0); GaussianBlur(imageForDetector, image_blurred, tld::GaussBlurKernelSize, 0.0);
...@@ -653,4 +654,4 @@ namespace cv ...@@ -653,4 +654,4 @@ namespace cv
} }
#endif #endif
} }
\ No newline at end of file
...@@ -44,29 +44,15 @@ ...@@ -44,29 +44,15 @@
namespace cv { namespace cv {
// constructor // constructor
MultiTracker::MultiTracker(const String& trackerType):defaultAlgorithm(trackerType){}; MultiTracker::MultiTracker(){};
// destructor // destructor
MultiTracker::~MultiTracker(){}; MultiTracker::~MultiTracker(){};
// add an object to be tracked, defaultAlgorithm is used
bool MultiTracker::add(const Mat& image, const Rect2d& boundingBox){
// quit if defaultAlgorithm has not been configured
if(defaultAlgorithm==""){
printf("Default algorithm was not defined!\n");
return false;
}
// add a new tracked object
return add(defaultAlgorithm.c_str(), image, boundingBox);
};
// add a new tracked object // add a new tracked object
bool MultiTracker::add( const String& trackerType, const Mat& image, const Rect2d& boundingBox ){ bool MultiTracker::add( Ptr<Tracker> newTracker, InputArray image, const Rect2d& boundingBox )
// declare a new tracker {
Ptr<Tracker> newTracker = Tracker::create( trackerType ); // add the tracker algorithm to the trackers list
// add the created tracker algorithm to the trackers list
trackerList.push_back(newTracker); trackerList.push_back(newTracker);
// add the ROI to the bounding box list // add the ROI to the bounding box list
...@@ -77,13 +63,13 @@ namespace cv { ...@@ -77,13 +63,13 @@ namespace cv {
}; };
// add a set of objects to be tracked // add a set of objects to be tracked
bool MultiTracker::add(const String& trackerType, const Mat& image, std::vector<Rect2d> boundingBox){ bool MultiTracker::add(std::vector<Ptr<Tracker> > newTrackers, InputArray image, std::vector<Rect2d> boundingBox){
// status of the tracker addition // status of the tracker addition
bool stat=false; bool stat=false;
// add tracker for all input objects // add tracker for all input objects
for(unsigned i =0;i<boundingBox.size();i++){ for(unsigned i =0;i<boundingBox.size();i++){
stat=add(trackerType,image,boundingBox[i]); stat=add(newTrackers[i],image,boundingBox[i]);
if(!stat)break; if(!stat)break;
} }
...@@ -91,30 +77,32 @@ namespace cv { ...@@ -91,30 +77,32 @@ namespace cv {
return stat; return stat;
}; };
// add a set of object to be tracked, defaultAlgorithm is used.
bool MultiTracker::add(const Mat& image, std::vector<Rect2d> boundingBox){
// quit if defaultAlgorithm has not been configured
if(defaultAlgorithm==""){
printf("Default algorithm was not defined!\n");
return false;
}
return add(defaultAlgorithm.c_str(), image, boundingBox);
};
// update position of the tracked objects, the result is stored in internal storage // update position of the tracked objects, the result is stored in internal storage
bool MultiTracker::update( const Mat& image){ bool MultiTracker::update(InputArray image)
{
bool status = true;
for(unsigned i=0;i< trackerList.size(); i++){ for(unsigned i=0;i< trackerList.size(); i++){
trackerList[i]->update(image, objects[i]); status &= trackerList[i]->update(image, objects[i]);
} }
return true; return status;
}; };
// update position of the tracked objects, the result is copied to external variable // update position of the tracked objects, the result is copied to external variable
bool MultiTracker::update( const Mat& image, std::vector<Rect2d> & boundingBox ){ bool MultiTracker::update(InputArray image, std::vector<Rect2d> & boundingBox )
update(image); {
bool status = update(image);
boundingBox=objects; boundingBox=objects;
return true; return status;
}; };
} /* namespace cv */ const std::vector<Rect2d>& MultiTracker::getObjects() const
\ No newline at end of file {
return objects;
}
Ptr<MultiTracker> MultiTracker::create()
{
return makePtr<MultiTracker>();
}
} /* namespace cv */
...@@ -52,10 +52,14 @@ namespace cv ...@@ -52,10 +52,14 @@ namespace cv
void TrackerTLD::Params::write(cv::FileStorage& /*fs*/) const {} void TrackerTLD::Params::write(cv::FileStorage& /*fs*/) const {}
Ptr<TrackerTLD> TrackerTLD::createTracker(const TrackerTLD::Params &parameters) Ptr<TrackerTLD> TrackerTLD::create(const TrackerTLD::Params &parameters)
{ {
return Ptr<tld::TrackerTLDImpl>(new tld::TrackerTLDImpl(parameters)); return Ptr<tld::TrackerTLDImpl>(new tld::TrackerTLDImpl(parameters));
} }
Ptr<TrackerTLD> TrackerTLD::create()
{
return Ptr<tld::TrackerTLDImpl>(new tld::TrackerTLDImpl());
}
namespace tld namespace tld
{ {
......
...@@ -98,7 +98,7 @@ public: ...@@ -98,7 +98,7 @@ public:
TrackerProxyImpl(Tparams params = Tparams()) :params_(params){} TrackerProxyImpl(Tparams params = Tparams()) :params_(params){}
bool init(const Mat& image, const Rect2d& boundingBox) bool init(const Mat& image, const Rect2d& boundingBox)
{ {
trackerPtr = T::createTracker(); trackerPtr = T::create();
return trackerPtr->init(image, boundingBox); return trackerPtr->init(image, boundingBox);
} }
bool update(const Mat& image, Rect2d& boundingBox) bool update(const Mat& image, Rect2d& boundingBox)
......
...@@ -41,12 +41,6 @@ ...@@ -41,12 +41,6 @@
#include "precomp.hpp" #include "precomp.hpp"
#undef BOILERPLATE_CODE
#define BOILERPLATE_CODE(name,classname)\
if(trackerType==name){\
return classname::createTracker();\
}
namespace cv namespace cv
{ {
...@@ -58,7 +52,7 @@ Tracker::~Tracker() ...@@ -58,7 +52,7 @@ Tracker::~Tracker()
{ {
} }
bool Tracker::init( const Mat& image, const Rect2d& boundingBox ) bool Tracker::init( InputArray image, const Rect2d& boundingBox )
{ {
if( isInit ) if( isInit )
...@@ -73,7 +67,7 @@ bool Tracker::init( const Mat& image, const Rect2d& boundingBox ) ...@@ -73,7 +67,7 @@ bool Tracker::init( const Mat& image, const Rect2d& boundingBox )
featureSet = Ptr<TrackerFeatureSet>( new TrackerFeatureSet() ); featureSet = Ptr<TrackerFeatureSet>( new TrackerFeatureSet() );
model = Ptr<TrackerModel>(); model = Ptr<TrackerModel>();
bool initTracker = initImpl( image, boundingBox ); bool initTracker = initImpl( image.getMat(), boundingBox );
//check if the model component is initialized //check if the model component is initialized
if( model == 0 ) if( model == 0 )
...@@ -90,7 +84,7 @@ bool Tracker::init( const Mat& image, const Rect2d& boundingBox ) ...@@ -90,7 +84,7 @@ bool Tracker::init( const Mat& image, const Rect2d& boundingBox )
return initTracker; return initTracker;
} }
bool Tracker::update( const Mat& image, Rect2d& boundingBox ) bool Tracker::update( InputArray image, Rect2d& boundingBox )
{ {
if( !isInit ) if( !isInit )
...@@ -101,19 +95,7 @@ bool Tracker::update( const Mat& image, Rect2d& boundingBox ) ...@@ -101,19 +95,7 @@ bool Tracker::update( const Mat& image, Rect2d& boundingBox )
if( image.empty() ) if( image.empty() )
return false; return false;
return updateImpl( image, boundingBox ); return updateImpl( image.getMat(), boundingBox );
}
Ptr<Tracker> Tracker::create( const String& trackerType )
{
BOILERPLATE_CODE("MIL",TrackerMIL);
BOILERPLATE_CODE("BOOSTING",TrackerBoosting);
BOILERPLATE_CODE("MEDIANFLOW",TrackerMedianFlow);
BOILERPLATE_CODE("TLD",TrackerTLD);
BOILERPLATE_CODE("KCF",TrackerKCF);
BOILERPLATE_CODE("GOTURN", TrackerGOTURN);
return Ptr<Tracker>();
} }
} /* namespace cv */ } /* namespace cv */
...@@ -97,9 +97,12 @@ void TrackerBoosting::Params::write( cv::FileStorage& fs ) const ...@@ -97,9 +97,12 @@ void TrackerBoosting::Params::write( cv::FileStorage& fs ) const
/* /*
* Constructor * Constructor
*/ */
Ptr<TrackerBoosting> TrackerBoosting::createTracker(const TrackerBoosting::Params &parameters){ Ptr<TrackerBoosting> TrackerBoosting::create(const TrackerBoosting::Params &parameters){
return Ptr<TrackerBoostingImpl>(new TrackerBoostingImpl(parameters)); return Ptr<TrackerBoostingImpl>(new TrackerBoostingImpl(parameters));
} }
Ptr<TrackerBoosting> TrackerBoosting::create(){
return Ptr<TrackerBoostingImpl>(new TrackerBoostingImpl());
}
TrackerBoostingImpl::TrackerBoostingImpl( const TrackerBoostingImpl::Params &parameters ) : TrackerBoostingImpl::TrackerBoostingImpl( const TrackerBoostingImpl::Params &parameters ) :
params( parameters ) params( parameters )
{ {
......
...@@ -160,9 +160,12 @@ namespace cv{ ...@@ -160,9 +160,12 @@ namespace cv{
/* /*
* Constructor * Constructor
*/ */
Ptr<TrackerKCF> TrackerKCF::createTracker(const TrackerKCF::Params &parameters){ Ptr<TrackerKCF> TrackerKCF::create(const TrackerKCF::Params &parameters){
return Ptr<TrackerKCFImpl>(new TrackerKCFImpl(parameters)); return Ptr<TrackerKCFImpl>(new TrackerKCFImpl(parameters));
} }
Ptr<TrackerKCF> TrackerKCF::create(){
return Ptr<TrackerKCFImpl>(new TrackerKCFImpl());
}
TrackerKCFImpl::TrackerKCFImpl( const TrackerKCF::Params &parameters ) : TrackerKCFImpl::TrackerKCFImpl( const TrackerKCF::Params &parameters ) :
params( parameters ) params( parameters )
{ {
...@@ -894,7 +897,4 @@ namespace cv{ ...@@ -894,7 +897,4 @@ namespace cv{
fs << "compressed_size" << compressed_size; fs << "compressed_size" << compressed_size;
fs << "pca_learning_rate" << pca_learning_rate; fs << "pca_learning_rate" << pca_learning_rate;
} }
void TrackerKCF::setFeatureExtractor(void (*)(const Mat, const Rect, Mat&), bool ){};
} /* namespace cv */ } /* namespace cv */
...@@ -105,9 +105,12 @@ void TrackerMIL::Params::write( cv::FileStorage& fs ) const ...@@ -105,9 +105,12 @@ void TrackerMIL::Params::write( cv::FileStorage& fs ) const
/* /*
* Constructor * Constructor
*/ */
Ptr<TrackerMIL> TrackerMIL::createTracker(const TrackerMIL::Params &parameters){ Ptr<TrackerMIL> TrackerMIL::create(const TrackerMIL::Params &parameters){
return Ptr<TrackerMILImpl>(new TrackerMILImpl(parameters)); return Ptr<TrackerMILImpl>(new TrackerMILImpl(parameters));
} }
Ptr<TrackerMIL> TrackerMIL::create(){
return Ptr<TrackerMILImpl>(new TrackerMILImpl());
}
TrackerMILImpl::TrackerMILImpl( const TrackerMIL::Params &parameters ) : TrackerMILImpl::TrackerMILImpl( const TrackerMIL::Params &parameters ) :
params( parameters ) params( parameters )
{ {
......
...@@ -73,7 +73,7 @@ using namespace cv; ...@@ -73,7 +73,7 @@ using namespace cv;
class TrackerMedianFlowImpl : public TrackerMedianFlow{ class TrackerMedianFlowImpl : public TrackerMedianFlow{
public: public:
TrackerMedianFlowImpl(TrackerMedianFlow::Params paramsIn) {params=paramsIn;isInit=false;} TrackerMedianFlowImpl(TrackerMedianFlow::Params paramsIn = TrackerMedianFlow::Params()) {params=paramsIn;isInit=false;}
void read( const FileNode& fn ); void read( const FileNode& fn );
void write( FileStorage& fs ) const; void write( FileStorage& fs ) const;
private: private:
...@@ -482,8 +482,11 @@ void TrackerMedianFlow::Params::write( cv::FileStorage& fs ) const{ ...@@ -482,8 +482,11 @@ void TrackerMedianFlow::Params::write( cv::FileStorage& fs ) const{
fs << "maxMedianLengthOfDisplacementDifference" << maxMedianLengthOfDisplacementDifference; fs << "maxMedianLengthOfDisplacementDifference" << maxMedianLengthOfDisplacementDifference;
} }
Ptr<TrackerMedianFlow> TrackerMedianFlow::createTracker(const TrackerMedianFlow::Params &parameters){ Ptr<TrackerMedianFlow> TrackerMedianFlow::create(const TrackerMedianFlow::Params &parameters){
return Ptr<TrackerMedianFlowImpl>(new TrackerMedianFlowImpl(parameters)); return Ptr<TrackerMedianFlowImpl>(new TrackerMedianFlowImpl(parameters));
} }
Ptr<TrackerMedianFlow> TrackerMedianFlow::create(){
return Ptr<TrackerMedianFlowImpl>(new TrackerMedianFlowImpl());
}
} /* namespace cv */ } /* namespace cv */
...@@ -439,100 +439,100 @@ PARAM_TEST_CASE(DistanceAndOverlap, string) ...@@ -439,100 +439,100 @@ PARAM_TEST_CASE(DistanceAndOverlap, string)
TEST_P(DistanceAndOverlap, MedianFlow) TEST_P(DistanceAndOverlap, MedianFlow)
{ {
TrackerTest test( Tracker::create( "MEDIANFLOW" ), dataset, 35, .5f, NoTransform, 1, 1); TrackerTest test( TrackerMedianFlow::create(), dataset, 35, .5f, NoTransform, 1, 1);
test.run(); test.run();
} }
TEST_P(DistanceAndOverlap, MIL) TEST_P(DistanceAndOverlap, MIL)
{ {
TrackerTest test( Tracker::create( "MIL" ), dataset, 30, .65f, NoTransform); TrackerTest test( TrackerMIL::create(), dataset, 30, .65f, NoTransform);
test.run(); test.run();
} }
TEST_P(DistanceAndOverlap, Boosting) TEST_P(DistanceAndOverlap, Boosting)
{ {
TrackerTest test( Tracker::create( "BOOSTING" ), dataset, 70, .7f, NoTransform); TrackerTest test( TrackerBoosting::create(), dataset, 70, .7f, NoTransform);
test.run(); test.run();
} }
TEST_P(DistanceAndOverlap, KCF) TEST_P(DistanceAndOverlap, KCF)
{ {
TrackerTest test( Tracker::create( "KCF" ), dataset, 20, .35f, NoTransform, 5); TrackerTest test( TrackerKCF::create(), dataset, 20, .35f, NoTransform, 5);
test.run(); test.run();
} }
TEST_P(DistanceAndOverlap, DISABLED_TLD) TEST_P(DistanceAndOverlap, DISABLED_TLD)
{ {
TrackerTest test( Tracker::create( "TLD" ), dataset, 60, .4f, NoTransform); TrackerTest test( TrackerTLD::create(), dataset, 60, .4f, NoTransform);
test.run(); test.run();
} }
/***************************************************************************************/ /***************************************************************************************/
//Tests with shifted initial window //Tests with shifted initial window
TEST_P(DistanceAndOverlap, Shifted_Data_MedianFlow) TEST_P(DistanceAndOverlap, Shifted_Data_MedianFlow)
{ {
TrackerTest test( Tracker::create( "MEDIANFLOW" ), dataset, 80, .2f, CenterShiftLeft, 1, 1); TrackerTest test( TrackerMedianFlow::create(), dataset, 80, .2f, CenterShiftLeft, 1, 1);
test.run(); test.run();
} }
TEST_P(DistanceAndOverlap, Shifted_Data_MIL) TEST_P(DistanceAndOverlap, Shifted_Data_MIL)
{ {
TrackerTest test( Tracker::create( "MIL" ), dataset, 30, .6f, CenterShiftLeft); TrackerTest test( TrackerMIL::create(), dataset, 30, .6f, CenterShiftLeft);
test.run(); test.run();
} }
TEST_P(DistanceAndOverlap, Shifted_Data_Boosting) TEST_P(DistanceAndOverlap, Shifted_Data_Boosting)
{ {
TrackerTest test( Tracker::create( "BOOSTING" ), dataset, 80, .65f, CenterShiftLeft); TrackerTest test( TrackerBoosting::create(), dataset, 80, .65f, CenterShiftLeft);
test.run(); test.run();
} }
TEST_P(DistanceAndOverlap, Shifted_Data_KCF) TEST_P(DistanceAndOverlap, Shifted_Data_KCF)
{ {
TrackerTest test( Tracker::create( "KCF" ), dataset, 20, .4f, CenterShiftLeft, 5); TrackerTest test( TrackerKCF::create(), dataset, 20, .4f, CenterShiftLeft, 5);
test.run(); test.run();
} }
TEST_P(DistanceAndOverlap, DISABLED_Shifted_Data_TLD) TEST_P(DistanceAndOverlap, DISABLED_Shifted_Data_TLD)
{ {
TrackerTest test( Tracker::create( "TLD" ), dataset, 120, .2f, CenterShiftLeft); TrackerTest test( TrackerTLD::create(), dataset, 120, .2f, CenterShiftLeft);
test.run(); test.run();
} }
/***************************************************************************************/ /***************************************************************************************/
//Tests with scaled initial window //Tests with scaled initial window
TEST_P(DistanceAndOverlap, Scaled_Data_MedianFlow) TEST_P(DistanceAndOverlap, Scaled_Data_MedianFlow)
{ {
TrackerTest test( Tracker::create( "MEDIANFLOW" ), dataset, 25, .5f, Scale_1_1, 1, 1); TrackerTest test( TrackerMedianFlow::create(), dataset, 25, .5f, Scale_1_1, 1, 1);
test.run(); test.run();
} }
TEST_P(DistanceAndOverlap, Scaled_Data_MIL) TEST_P(DistanceAndOverlap, Scaled_Data_MIL)
{ {
TrackerTest test( Tracker::create( "MIL" ), dataset, 30, .7f, Scale_1_1); TrackerTest test( TrackerMIL::create(), dataset, 30, .7f, Scale_1_1);
test.run(); test.run();
} }
TEST_P(DistanceAndOverlap, Scaled_Data_Boosting) TEST_P(DistanceAndOverlap, Scaled_Data_Boosting)
{ {
TrackerTest test( Tracker::create( "BOOSTING" ), dataset, 80, .7f, Scale_1_1); TrackerTest test( TrackerBoosting::create(), dataset, 80, .7f, Scale_1_1);
test.run(); test.run();
} }
TEST_P(DistanceAndOverlap, Scaled_Data_KCF) TEST_P(DistanceAndOverlap, Scaled_Data_KCF)
{ {
TrackerTest test( Tracker::create( "KCF" ), dataset, 20, .4f, Scale_1_1, 5); TrackerTest test( TrackerKCF::create(), dataset, 20, .4f, Scale_1_1, 5);
test.run(); test.run();
} }
TEST_P(DistanceAndOverlap, DISABLED_Scaled_Data_TLD) TEST_P(DistanceAndOverlap, DISABLED_Scaled_Data_TLD)
{ {
TrackerTest test( Tracker::create( "TLD" ), dataset, 120, .45f, Scale_1_1); TrackerTest test( TrackerTLD::create(), dataset, 120, .45f, Scale_1_1);
test.run(); test.run();
} }
TEST_P(DistanceAndOverlap, DISABLED_GOTURN) TEST_P(DistanceAndOverlap, DISABLED_GOTURN)
{ {
TrackerTest test(Tracker::create("GOTURN"), dataset, 0, 100, NoTransform); TrackerTest test(TrackerGOTURN::create(), dataset, 0, 100, NoTransform);
test.run(); test.run();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment