Commit c27db0d1 authored by Alex Leontiev's avatar Alex Leontiev

Tracking-Learning-Detection and MedianFlow

This contribution includes the following logical components into
tracking module:

.) Change Rect to Rect2d into headers for Tracker's methods;
This contribution includes the following logical components into
tracking module:

.) Change Rect to Rect2d into headers for Tracker's methods;
.) MedianFlow tracker;
.) extensible benchmark to compare trackers interactively and
	assess them quantitatively;
.) TLD tracker (work-in-progress);

Work was funded by Google Summer of Code 2014 initiative. Mentors:
Gary
Bradski and Vadim Pisarevsky.
parent ed3e4506
set(the_description "Tracking API") set(the_description "Tracking API")
ocv_define_module(tracking opencv_imgproc opencv_optim) ocv_define_module(tracking opencv_imgproc opencv_optim opencv_video opencv_highgui)
...@@ -39,8 +39,8 @@ ...@@ -39,8 +39,8 @@
// //
//M*/ //M*/
#ifndef __OPENCV_TRACKING_HPP__ #ifndef __OPENCV_TRACKING_LENLEN_HPP__
#define __OPENCV_TRACKING_HPP__ #define __OPENCV_TRACKING_LENLEN_HPP__
#include "opencv2/core/cvdef.h" #include "opencv2/core/cvdef.h"
...@@ -50,5 +50,4 @@ CV_EXPORTS bool initModule_tracking(void); ...@@ -50,5 +50,4 @@ CV_EXPORTS bool initModule_tracking(void);
} }
#include "opencv2/tracking/tracker.hpp" #include "opencv2/tracking/tracker.hpp"
#endif //__OPENCV_TRACKING_LENLEN
#endif //__OPENCV_TRACKING_HPP__
...@@ -1005,6 +1005,58 @@ class CV_EXPORTS_W TrackerBoosting : public Tracker ...@@ -1005,6 +1005,58 @@ class CV_EXPORTS_W TrackerBoosting : public Tracker
BOILERPLATE_CODE("BOOSTING",TrackerBoosting); BOILERPLATE_CODE("BOOSTING",TrackerBoosting);
}; };
/**
\brief Median Flow tracker implementation.
Implementation of a paper "Forward-Backward Error: Automatic Detection of Tracking Failures" by Z. Kalal, K. Mikolajczyk
and Jiri Matas.
*/
class CV_EXPORTS_W TrackerMedianFlow : public Tracker
{
public:
struct CV_EXPORTS Params
{
Params();
int pointsInGrid;
void read( const FileNode& /*fn*/ );
void write( FileStorage& /*fs*/ ) const;
};
TrackerMedianFlow( const TrackerMedianFlow::Params &parameters = TrackerMedianFlow::Params() );
virtual ~TrackerMedianFlow();
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;
};
class CV_EXPORTS_W TrackerTLD : public Tracker
{
public:
struct CV_EXPORTS Params
{
Params();
void read( const FileNode& /*fn*/ );
void write( FileStorage& /*fs*/ ) const;
};
TrackerTLD( const TrackerTLD::Params &parameters = TrackerTLD::Params() );
virtual ~TrackerTLD();
void read( const FileNode& fn );
void write( FileStorage& fs ) const;
class Private{public: virtual ~Private(){}};
protected:
bool initImpl( const Mat& image, const Rect2d& boundingBox );
bool updateImpl( const Mat& image, Rect2d& boundingBox );
Params params;
std::vector<Ptr<Private> > privateInfo;
AlgorithmInfo* info() const;
};
} /* namespace cv */ } /* namespace cv */
#endif #endif
This diff is collapsed.
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <opencv2/tracking.hpp> #include <opencv2/tracking.hpp>
#include <opencv2/highgui.hpp> #include <opencv2/highgui.hpp>
#include <iostream> #include <iostream>
#include <cstring>
using namespace std; using namespace std;
using namespace cv; using namespace cv;
...@@ -15,21 +16,20 @@ static bool startSelection = false; ...@@ -15,21 +16,20 @@ 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 |1| 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 help() static void listTrackers(){
{ vector<String> algorithms;
cout << "\nThis example shows the functionality of \"Long-term optical tracking API\"" Algorithm::getList(algorithms);
"-- pause video [p] and draw a bounding box around the target to start the tracker\n" cout << "\nAvailable tracker algorithms:\n";
"Example of <video_name> is in opencv_extra/testdata/cv/tracking/\n" for (size_t i=0; i < algorithms.size(); i++){
"Call:\n" const char* algoname=algorithms[i].c_str();
"./tracker <tracker_algorithm> <video_name> <start_frame> [<bounding_frame>]\n" char *pos=NULL;
<< endl; if((pos=strstr((char*)algoname,"TRACKER."))!=NULL){
printf("%s\n",pos+8);
cout << "\n\nHot keys: \n" }
"\tq - quit the program\n" }
"\tp - pause video\n";
} }
static void onMouse( int event, int x, int y, int, void* ) static void onMouse( int event, int x, int y, int, void* )
...@@ -58,7 +58,7 @@ static void onMouse( int event, int x, int y, int, void* ) ...@@ -58,7 +58,7 @@ static void onMouse( int event, int x, int y, int, void* )
//draw the bounding box //draw the bounding box
Mat currentFrame; Mat currentFrame;
image.copyTo( currentFrame ); image.copyTo( currentFrame );
rectangle( currentFrame, Point( (int)boundingBox.x, (int)boundingBox.y ), Point( x, y ), Scalar( 255, 0, 0 ), 2, 1 ); rectangle( currentFrame, Point( boundingBox.x, boundingBox.y ), Point( x, y ), Scalar( 255, 0, 0 ), 2, 1 );
imshow( "Tracking API", currentFrame ); imshow( "Tracking API", currentFrame );
} }
break; break;
...@@ -66,8 +66,22 @@ static void onMouse( int event, int x, int y, int, void* ) ...@@ -66,8 +66,22 @@ static void onMouse( int event, int x, int y, int, void* )
} }
} }
int main( int argc, char** argv ) static void help()
{ {
cout << "\nThis example shows the functionality of \"Long-term optical tracking API\""
"-- pause video [p] and draw a bounding box around the target to start the tracker\n"
"Example of <video_name> is in opencv_extra/testdata/cv/tracking/\n"
"Call:\n"
"./tracker <tracker_algorithm> <video_name> <start_frame> [<bounding_frame>]\n"
<< endl;
cout << "\n\nHot keys: \n"
"\tq - quit the program\n"
"\tp - pause video\n";
listTrackers();
}
int main( int argc, char** argv ){
CommandLineParser parser( argc, argv, keys ); CommandLineParser parser( argc, argv, keys );
String tracker_algorithm = parser.get<String>( 0 ); String tracker_algorithm = parser.get<String>( 0 );
...@@ -81,24 +95,19 @@ int main( int argc, char** argv ) ...@@ -81,24 +95,19 @@ int main( int argc, char** argv )
} }
int coords[4]={0,0,0,0}; int coords[4]={0,0,0,0};
bool initFrameWasGivenInCommandLine=false; bool initBoxWasGivenInCommandLine=false;
do{
do
{
String initBoundingBox=parser.get<String>(3); String initBoundingBox=parser.get<String>(3);
for(size_t pos=0,ctr=0;ctr<4;ctr++) for(size_t npos=0,pos=0,ctr=0;ctr<4;ctr++){
{ npos=initBoundingBox.find_first_of(',',pos);
size_t npos=initBoundingBox.find_first_of(',',pos); if(npos==string::npos && ctr<3){
if(npos==string::npos && ctr<3)
{
printf("bounding box should be given in format \"x1,y1,x2,y2\",where x's and y's are integer cordinates of opposed corners of bdd box\n"); printf("bounding box should be given in format \"x1,y1,x2,y2\",where x's and y's are integer cordinates of opposed corners of bdd box\n");
printf("got: %s\n",initBoundingBox.substr(pos,string::npos).c_str()); printf("got: %s\n",initBoundingBox.substr(pos,string::npos).c_str());
printf("manual selection of bounding box will be employed\n"); printf("manual selection of bounding box will be employed\n");
break; break;
} }
int num=atoi(initBoundingBox.substr(pos,(ctr==3)?(string::npos):(npos-pos)).c_str()); int num=atoi(initBoundingBox.substr(pos,(ctr==3)?(string::npos):(npos-pos)).c_str());
if(num<=0) if(num<=0){
{
printf("bounding box should be given in format \"x1,y1,x2,y2\",where x's and y's are integer cordinates of opposed corners of bdd box\n"); printf("bounding box should be given in format \"x1,y1,x2,y2\",where x's and y's are integer cordinates of opposed corners of bdd box\n");
printf("got: %s\n",initBoundingBox.substr(pos,npos-pos).c_str()); printf("got: %s\n",initBoundingBox.substr(pos,npos-pos).c_str());
printf("manual selection of bounding box will be employed\n"); printf("manual selection of bounding box will be employed\n");
...@@ -107,9 +116,10 @@ int main( int argc, char** argv ) ...@@ -107,9 +116,10 @@ int main( int argc, char** argv )
coords[ctr]=num; coords[ctr]=num;
pos=npos+1; pos=npos+1;
} }
if(coords[0]>0 && coords[1]>0 && coords[2]>0 && coords[3]>0) if(coords[0]>0 && coords[1]>0 && coords[2]>0 && coords[3]>0){
initFrameWasGivenInCommandLine=true; initBoxWasGivenInCommandLine=true;
} while((void)0, 0); }
}while(0);
//open the capture //open the capture
VideoCapture cap; VideoCapture cap;
...@@ -141,7 +151,7 @@ int main( int argc, char** argv ) ...@@ -141,7 +151,7 @@ int main( int argc, char** argv )
//get the first frame //get the first frame
cap >> frame; cap >> frame;
frame.copyTo( image ); frame.copyTo( image );
if(initFrameWasGivenInCommandLine){ if(initBoxWasGivenInCommandLine){
selectObject=true; selectObject=true;
paused=false; paused=false;
boundingBox.x = coords[0]; boundingBox.x = coords[0];
...@@ -160,14 +170,13 @@ int main( int argc, char** argv ) ...@@ -160,14 +170,13 @@ int main( int argc, char** argv )
{ {
if( !paused ) if( !paused )
{ {
if(initialized){
cap >> frame; cap >> frame;
if(frame.empty()){
if( frame.empty() )
{
break; break;
} }
frame.copyTo( image ); frame.copyTo( image );
}
if( !initialized && selectObject ) if( !initialized && selectObject )
{ {
......
This diff is collapsed.
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc.hpp"
#include <algorithm>
#include <limits.h>
using namespace cv;
namespace cv
{
//debug functions and variables
#define MEASURE_TIME(a) {\
clock_t start;float milisec=0.0;\
start=clock();{a} milisec=1000.0*(clock()-start)/CLOCKS_PER_SEC;\
printf("%-90s took %f milis\n",#a,milisec); }
#define HERE fprintf(stderr,"%d\n",__LINE__);fflush(stderr);
#define START_TICK(name) { clock_t start;float milisec=0.0; start=clock();
#define END_TICK(name) milisec=1000.0*(clock()-start)/CLOCKS_PER_SEC;\
printf("%s took %f milis\n",name,milisec); }
extern Rect2d etalon;
void myassert(const Mat& img);
void printPatch(const Mat_<uchar>& standardPatch);
std::string type2str(const Mat& mat);
void drawWithRects(const Mat& img,std::vector<Rect2d>& blackOnes,Rect2d whiteOne=Rect2d(-1.0,-1.0,-1.0,-1.0));
void drawWithRects(const Mat& img,std::vector<Rect2d>& blackOnes,std::vector<Rect2d>& whiteOnes);
//aux functions and variables
#define CLIP(x,a,b) MIN(MAX((x),(a)),(b))
double overlap(const Rect2d& r1,const Rect2d& r2);
void resample(const Mat& img,const RotatedRect& r2,Mat_<uchar>& samples);
void resample(const Mat& img,const Rect2d& r2,Mat_<uchar>& samples);
double variance(const Mat& img);
double variance(Mat_<unsigned int>& intImgP,Mat_<unsigned int>& intImgP2,Rect box);
double NCC(Mat_<uchar> patch1,Mat_<uchar> patch2);
void getClosestN(std::vector<Rect2d>& scanGrid,Rect2d bBox,int n,std::vector<Rect2d>& res);
double scaleAndBlur(const Mat& originalImg,int scale,Mat& scaledImg,Mat& blurredImg,Size GaussBlurKernelSize);
unsigned int getMedian(const std::vector<unsigned int>& values, int size=-1);
class TLDEnsembleClassifier{
public:
TLDEnsembleClassifier(int ordinal,Size size);
void integrate(Mat_<uchar> patch,bool isPositive);
double posteriorProbability(const uchar* data,int rowstep)const;
static int getMaxOrdinal();
private:
static int getGridSize();
inline void stepPrefSuff(uchar* arr,int len);
void preinit(int ordinal);
unsigned short int code(const uchar* data,int rowstep)const;
unsigned int pos[8192],neg[8192];//8192=2^13
uchar x1[13],y1[13],x2[13],y2[13];
};
class TrackerProxy : public TrackerTLD::Private{
public:
virtual bool init( const Mat& image, const Rect2d& boundingBox)=0;
virtual bool update(const Mat& image, Rect2d& boundingBox)=0;
virtual ~TrackerProxy(){}
};
}
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -78,7 +78,7 @@ bool Tracker::init( const Mat& image, const Rect2d& boundingBox ) ...@@ -78,7 +78,7 @@ bool Tracker::init( const Mat& image, const Rect2d& boundingBox )
//check if the model component is initialized //check if the model component is initialized
if( model == 0 ) if( model == 0 )
{ {
CV_Error( -1, "The model are not initialized" ); CV_Error( -1, "The model is not initialized" );
return false; return false;
} }
......
This diff is collapsed.
This diff is collapsed.
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