Commit 1940c120 authored by Alex Leontiev's avatar Alex Leontiev

More abstract tracker declaration

This contribution changes the way how trackers should be implemented by
programmer. It should be noted first, that from the user prospective,
Tracker::create() method still can be called with the same effect.
However, there's no more thing as a "constructor" for Tracker, they
should be created via static functions, e.g.
    static Ptr<TrackerMIL> createTracker(const TrackerMIL::Params &parameters=TrackerMIL::Params());

From the programmer's perspective now for every tracker what is declared
in tracker.hpp header is more a "interface", while the real
implementation class can (and has to) be implemented in .cpp file.

Changes in documentation are also included.
parent bf93366d
...@@ -69,35 +69,57 @@ The following detector types are supported: ...@@ -69,35 +69,57 @@ The following detector types are supported:
Creating Own Tracker Creating Own Tracker
-------------------- --------------------
If you want create a new tracker, you should follow some simple rules. If you want create a new tracker, here's what you have to do. First, decide on the name of the class for the tracker (to meet the existing style,
we suggest something with prefix "tracker", e.g. trackerMIL, trackerBoosting) -- we shall refer to this choice as to "classname" in subsequent. Also,
First, your tracker should be inherit from :ocv:class:`Tracker`, so you must implement two method: you should decide upon the name of the tracker, is it will be known to user (the current style suggests using all capitals, say MIL or BOOSTING) --
we'll call it a "name".
* Tracker: initImpl, it should be called once in the first frame, here you should initialize all structures. The second argument is the initial bounding box of the target.
* Declare your tracker in ``include/opencv2/tracking/tracker.hpp``.
* Tracker:updateImpl, it should be called at the begin of in loop through video frames. Here you should overwrite the bounding box with new location. Your tracker should inherit from :ocv:class:`Tracker` (please, see the example below). You should declare the specialized ``Param``
structure, where you probably will want to put the data, needed to initialize your tracker. Also don't forget to put the
Example of creating specialized Tracker ``TrackerMIL`` : :: BOILERPLATE_CODE(name,classname) macro inside the class declaration. That macro will generate static ``createTracker()`` function, which
we'll talk about later. You should get something similar to ::
class CV_EXPORTS_W TrackerMIL : public Tracker
{ class CV_EXPORTS_W TrackerMIL : public Tracker
public: {
TrackerMIL( const TrackerMIL::Params &parameters = TrackerMIL::Params() ); public:
virtual ~TrackerMIL(); struct CV_EXPORTS Params
... {
Params();
//parameters for sampler
float samplerInitInRadius; // radius for gathering positive instances during init
int samplerInitMaxNegNum; // # negative samples to use during init
float samplerSearchWinSize; // size of search window
float samplerTrackInRadius; // radius for gathering positive instances during tracking
int samplerTrackMaxPosNum; // # positive samples to use during tracking
int samplerTrackMaxNegNum; // # negative samples to use during tracking
int featureSetNumFeatures; // #features
void read( const FileNode& fn );
void write( FileStorage& fs ) const;
};
of course, you can also add any additional methods of your choice. It should be pointed out, however, that it is not expected to have a constructor
declared, as creation should be done via the corresponding ``createTracker()`` method.
* In ``src/tracker.cpp`` file add BOILERPLATE_CODE(name,classname) line to the body of ``Tracker::create()`` method you will find there, like ::
Ptr<Tracker> Tracker::create( const String& trackerType )
{
BOILERPLATE_CODE("BOOSTING",TrackerBoosting);
BOILERPLATE_CODE("MIL",TrackerMIL);
return Ptr<Tracker>();
}
* Finally, you should implement the function with signature ::
protected: Ptr<classname> classname::createTracker(const classname::Params &parameters){
bool initImpl( const Mat& image, const Rect2d& boundingBox ); ...
bool updateImpl( const Mat& image, Rect2d& boundingBox ); }
...
};
That function can (and probably will) return a pointer to some derived class of "classname", which will probably have a real constructor.
Every tracker has three component :ocv:class:`TrackerSampler`, :ocv:class:`TrackerFeatureSet` and :ocv:class:`TrackerModel`. Every tracker has three component :ocv:class:`TrackerSampler`, :ocv:class:`TrackerFeatureSet` and :ocv:class:`TrackerModel`.
The first two are instantiated from Tracker base class, instead the last component is abstract, so you must implement your TrackerModel. The first two are instantiated from Tracker base class, instead the last component is abstract, so you must implement your TrackerModel.
Finally add your tracker in the file tracking_init.cpp
TrackerSampler TrackerSampler
.............. ..............
......
...@@ -20,19 +20,18 @@ The classifier uses the surrounding background as negative examples in update st ...@@ -20,19 +20,18 @@ The classifier uses the surrounding background as negative examples in update st
Implementation of TrackerBoosting from :ocv:class:`Tracker`:: Implementation of TrackerBoosting from :ocv:class:`Tracker`::
class CV_EXPORTS_W TrackerBoosting : public Tracker class CV_EXPORTS_W TrackerBoosting : public Tracker
{ {
public: public:
void read( const FileNode& fn );
TrackerBoosting( const TrackerBoosting::Params &parameters = TrackerBoosting::Params() ); void write( FileStorage& fs ) const;
static Ptr<trackerBoosting> createTracker(const trackerBoosting::Params &parameters=trackerBoosting::Params());
virtual ~TrackerBoosting(); virtual ~trackerBoosting(){};
void read( const FileNode& fn ); protected:
void write( FileStorage& fs ) const; bool initImpl( const Mat& image, const Rect2d& boundingBox );
bool updateImpl( const Mat& image, Rect2d& boundingBox );
};
};
TrackerBoosting::Params TrackerBoosting::Params
----------------------------------------------------------------------- -----------------------------------------------------------------------
...@@ -54,12 +53,12 @@ List of BOOSTING parameters:: ...@@ -54,12 +53,12 @@ List of BOOSTING parameters::
void write( FileStorage& fs ) const; void write( FileStorage& fs ) const;
}; };
TrackerBoosting::TrackerBoosting TrackerBoosting::createTracker
----------------------------------------------------------------------- -----------------------------------------------------------------------
Constructor Constructor
.. ocv:function:: bool TrackerBoosting::TrackerBoosting( const TrackerBoosting::Params &parameters = TrackerBoosting::Params() ) .. ocv:function:: Ptr<trackerBoosting> TrackerBoosting::createTracker(const trackerBoosting::Params &parameters=trackerBoosting::Params())
:param parameters: BOOSTING parameters :ocv:struct:`TrackerBoosting::Params` :param parameters: BOOSTING parameters :ocv:struct:`TrackerBoosting::Params`
...@@ -74,18 +73,18 @@ Original code can be found here http://vision.ucsd.edu/~bbabenko/project_miltrac ...@@ -74,18 +73,18 @@ Original code can be found here http://vision.ucsd.edu/~bbabenko/project_miltrac
Implementation of TrackerMIL from :ocv:class:`Tracker`:: Implementation of TrackerMIL from :ocv:class:`Tracker`::
class CV_EXPORTS_W TrackerMIL : public Tracker class CV_EXPORTS_W TrackerMIL : public Tracker
{ {
public: public:
void read( const FileNode& fn );
TrackerMIL( const TrackerMIL::Params &parameters = TrackerMIL::Params() ); void write( FileStorage& fs ) const;
static Ptr<trackerMIL> createTracker(const trackerMIL::Params &parameters=trackerMIL::Params());
virtual ~trackerMIL(){};
virtual ~TrackerMIL(); protected:
bool initImpl( const Mat& image, const Rect2d& boundingBox );
void read( const FileNode& fn ); bool updateImpl( const Mat& image, Rect2d& boundingBox );
void write( FileStorage& fs ) const; };
};
TrackerMIL::Params TrackerMIL::Params
------------------ ------------------
...@@ -111,11 +110,11 @@ List of MIL parameters:: ...@@ -111,11 +110,11 @@ List of MIL parameters::
void write( FileStorage& fs ) const; void write( FileStorage& fs ) const;
}; };
TrackerMIL::TrackerMIL TrackerMIL::createTracker
---------------------- -------------------------------
Constructor Constructor
.. ocv:function:: bool TrackerMIL::TrackerMIL( const TrackerMIL::Params &parameters = TrackerMIL::Params() ) .. ocv:function:: Ptr<trackerMIL> TrackerMIL::createTracker(const trackerMIL::Params &parameters=trackerMIL::Params())
:param parameters: MIL parameters :ocv:struct:`TrackerMIL::Params` :param parameters: MIL parameters :ocv:struct:`TrackerMIL::Params`
...@@ -42,11 +42,13 @@ ...@@ -42,11 +42,13 @@
#ifndef __OPENCV_TRACKING_HPP__ #ifndef __OPENCV_TRACKING_HPP__
#define __OPENCV_TRACKING_HPP__ #define __OPENCV_TRACKING_HPP__
#include "opencv2/tracking/tracker.hpp" #include "opencv2/core/cvdef.h"
namespace cv namespace cv
{ {
CV_EXPORTS bool initModule_tracking(void); CV_EXPORTS bool initModule_tracking(void);
} }
#include "opencv2/tracking/tracker.hpp"
#endif //__OPENCV_TRACKING_HPP__ #endif //__OPENCV_TRACKING_HPP__
...@@ -50,6 +50,10 @@ ...@@ -50,6 +50,10 @@
#include "opencv2/optim.hpp" #include "opencv2/optim.hpp"
#include <iostream> #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:
* ==================================================================================================================== * ====================================================================================================================
...@@ -497,6 +501,9 @@ class CV_EXPORTS_W Tracker : public virtual Algorithm ...@@ -497,6 +501,9 @@ class CV_EXPORTS_W Tracker : public virtual Algorithm
*/ */
static Ptr<Tracker> create( const String& trackerType ); static Ptr<Tracker> create( const String& trackerType );
virtual void read( const FileNode& fn )=0;
virtual void write( FileStorage& fs ) const=0;
protected: protected:
virtual bool initImpl( const Mat& image, const Rect2d& boundingBox ) = 0; virtual bool initImpl( const Mat& image, const Rect2d& boundingBox ) = 0;
...@@ -507,7 +514,7 @@ class CV_EXPORTS_W Tracker : public virtual Algorithm ...@@ -507,7 +514,7 @@ class CV_EXPORTS_W Tracker : public virtual Algorithm
Ptr<TrackerFeatureSet> featureSet; Ptr<TrackerFeatureSet> featureSet;
Ptr<TrackerSampler> sampler; Ptr<TrackerSampler> sampler;
Ptr<TrackerModel> model; Ptr<TrackerModel> model;
virtual AlgorithmInfo* info() const;
}; };
/************************************ Specific TrackerStateEstimator Classes ************************************/ /************************************ Specific TrackerStateEstimator Classes ************************************/
...@@ -961,33 +968,13 @@ class CV_EXPORTS_W TrackerMIL : public Tracker ...@@ -961,33 +968,13 @@ class CV_EXPORTS_W TrackerMIL : public Tracker
float samplerTrackInRadius; // radius for gathering positive instances during tracking float samplerTrackInRadius; // radius for gathering positive instances during tracking
int samplerTrackMaxPosNum; // # positive samples to use during tracking int samplerTrackMaxPosNum; // # positive samples to use during tracking
int samplerTrackMaxNegNum; // # negative samples to use during tracking int samplerTrackMaxNegNum; // # negative samples to use during tracking
int featureSetNumFeatures; // #features int featureSetNumFeatures; // #features
void read( const FileNode& fn ); void read( const FileNode& fn );
void write( FileStorage& fs ) const; void write( FileStorage& fs ) const;
}; };
/** BOILERPLATE_CODE("MIL",TrackerMIL);
* \brief TrackerMIL Constructor
* \param parameters TrackerMIL parameters
*/
TrackerMIL( const TrackerMIL::Params &parameters = TrackerMIL::Params() );
virtual ~TrackerMIL();
void read( const FileNode& fn );
void write( FileStorage& fs ) const;
protected:
bool initImpl( const Mat& image, const Rect2d& boundingBox );
bool updateImpl( const Mat& image, Rect2d& boundingBox );
void compute_integral( const Mat & img, Mat & ii_img );
Params params;
AlgorithmInfo* info() const;
}; };
/** /**
...@@ -1016,24 +1003,7 @@ class CV_EXPORTS_W TrackerBoosting : public Tracker ...@@ -1016,24 +1003,7 @@ class CV_EXPORTS_W TrackerBoosting : public Tracker
void write( FileStorage& fs ) const; void write( FileStorage& fs ) const;
}; };
/** BOILERPLATE_CODE("BOOSTING",TrackerBoosting);
* \brief TrackerBoosting Constructor
* \param parameters TrackerBoosting parameters
*/
TrackerBoosting( const TrackerBoosting::Params &parameters = TrackerBoosting::Params() );
virtual ~TrackerBoosting();
void read( const FileNode& fn );
void write( FileStorage& fs ) const;
protected:
bool initImpl( const Mat& image, const Rect2d& boundingBox );
bool updateImpl( const Mat& image, Rect2d& boundingBox );
Params params;
AlgorithmInfo* info() const;
}; };
} /* namespace cv */ } /* namespace cv */
......
...@@ -41,6 +41,12 @@ ...@@ -41,6 +41,12 @@
#include "precomp.hpp" #include "precomp.hpp"
#undef BOILERPLATE_CODE
#define BOILERPLATE_CODE(name,classname)\
if(trackerType==name){\
return classname::createTracker();\
}
namespace cv namespace cv
{ {
...@@ -98,10 +104,15 @@ bool Tracker::update( const Mat& image, Rect2d& boundingBox ) ...@@ -98,10 +104,15 @@ bool Tracker::update( const Mat& image, Rect2d& boundingBox )
return updateImpl( image, boundingBox ); return updateImpl( image, boundingBox );
} }
AlgorithmInfo* Tracker::info() const{
return 0;
}
Ptr<Tracker> Tracker::create( const String& trackerType ) Ptr<Tracker> Tracker::create( const String& trackerType )
{ {
BOILERPLATE_CODE("MIL",TrackerMIL);
return Algorithm::create<Tracker>( "TRACKER." + trackerType ); BOILERPLATE_CODE("BOOSTING",TrackerBoosting);
return Ptr<Tracker>();
} }
} /* namespace cv */ } /* namespace cv */
...@@ -45,6 +45,21 @@ ...@@ -45,6 +45,21 @@
namespace cv namespace cv
{ {
class TrackerBoostingImpl : public TrackerBoosting
{
public:
TrackerBoostingImpl( const TrackerBoosting::Params &parameters = TrackerBoosting::Params() );
void read( const FileNode& fn );
void write( FileStorage& fs ) const;
protected:
bool initImpl( const Mat& image, const Rect2d& boundingBox );
bool updateImpl( const Mat& image, Rect2d& boundingBox );
TrackerBoosting::Params params;
};
/* /*
* TrackerBoosting * TrackerBoosting
*/ */
...@@ -82,31 +97,26 @@ void TrackerBoosting::Params::write( cv::FileStorage& fs ) const ...@@ -82,31 +97,26 @@ void TrackerBoosting::Params::write( cv::FileStorage& fs ) const
/* /*
* Constructor * Constructor
*/ */
TrackerBoosting::TrackerBoosting( const TrackerBoosting::Params &parameters ) : Ptr<TrackerBoosting> TrackerBoosting::createTracker(const TrackerBoosting::Params &parameters){
return Ptr<TrackerBoostingImpl>(new TrackerBoostingImpl(parameters));
}
TrackerBoostingImpl::TrackerBoostingImpl( const TrackerBoostingImpl::Params &parameters ) :
params( parameters ) params( parameters )
{ {
isInit = false; isInit = false;
} }
/* void TrackerBoostingImpl::read( const cv::FileNode& fn )
* Destructor
*/
TrackerBoosting::~TrackerBoosting()
{
}
void TrackerBoosting::read( const cv::FileNode& fn )
{ {
params.read( fn ); params.read( fn );
} }
void TrackerBoosting::write( cv::FileStorage& fs ) const void TrackerBoostingImpl::write( cv::FileStorage& fs ) const
{ {
params.write( fs ); params.write( fs );
} }
bool TrackerBoosting::initImpl( const Mat& image, const Rect2d& boundingBox ) bool TrackerBoostingImpl::initImpl( const Mat& image, const Rect2d& boundingBox )
{ {
srand (1); srand (1);
//sampling //sampling
...@@ -190,7 +200,7 @@ bool TrackerBoosting::initImpl( const Mat& image, const Rect2d& boundingBox ) ...@@ -190,7 +200,7 @@ bool TrackerBoosting::initImpl( const Mat& image, const Rect2d& boundingBox )
return true; return true;
} }
bool TrackerBoosting::updateImpl( const Mat& image, Rect2d& boundingBox ) bool TrackerBoostingImpl::updateImpl( const Mat& image, Rect2d& boundingBox )
{ {
Mat_<int> intImage; Mat_<int> intImage;
Mat_<double> intSqImage; Mat_<double> intSqImage;
......
...@@ -45,6 +45,22 @@ ...@@ -45,6 +45,22 @@
namespace cv namespace cv
{ {
class TrackerMILImpl : public TrackerMIL
{
public:
TrackerMILImpl( const TrackerMIL::Params &parameters = TrackerMIL::Params() );
void read( const FileNode& fn );
void write( FileStorage& fs ) const;
protected:
bool initImpl( const Mat& image, const Rect2d& boundingBox );
bool updateImpl( const Mat& image, Rect2d& boundingBox );
void compute_integral( const Mat & img, Mat & ii_img );
TrackerMIL::Params params;
};
/* /*
* TrackerMIL * TrackerMIL
*/ */
...@@ -89,31 +105,26 @@ void TrackerMIL::Params::write( cv::FileStorage& fs ) const ...@@ -89,31 +105,26 @@ void TrackerMIL::Params::write( cv::FileStorage& fs ) const
/* /*
* Constructor * Constructor
*/ */
TrackerMIL::TrackerMIL( const TrackerMIL::Params &parameters ) : Ptr<TrackerMIL> TrackerMIL::createTracker(const TrackerMIL::Params &parameters){
return Ptr<TrackerMILImpl>(new TrackerMILImpl(parameters));
}
TrackerMILImpl::TrackerMILImpl( const TrackerMIL::Params &parameters ) :
params( parameters ) params( parameters )
{ {
isInit = false; isInit = false;
} }
/* void TrackerMILImpl::read( const cv::FileNode& fn )
* Destructor
*/
TrackerMIL::~TrackerMIL()
{
}
void TrackerMIL::read( const cv::FileNode& fn )
{ {
params.read( fn ); params.read( fn );
} }
void TrackerMIL::write( cv::FileStorage& fs ) const void TrackerMILImpl::write( cv::FileStorage& fs ) const
{ {
params.write( fs ); params.write( fs );
} }
void TrackerMIL::compute_integral( const Mat & img, Mat & ii_img ) void TrackerMILImpl::compute_integral( const Mat & img, Mat & ii_img )
{ {
Mat ii; Mat ii;
std::vector<Mat> ii_imgs; std::vector<Mat> ii_imgs;
...@@ -122,7 +133,7 @@ void TrackerMIL::compute_integral( const Mat & img, Mat & ii_img ) ...@@ -122,7 +133,7 @@ void TrackerMIL::compute_integral( const Mat & img, Mat & ii_img )
ii_img = ii_imgs[0]; ii_img = ii_imgs[0];
} }
bool TrackerMIL::initImpl( const Mat& image, const Rect2d& boundingBox ) bool TrackerMILImpl::initImpl( const Mat& image, const Rect2d& boundingBox )
{ {
srand (1); srand (1);
Mat intImage; Mat intImage;
...@@ -184,7 +195,7 @@ bool TrackerMIL::initImpl( const Mat& image, const Rect2d& boundingBox ) ...@@ -184,7 +195,7 @@ bool TrackerMIL::initImpl( const Mat& image, const Rect2d& boundingBox )
return true; return true;
} }
bool TrackerMIL::updateImpl( const Mat& image, Rect2d& boundingBox ) bool TrackerMILImpl::updateImpl( const Mat& image, Rect2d& boundingBox )
{ {
Mat intImage; Mat intImage;
compute_integral( image, intImage ); compute_integral( image, intImage );
......
...@@ -45,17 +45,9 @@ ...@@ -45,17 +45,9 @@
namespace cv namespace cv
{ {
CV_INIT_ALGORITHM(TrackerMIL, "TRACKER.MIL",);
CV_INIT_ALGORITHM(TrackerBoosting, "TRACKER.BOOSTING",);
bool initModule_tracking(void) bool initModule_tracking(void)
{ {
bool all = true; return true;
all &= !TrackerMIL_info_auto.name().empty();
all &= !TrackerBoosting_info_auto.name().empty();
return all;
} }
} }
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