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:
Creating Own Tracker
--------------------
If you want create a new tracker, you should follow some simple rules.
First, your tracker should be inherit from :ocv:class:`Tracker`, so you must implement two method:
* 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.
* 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.
Example of creating specialized Tracker ``TrackerMIL`` : ::
class CV_EXPORTS_W TrackerMIL : public Tracker
{
public:
TrackerMIL( const TrackerMIL::Params &parameters = TrackerMIL::Params() );
virtual ~TrackerMIL();
...
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,
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".
* Declare your tracker in ``include/opencv2/tracking/tracker.hpp``.
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
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
{
public:
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:
bool initImpl( const Mat& image, const Rect2d& boundingBox );
bool updateImpl( const Mat& image, Rect2d& boundingBox );
...
};
Ptr<classname> classname::createTracker(const classname::Params &parameters){
...
}
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`.
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
..............
......
......@@ -20,19 +20,18 @@ The classifier uses the surrounding background as negative examples in update st
Implementation of TrackerBoosting from :ocv:class:`Tracker`::
class CV_EXPORTS_W TrackerBoosting : public Tracker
{
public:
TrackerBoosting( const TrackerBoosting::Params &parameters = TrackerBoosting::Params() );
virtual ~TrackerBoosting();
void read( const FileNode& fn );
void write( FileStorage& fs ) const;
};
class CV_EXPORTS_W TrackerBoosting : public Tracker
{
public:
void read( const FileNode& fn );
void write( FileStorage& fs ) const;
static Ptr<trackerBoosting> createTracker(const trackerBoosting::Params &parameters=trackerBoosting::Params());
virtual ~trackerBoosting(){};
protected:
bool initImpl( const Mat& image, const Rect2d& boundingBox );
bool updateImpl( const Mat& image, Rect2d& boundingBox );
};
TrackerBoosting::Params
-----------------------------------------------------------------------
......@@ -54,12 +53,12 @@ List of BOOSTING parameters::
void write( FileStorage& fs ) const;
};
TrackerBoosting::TrackerBoosting
TrackerBoosting::createTracker
-----------------------------------------------------------------------
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`
......@@ -74,18 +73,18 @@ Original code can be found here http://vision.ucsd.edu/~bbabenko/project_miltrac
Implementation of TrackerMIL from :ocv:class:`Tracker`::
class CV_EXPORTS_W TrackerMIL : public Tracker
{
public:
TrackerMIL( const TrackerMIL::Params &parameters = TrackerMIL::Params() );
class CV_EXPORTS_W TrackerMIL : public Tracker
{
public:
void read( const FileNode& fn );
void write( FileStorage& fs ) const;
static Ptr<trackerMIL> createTracker(const trackerMIL::Params &parameters=trackerMIL::Params());
virtual ~trackerMIL(){};
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 );
};
TrackerMIL::Params
------------------
......@@ -111,11 +110,11 @@ List of MIL parameters::
void write( FileStorage& fs ) const;
};
TrackerMIL::TrackerMIL
----------------------
TrackerMIL::createTracker
-------------------------------
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`
......@@ -42,11 +42,13 @@
#ifndef __OPENCV_TRACKING_HPP__
#define __OPENCV_TRACKING_HPP__
#include "opencv2/tracking/tracker.hpp"
#include "opencv2/core/cvdef.h"
namespace cv
{
CV_EXPORTS bool initModule_tracking(void);
}
#include "opencv2/tracking/tracker.hpp"
#endif //__OPENCV_TRACKING_HPP__
......@@ -50,6 +50,10 @@
#include "opencv2/optim.hpp"
#include <iostream>
#define BOILERPLATE_CODE(name,classname) \
static Ptr<classname> createTracker(const classname::Params &parameters=classname::Params());\
virtual ~classname(){};
/*
* Partially based on:
* ====================================================================================================================
......@@ -497,6 +501,9 @@ class CV_EXPORTS_W Tracker : public virtual Algorithm
*/
static Ptr<Tracker> create( const String& trackerType );
virtual void read( const FileNode& fn )=0;
virtual void write( FileStorage& fs ) const=0;
protected:
virtual bool initImpl( const Mat& image, const Rect2d& boundingBox ) = 0;
......@@ -507,7 +514,7 @@ class CV_EXPORTS_W Tracker : public virtual Algorithm
Ptr<TrackerFeatureSet> featureSet;
Ptr<TrackerSampler> sampler;
Ptr<TrackerModel> model;
virtual AlgorithmInfo* info() const;
};
/************************************ Specific TrackerStateEstimator Classes ************************************/
......@@ -961,33 +968,13 @@ class CV_EXPORTS_W TrackerMIL : public Tracker
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;
};
/**
* \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;
BOILERPLATE_CODE("MIL",TrackerMIL);
};
/**
......@@ -1016,24 +1003,7 @@ class CV_EXPORTS_W TrackerBoosting : public Tracker
void write( FileStorage& fs ) const;
};
/**
* \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;
BOILERPLATE_CODE("BOOSTING",TrackerBoosting);
};
} /* namespace cv */
......
......@@ -41,6 +41,12 @@
#include "precomp.hpp"
#undef BOILERPLATE_CODE
#define BOILERPLATE_CODE(name,classname)\
if(trackerType==name){\
return classname::createTracker();\
}
namespace cv
{
......@@ -98,10 +104,15 @@ bool Tracker::update( const Mat& image, Rect2d& boundingBox )
return updateImpl( image, boundingBox );
}
AlgorithmInfo* Tracker::info() const{
return 0;
}
Ptr<Tracker> Tracker::create( const String& trackerType )
{
return Algorithm::create<Tracker>( "TRACKER." + trackerType );
BOILERPLATE_CODE("MIL",TrackerMIL);
BOILERPLATE_CODE("BOOSTING",TrackerBoosting);
return Ptr<Tracker>();
}
} /* namespace cv */
......@@ -45,6 +45,21 @@
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
*/
......@@ -82,31 +97,26 @@ void TrackerBoosting::Params::write( cv::FileStorage& fs ) const
/*
* 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 )
{
isInit = false;
}
/*
* Destructor
*/
TrackerBoosting::~TrackerBoosting()
{
}
void TrackerBoosting::read( const cv::FileNode& fn )
void TrackerBoostingImpl::read( const cv::FileNode& fn )
{
params.read( fn );
}
void TrackerBoosting::write( cv::FileStorage& fs ) const
void TrackerBoostingImpl::write( cv::FileStorage& fs ) const
{
params.write( fs );
}
bool TrackerBoosting::initImpl( const Mat& image, const Rect2d& boundingBox )
bool TrackerBoostingImpl::initImpl( const Mat& image, const Rect2d& boundingBox )
{
srand (1);
//sampling
......@@ -190,7 +200,7 @@ bool TrackerBoosting::initImpl( const Mat& image, const Rect2d& boundingBox )
return true;
}
bool TrackerBoosting::updateImpl( const Mat& image, Rect2d& boundingBox )
bool TrackerBoostingImpl::updateImpl( const Mat& image, Rect2d& boundingBox )
{
Mat_<int> intImage;
Mat_<double> intSqImage;
......
......@@ -45,6 +45,22 @@
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
*/
......@@ -89,31 +105,26 @@ void TrackerMIL::Params::write( cv::FileStorage& fs ) const
/*
* 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 )
{
isInit = false;
}
/*
* Destructor
*/
TrackerMIL::~TrackerMIL()
{
}
void TrackerMIL::read( const cv::FileNode& fn )
void TrackerMILImpl::read( const cv::FileNode& fn )
{
params.read( fn );
}
void TrackerMIL::write( cv::FileStorage& fs ) const
void TrackerMILImpl::write( cv::FileStorage& fs ) const
{
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;
std::vector<Mat> ii_imgs;
......@@ -122,7 +133,7 @@ void TrackerMIL::compute_integral( const Mat & img, Mat & ii_img )
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);
Mat intImage;
......@@ -184,7 +195,7 @@ bool TrackerMIL::initImpl( const Mat& image, const Rect2d& boundingBox )
return true;
}
bool TrackerMIL::updateImpl( const Mat& image, Rect2d& boundingBox )
bool TrackerMILImpl::updateImpl( const Mat& image, Rect2d& boundingBox )
{
Mat intImage;
compute_integral( image, intImage );
......
......@@ -45,17 +45,9 @@
namespace cv
{
CV_INIT_ALGORITHM(TrackerMIL, "TRACKER.MIL",);
CV_INIT_ALGORITHM(TrackerBoosting, "TRACKER.BOOSTING",);
bool initModule_tracking(void)
{
bool all = true;
all &= !TrackerMIL_info_auto.name().empty();
all &= !TrackerBoosting_info_auto.name().empty();
return all;
return true;
}
}
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