Commit 4e14e8c8 authored by Alex Leontiev's avatar Alex Leontiev

coding style

parent ed4aeef7
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
#define DOWNSCALE_MODE INTER_LINEAR #define DOWNSCALE_MODE INTER_LINEAR
#define BLUR_AS_VADIM #define BLUR_AS_VADIM
#undef CLOSED_LOOP #undef CLOSED_LOOP
static const cv::Size GaussBlurKernelSize(3,3); static const cv::Size GaussBlurKernelSize(3, 3);
using namespace cv; using namespace cv;
using namespace tld; using namespace tld;
...@@ -88,18 +88,12 @@ using namespace tld; ...@@ -88,18 +88,12 @@ using namespace tld;
* 11. group decls logically, order of statements * 11. group decls logically, order of statements
* *
* ?10. all in one class * ?10. all in one class
* todo: initializer lists * todo: initializer lists; const methods
*
* format: if,while,for, , Assert
* format: methods
* --> compile
* ; ,
* --> compile
* -->commit-push -->notify
* *
* ?( ) * ?( )
* *
* ?vadim: for{1command} can omit {}; if( a != (b + c) ) vs ( a != ( b + c ) ) * ?vadim: for{1command} can omit {}; if( a != (b + c) ) vs ( a != ( b + c ) ); if{} for{} method{} oneline:spaces, omit{};
* 1-statement for/if without {}
*/ */
/* design decisions: /* design decisions:
...@@ -109,24 +103,24 @@ namespace cv ...@@ -109,24 +103,24 @@ namespace cv
{ {
class TLDDetector; class TLDDetector;
class MyMouseCallbackDEBUG{ class MyMouseCallbackDEBUG
{
public: public:
MyMouseCallbackDEBUG( Mat& img, Mat& imgBlurred,TLDDetector* detector):img_(img),imgBlurred_(imgBlurred),detector_(detector){} MyMouseCallbackDEBUG(Mat& img, Mat& imgBlurred, TLDDetector* detector):img_(img), imgBlurred_(imgBlurred), detector_(detector){}
static void onMouse( int event, int x, int y, int, void* obj){ static void onMouse(int event, int x, int y, int, void* obj){ ((MyMouseCallbackDEBUG*)obj)->onMouse(event, x, y); }
((MyMouseCallbackDEBUG*)obj)->onMouse(event,x,y); MyMouseCallbackDEBUG& operator = (const MyMouseCallbackDEBUG& /*other*/){ return *this; }
}
MyMouseCallbackDEBUG& operator = (const MyMouseCallbackDEBUG& /*other*/){return *this;}
private: private:
void onMouse( int event, int x, int y); void onMouse(int event, int x, int y);
Mat& img_,imgBlurred_; Mat& img_, imgBlurred_;
TLDDetector* detector_; TLDDetector* detector_;
}; };
class Data { class Data
{
public: public:
Data(Rect2d initBox); Data(Rect2d initBox);
Size getMinSize(){return minSize;} Size getMinSize(){ return minSize; }
double getScale(){return scale;} double getScale(){ return scale; }
bool confident; bool confident;
bool failedLastTime; bool failedLastTime;
int frameNum; int frameNum;
...@@ -136,35 +130,39 @@ private: ...@@ -136,35 +130,39 @@ private:
Size minSize; Size minSize;
}; };
class TLDDetector { class TLDDetector
{
public: public:
TLDDetector(const TrackerTLD::Params& params,Ptr<TrackerModel> model_in):model(model_in),params_(params){} TLDDetector(const TrackerTLD::Params& params, Ptr<TrackerModel> model_in):model(model_in), params_(params){}
~TLDDetector(){} ~TLDDetector(){}
static void generateScanGrid(int rows,int cols,Size initBox,std::vector<Rect2d>& res,bool withScaling = false); static void generateScanGrid(int rows, int cols, Size initBox, std::vector<Rect2d>& res, bool withScaling = false);
struct LabeledPatch{ struct LabeledPatch
{
Rect2d rect; Rect2d rect;
bool isObject, shouldBeIntegrated; bool isObject, shouldBeIntegrated;
}; };
bool detect(const Mat& img,const Mat& imgBlurred,Rect2d& res,std::vector<LabeledPatch>& patches); bool detect(const Mat& img, const Mat& imgBlurred, Rect2d& res, std::vector<LabeledPatch>& patches);
protected: protected:
friend class MyMouseCallbackDEBUG; friend class MyMouseCallbackDEBUG;
Ptr<TrackerModel> model; Ptr<TrackerModel> model;
void computeIntegralImages(const Mat& img,Mat_<double>& intImgP,Mat_<double>& intImgP2){integral(img,intImgP,intImgP2,CV_64F);} void computeIntegralImages(const Mat& img, Mat_<double>& intImgP, Mat_<double>& intImgP2){ integral(img, intImgP, intImgP2, CV_64F); }
inline bool patchVariance(Mat_<double>& intImgP,Mat_<double>& intImgP2,double originalVariance,Point pt,Size size); inline bool patchVariance(Mat_<double>& intImgP, Mat_<double>& intImgP2, double originalVariance, Point pt, Size size);
TrackerTLD::Params params_; TrackerTLD::Params params_;
}; };
template<class T, class Tparams> template<class T, class Tparams>
class TrackerProxyImpl : public TrackerProxy{ class TrackerProxyImpl : public TrackerProxy
{
public: 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::createTracker();
return trackerPtr->init(image,boundingBox); return trackerPtr->init(image, boundingBox);
} }
bool update( const Mat& image,Rect2d& boundingBox){ bool update(const Mat& image, Rect2d& boundingBox)
return trackerPtr->update(image,boundingBox); {
return trackerPtr->update(image, boundingBox);
} }
private: private:
Ptr<T> trackerPtr; Ptr<T> trackerPtr;
...@@ -172,53 +170,55 @@ private: ...@@ -172,53 +170,55 @@ private:
Rect2d boundingBox_; Rect2d boundingBox_;
}; };
class TrackerTLDModel : public TrackerModel{ class TrackerTLDModel : public TrackerModel
public: {
TrackerTLDModel(TrackerTLD::Params params,const Mat& image, const Rect2d& boundingBox,Size minSize); public:
Rect2d getBoundingBox(){return boundingBox_;} TrackerTLDModel(TrackerTLD::Params params, const Mat& image, const Rect2d& boundingBox, Size minSize);
void setBoudingBox(Rect2d boundingBox){boundingBox_ = boundingBox;} Rect2d getBoundingBox(){ return boundingBox_; }
double getOriginalVariance(){return originalVariance_;} void setBoudingBox(Rect2d boundingBox){ boundingBox_ = boundingBox; }
double getOriginalVariance(){ return originalVariance_; }
inline double ensembleClassifierNum(const uchar* data); inline double ensembleClassifierNum(const uchar* data);
inline void prepareClassifiers(int rowstep){for(int i = 0;i < (int)classifiers.size();i++)classifiers[i].prepareClassifier(rowstep);} inline void prepareClassifiers(int rowstep){ for( int i = 0; i < (int)classifiers.size(); i++ ) classifiers[i].prepareClassifier(rowstep); }
double Sr(const Mat_<uchar>& patch); double Sr(const Mat_<uchar>& patch);
double Sc(const Mat_<uchar>& patch); double Sc(const Mat_<uchar>& patch);
void integrateRelabeled(Mat& img,Mat& imgBlurred,const std::vector<TLDDetector::LabeledPatch>& patches); void integrateRelabeled(Mat& img, Mat& imgBlurred, const std::vector<TLDDetector::LabeledPatch>& patches);
void integrateAdditional(const std::vector<Mat_<uchar> >& eForModel,const std::vector<Mat_<uchar> >& eForEnsemble,bool isPositive); void integrateAdditional(const std::vector<Mat_<uchar> >& eForModel, const std::vector<Mat_<uchar> >& eForEnsemble, bool isPositive);
Size getMinSize(){return minSize_;} Size getMinSize(){ return minSize_; }
void printme(FILE* port = stdout); void printme(FILE* port = stdout);
protected: protected:
Size minSize_; Size minSize_;
int timeStampPositiveNext,timeStampNegativeNext; int timeStampPositiveNext, timeStampNegativeNext;
TrackerTLD::Params params_; TrackerTLD::Params params_;
void pushIntoModel(const Mat_<uchar>& example,bool positive); void pushIntoModel(const Mat_<uchar>& example, bool positive);
void modelEstimationImpl( const std::vector<Mat>& /*responses*/ ){} void modelEstimationImpl( const std::vector<Mat>& /*responses*/ ){}
void modelUpdateImpl(){} void modelUpdateImpl(){}
Rect2d boundingBox_; Rect2d boundingBox_;
double originalVariance_; double originalVariance_;
std::vector<Mat_<uchar> > positiveExamples,negativeExamples; std::vector<Mat_<uchar> > positiveExamples, negativeExamples;
std::vector<int> timeStampsPositive,timeStampsNegative; std::vector<int> timeStampsPositive, timeStampsNegative;
RNG rng; RNG rng;
std::vector<TLDEnsembleClassifier> classifiers; std::vector<TLDEnsembleClassifier> classifiers;
}; };
class TrackerTLDImpl : public TrackerTLD class TrackerTLDImpl : public TrackerTLD
{ {
public: public:
TrackerTLDImpl( const TrackerTLD::Params &parameters = TrackerTLD::Params() ); TrackerTLDImpl(const TrackerTLD::Params &parameters = TrackerTLD::Params());
void read( const FileNode& fn ); void read(const FileNode& fn);
void write( FileStorage& fs ) const; void write(FileStorage& fs) const;
protected: protected:
class Pexpert{ class Pexpert
{
public: public:
Pexpert(const Mat& img,const Mat& imgBlurred,Rect2d& resultBox,const TLDDetector* detector,TrackerTLD::Params params,Size initSize): Pexpert(const Mat& img, const Mat& imgBlurred, Rect2d& resultBox, const TLDDetector* detector, TrackerTLD::Params params, Size initSize):
img_(img),imgBlurred_(imgBlurred),resultBox_(resultBox),detector_(detector),params_(params),initSize_(initSize){} img_(img), imgBlurred_(imgBlurred), resultBox_(resultBox), detector_(detector), params_(params), initSize_(initSize){}
bool operator()(Rect2d /*box*/){return false;} bool operator()(Rect2d /*box*/){ return false; }
int additionalExamples(std::vector<Mat_<uchar> >& examplesForModel,std::vector<Mat_<uchar> >& examplesForEnsemble); int additionalExamples(std::vector<Mat_<uchar> >& examplesForModel, std::vector<Mat_<uchar> >& examplesForEnsemble);
protected: protected:
Pexpert(){} Pexpert(){}
Mat img_,imgBlurred_; Mat img_, imgBlurred_;
Rect2d resultBox_; Rect2d resultBox_;
const TLDDetector* detector_; const TLDDetector* detector_;
TrackerTLD::Params params_; TrackerTLD::Params params_;
...@@ -226,17 +226,22 @@ class TrackerTLDImpl : public TrackerTLD ...@@ -226,17 +226,22 @@ class TrackerTLDImpl : public TrackerTLD
Size initSize_; Size initSize_;
}; };
class Nexpert : public Pexpert{ class Nexpert : public Pexpert
{
public: public:
Nexpert(const Mat& img,Rect2d& resultBox,const TLDDetector* detector,TrackerTLD::Params params){ Nexpert(const Mat& img, Rect2d& resultBox, const TLDDetector* detector, TrackerTLD::Params params)
img_ = img; resultBox_ = resultBox; detector_ = detector; params_ = params;} {
img_ = img; resultBox_ = resultBox; detector_ = detector; params_ = params;
}
bool operator()(Rect2d box); bool operator()(Rect2d box);
int additionalExamples(std::vector<Mat_<uchar> >& examplesForModel,std::vector<Mat_<uchar> >& examplesForEnsemble){ int additionalExamples(std::vector<Mat_<uchar> >& examplesForModel, std::vector<Mat_<uchar> >& examplesForEnsemble)
examplesForModel.clear();examplesForEnsemble.clear();return 0;} {
examplesForModel.clear(); examplesForEnsemble.clear(); return 0;
}
}; };
bool initImpl( const Mat& image, const Rect2d& boundingBox ); bool initImpl(const Mat& image, const Rect2d& boundingBox);
bool updateImpl( const Mat& image, Rect2d& boundingBox ); bool updateImpl(const Mat& image, Rect2d& boundingBox);
TrackerTLD::Params params; TrackerTLD::Params params;
Ptr<Data> data; Ptr<Data> data;
...@@ -244,75 +249,74 @@ class TrackerTLDImpl : public TrackerTLD ...@@ -244,75 +249,74 @@ class TrackerTLDImpl : public TrackerTLD
Ptr<TLDDetector> detector; Ptr<TLDDetector> detector;
}; };
TrackerTLD::Params::Params(){}
TrackerTLD::Params::Params(){ void TrackerTLD::Params::read(const cv::FileNode& /*fn*/){}
}
void TrackerTLD::Params::read( const cv::FileNode& /*fn*/ ){
}
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::createTracker(const TrackerTLD::Params &parameters)
{
return Ptr<TrackerTLDImpl>(new TrackerTLDImpl(parameters)); return Ptr<TrackerTLDImpl>(new TrackerTLDImpl(parameters));
} }
TrackerTLDImpl::TrackerTLDImpl(const TrackerTLD::Params &parameters) : TrackerTLDImpl::TrackerTLDImpl(const TrackerTLD::Params &parameters) :
params( parameters ){ params( parameters )
{
isInit = false; isInit = false;
trackerProxy = Ptr<TrackerProxyImpl<TrackerMedianFlow,TrackerMedianFlow::Params> > trackerProxy = Ptr<TrackerProxyImpl<TrackerMedianFlow, TrackerMedianFlow::Params> >
(new TrackerProxyImpl<TrackerMedianFlow,TrackerMedianFlow::Params>()); (new TrackerProxyImpl<TrackerMedianFlow, TrackerMedianFlow::Params>());
} }
void TrackerTLDImpl::read( const cv::FileNode& fn ) void TrackerTLDImpl::read(const cv::FileNode& fn)
{ {
params.read( fn ); params.read( fn );
} }
void TrackerTLDImpl::write( cv::FileStorage& fs ) const void TrackerTLDImpl::write(cv::FileStorage& fs) const
{ {
params.write( fs ); params.write( fs );
} }
bool TrackerTLDImpl::initImpl(const Mat& image, const Rect2d& boundingBox ){ bool TrackerTLDImpl::initImpl(const Mat& image, const Rect2d& boundingBox)
{
Mat image_gray; Mat image_gray;
trackerProxy->init(image,boundingBox); trackerProxy->init(image, boundingBox);
cvtColor( image, image_gray, COLOR_BGR2GRAY ); cvtColor( image, image_gray, COLOR_BGR2GRAY );
data = Ptr<Data>(new Data(boundingBox)); data = Ptr<Data>(new Data(boundingBox));
double scale = data->getScale(); double scale = data->getScale();
Rect2d myBoundingBox = boundingBox; Rect2d myBoundingBox = boundingBox;
if(scale > 1.0) if( scale > 1.0 )
{ {
Mat image_proxy; Mat image_proxy;
resize(image_gray,image_proxy,Size(cvRound(image.cols * scale),cvRound(image.rows * scale)),0,0,DOWNSCALE_MODE); resize(image_gray, image_proxy, Size(cvRound(image.cols * scale), cvRound(image.rows * scale)), 0, 0, DOWNSCALE_MODE);
image_proxy.copyTo(image_gray); image_proxy.copyTo(image_gray);
myBoundingBox.x *= scale; myBoundingBox.x *= scale;
myBoundingBox.y *= scale; myBoundingBox.y *= scale;
myBoundingBox.width *= scale; myBoundingBox.width *= scale;
myBoundingBox.height *= scale; myBoundingBox.height *= scale;
} }
model = Ptr<TrackerTLDModel>(new TrackerTLDModel(params,image_gray,myBoundingBox,data->getMinSize())); model = Ptr<TrackerTLDModel>(new TrackerTLDModel(params, image_gray, myBoundingBox, data->getMinSize()));
detector = Ptr<TLDDetector>(new TLDDetector(params,model)); detector = Ptr<TLDDetector>(new TLDDetector(params, model));
data->confident = false; data->confident = false;
data->failedLastTime = false; data->failedLastTime = false;
return true; return true;
} }
bool TrackerTLDImpl::updateImpl(const Mat& image, Rect2d& boundingBox){ bool TrackerTLDImpl::updateImpl(const Mat& image, Rect2d& boundingBox)
Mat image_gray,image_blurred,imageForDetector; {
Mat image_gray, image_blurred, imageForDetector;
cvtColor( image, image_gray, COLOR_BGR2GRAY ); cvtColor( image, image_gray, COLOR_BGR2GRAY );
double scale = data->getScale(); double scale = data->getScale();
if(scale > 1.0){ if( scale > 1.0 )
resize(image_gray,imageForDetector,Size(cvRound(image.cols*scale),cvRound(image.rows*scale)),0,0,DOWNSCALE_MODE); resize(image_gray, imageForDetector, Size(cvRound(image.cols*scale), cvRound(image.rows*scale)), 0, 0, DOWNSCALE_MODE);
}else{ else
imageForDetector = image_gray; imageForDetector = image_gray;
} GaussianBlur(imageForDetector, image_blurred, GaussBlurKernelSize, 0.0);
GaussianBlur(imageForDetector,image_blurred,GaussBlurKernelSize,0.0);
TrackerTLDModel* tldModel = ((TrackerTLDModel*)static_cast<TrackerModel*>(model)); TrackerTLDModel* tldModel = ((TrackerTLDModel*)static_cast<TrackerModel*>(model));
data->frameNum++; data->frameNum++;
Mat_<uchar> standardPatch(STANDARD_PATCH_SIZE,STANDARD_PATCH_SIZE); Mat_<uchar> standardPatch(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE);
std::vector<TLDDetector::LabeledPatch> detectorResults; std::vector<TLDDetector::LabeledPatch> detectorResults;
//best overlap around 92% //best overlap around 92%
...@@ -322,169 +326,187 @@ bool TrackerTLDImpl::updateImpl(const Mat& image, Rect2d& boundingBox){ ...@@ -322,169 +326,187 @@ bool TrackerTLDImpl::updateImpl(const Mat& image, Rect2d& boundingBox){
for( int i = 0; i < 2; i++ ) for( int i = 0; i < 2; i++ )
{ {
Rect2d tmpCandid = boundingBox; Rect2d tmpCandid = boundingBox;
if(((i == 0)&& !(data->failedLastTime)&& trackerProxy->update(image,tmpCandid)) || if( ( (i == 0) && !(data->failedLastTime) && trackerProxy->update(image, tmpCandid) ) ||
((i == 1)&& (detector->detect(imageForDetector,image_blurred,tmpCandid,detectorResults)))){ ( (i == 1) && detector->detect(imageForDetector, image_blurred, tmpCandid, detectorResults) ) )
{
candidates.push_back(tmpCandid); candidates.push_back(tmpCandid);
if(i == 0){ if( i == 0 )
resample(image_gray,tmpCandid,standardPatch); resample(image_gray, tmpCandid, standardPatch);
}else{ else
resample(imageForDetector,tmpCandid,standardPatch); resample(imageForDetector, tmpCandid, standardPatch);
}
candidatesRes.push_back(tldModel->Sc(standardPatch)); candidatesRes.push_back(tldModel->Sc(standardPatch));
}else{ }
if(i == 0){ else
{
if( i == 0 )
trackerNeedsReInit = true; trackerNeedsReInit = true;
}
} }
} }
std::vector<double>::iterator it = std::max_element(candidatesRes.begin(),candidatesRes.end()); std::vector<double>::iterator it = std::max_element(candidatesRes.begin(), candidatesRes.end());
dfprintf((stdout,"scale = %f\n",log(1.0 * boundingBox.width / (data->getMinSize()).width) / log(SCALE_STEP))); dfprintf((stdout, "scale = %f\n", log(1.0 * boundingBox.width / (data->getMinSize()).width) / log(SCALE_STEP)));
for(int i = 0;i < (int)candidatesRes.size();i++){ for( int i = 0; i < (int)candidatesRes.size(); i++ )
dprintf(("\tcandidatesRes[%d] = %f\n",i,candidatesRes[i])); dprintf(("\tcandidatesRes[%d] = %f\n", i, candidatesRes[i]));
}
data->printme(); data->printme();
tldModel->printme(stdout); tldModel->printme(stdout);
if(it == candidatesRes.end()){ if( it == candidatesRes.end() )
{
data->confident = false; data->confident = false;
data->failedLastTime = true; data->failedLastTime = true;
return false; return false;
}else{ }
else
{
boundingBox = candidates[it - candidatesRes.begin()]; boundingBox = candidates[it - candidatesRes.begin()];
data->failedLastTime = false; data->failedLastTime = false;
if(trackerNeedsReInit || it != candidatesRes.begin()){ if( trackerNeedsReInit || it != candidatesRes.begin() )
trackerProxy->init(image,boundingBox); trackerProxy->init(image, boundingBox);
}
} }
#if 1 #if 1
if(it != candidatesRes.end()){ if( it != candidatesRes.end() )
resample(imageForDetector,candidates[it - candidatesRes.begin()],standardPatch); {
dfprintf((stderr,"%d %f %f\n",data->frameNum,tldModel->Sc(standardPatch),tldModel->Sr(standardPatch))); resample(imageForDetector, candidates[it - candidatesRes.begin()], standardPatch);
if(candidatesRes.size() == 2 && it == (candidatesRes.begin() + 1)) dfprintf((stderr, "%d %f %f\n", data->frameNum, tldModel->Sc(standardPatch), tldModel->Sr(standardPatch)));
dfprintf((stderr,"detector WON\n")); if( candidatesRes.size() == 2 && it == (candidatesRes.begin() + 1) )
}else{ dfprintf((stderr, "detector WON\n"));
dfprintf((stderr,"%d x x\n",data->frameNum)); }
else
{
dfprintf((stderr, "%d x x\n", data->frameNum));
} }
#endif #endif
if(*it > CORE_THRESHOLD){ if( *it > CORE_THRESHOLD )
data->confident = true; data->confident = true;
}
if(data->confident){ if( data->confident )
Pexpert pExpert(imageForDetector,image_blurred,boundingBox,detector,params,data->getMinSize()); {
Nexpert nExpert(imageForDetector,boundingBox,detector,params); Pexpert pExpert(imageForDetector, image_blurred, boundingBox, detector, params, data->getMinSize());
std::vector<Mat_<uchar> > examplesForModel,examplesForEnsemble; Nexpert nExpert(imageForDetector, boundingBox, detector, params);
examplesForModel.reserve(100);examplesForEnsemble.reserve(100); std::vector<Mat_<uchar> > examplesForModel, examplesForEnsemble;
examplesForModel.reserve(100); examplesForEnsemble.reserve(100);
int negRelabeled = 0; int negRelabeled = 0;
for(int i = 0;i < (int)detectorResults.size();i++){ for( int i = 0; i < (int)detectorResults.size(); i++ )
{
bool expertResult; bool expertResult;
if(detectorResults[i].isObject){ if( detectorResults[i].isObject )
{
expertResult = nExpert(detectorResults[i].rect); expertResult = nExpert(detectorResults[i].rect);
if(expertResult != detectorResults[i].isObject){negRelabeled++;} if( expertResult != detectorResults[i].isObject ){ negRelabeled++; }
}else{ }
else
{
expertResult = pExpert(detectorResults[i].rect); expertResult = pExpert(detectorResults[i].rect);
} }
detectorResults[i].shouldBeIntegrated = detectorResults[i].shouldBeIntegrated || (detectorResults[i].isObject != expertResult); detectorResults[i].shouldBeIntegrated = detectorResults[i].shouldBeIntegrated || (detectorResults[i].isObject != expertResult);
detectorResults[i].isObject = expertResult; detectorResults[i].isObject = expertResult;
} }
tldModel->integrateRelabeled(imageForDetector,image_blurred,detectorResults); tldModel->integrateRelabeled(imageForDetector, image_blurred, detectorResults);
dprintf(("%d relabeled by nExpert\n",negRelabeled)); dprintf(("%d relabeled by nExpert\n", negRelabeled));
pExpert.additionalExamples(examplesForModel,examplesForEnsemble); pExpert.additionalExamples(examplesForModel, examplesForEnsemble);
tldModel->integrateAdditional(examplesForModel,examplesForEnsemble,true); tldModel->integrateAdditional(examplesForModel, examplesForEnsemble, true);
examplesForModel.clear();examplesForEnsemble.clear(); examplesForModel.clear(); examplesForEnsemble.clear();
nExpert.additionalExamples(examplesForModel,examplesForEnsemble); nExpert.additionalExamples(examplesForModel, examplesForEnsemble);
tldModel->integrateAdditional(examplesForModel,examplesForEnsemble,false); tldModel->integrateAdditional(examplesForModel, examplesForEnsemble, false);
}else{ }
else
{
#ifdef CLOSED_LOOP #ifdef CLOSED_LOOP
tldModel->integrateRelabeled(imageForDetector,image_blurred,detectorResults); tldModel->integrateRelabeled(imageForDetector, image_blurred, detectorResults);
#endif #endif
} }
return true; return true;
} }
TrackerTLDModel::TrackerTLDModel(TrackerTLD::Params params,const Mat& image, const Rect2d& boundingBox,Size minSize):minSize_(minSize), TrackerTLDModel::TrackerTLDModel(TrackerTLD::Params params, const Mat& image, const Rect2d& boundingBox, Size minSize):minSize_(minSize),
timeStampPositiveNext(0),timeStampNegativeNext(0),params_(params),boundingBox_(boundingBox){ timeStampPositiveNext(0), timeStampNegativeNext(0), params_(params), boundingBox_(boundingBox)
{
originalVariance_ = variance(image(boundingBox)); originalVariance_ = variance(image(boundingBox));
std::vector<Rect2d> closest,scanGrid; std::vector<Rect2d> closest, scanGrid;
Mat scaledImg,blurredImg,image_blurred; Mat scaledImg, blurredImg, image_blurred;
double scale = scaleAndBlur(image,cvRound(log(1.0 * boundingBox.width / (minSize.width)) / log(SCALE_STEP)), double scale = scaleAndBlur(image, cvRound(log(1.0 * boundingBox.width / (minSize.width)) / log(SCALE_STEP)),
scaledImg,blurredImg,GaussBlurKernelSize,SCALE_STEP); scaledImg, blurredImg, GaussBlurKernelSize, SCALE_STEP);
GaussianBlur(image,image_blurred,GaussBlurKernelSize,0.0); GaussianBlur(image, image_blurred, GaussBlurKernelSize, 0.0);
TLDDetector::generateScanGrid(image.rows,image.cols,minSize,scanGrid); TLDDetector::generateScanGrid(image.rows, image.cols, minSize, scanGrid);
getClosestN(scanGrid,Rect2d(boundingBox.x / scale,boundingBox.y / scale,boundingBox.width / scale,boundingBox.height / scale),10,closest); getClosestN(scanGrid, Rect2d(boundingBox.x / scale, boundingBox.y / scale, boundingBox.width / scale, boundingBox.height / scale), 10, closest);
Mat_<uchar> blurredPatch(minSize); Mat_<uchar> blurredPatch(minSize);
TLDEnsembleClassifier::makeClassifiers(minSize,MEASURES_PER_CLASSIFIER,GRIDSIZE,classifiers); TLDEnsembleClassifier::makeClassifiers(minSize, MEASURES_PER_CLASSIFIER, GRIDSIZE, classifiers);
positiveExamples.reserve(200); positiveExamples.reserve(200);
for(int i = 0;i < (int)closest.size();i++){ for( int i = 0; i < (int)closest.size(); i++ )
for(int j = 0;j < 20;j++){ {
for( int j = 0; j < 20; j++ )
{
Point2f center; Point2f center;
Size2f size; Size2f size;
Mat_<uchar> standardPatch(STANDARD_PATCH_SIZE,STANDARD_PATCH_SIZE); Mat_<uchar> standardPatch(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE);
center.x = (float)(closest[i].x + closest[i].width * (0.5 + rng.uniform(-0.01,0.01))); center.x = (float)(closest[i].x + closest[i].width * (0.5 + rng.uniform(-0.01, 0.01)));
center.y = (float)(closest[i].y + closest[i].height * (0.5 + rng.uniform(-0.01,0.01))); center.y = (float)(closest[i].y + closest[i].height * (0.5 + rng.uniform(-0.01, 0.01)));
size.width = (float)(closest[i].width * rng.uniform((double)0.99,(double)1.01)); size.width = (float)(closest[i].width * rng.uniform((double)0.99, (double)1.01));
size.height = (float)(closest[i].height * rng.uniform((double)0.99,(double)1.01)); size.height = (float)(closest[i].height * rng.uniform((double)0.99, (double)1.01));
float angle = (float)rng.uniform(-10.0,10.0); float angle = (float)rng.uniform(-10.0, 10.0);
resample(scaledImg,RotatedRect(center,size,angle),standardPatch); resample(scaledImg, RotatedRect(center, size, angle), standardPatch);
for(int y = 0;y < standardPatch.rows;y++){ for( int y = 0; y < standardPatch.rows; y++ )
for(int x = 0;x < standardPatch.cols;x++){ {
standardPatch(x,y) += (uchar)rng.gaussian(5.0); for( int x = 0; x < standardPatch.cols; x++ )
{
standardPatch(x, y) += (uchar)rng.gaussian(5.0);
} }
} }
#ifdef BLUR_AS_VADIM #ifdef BLUR_AS_VADIM
GaussianBlur(standardPatch,blurredPatch,GaussBlurKernelSize,0.0); GaussianBlur(standardPatch, blurredPatch, GaussBlurKernelSize, 0.0);
resize(blurredPatch,blurredPatch,minSize); resize(blurredPatch, blurredPatch, minSize);
#else #else
resample(blurredImg,RotatedRect(center,size,angle),blurredPatch); resample(blurredImg, RotatedRect(center, size, angle), blurredPatch);
#endif #endif
pushIntoModel(standardPatch,true); pushIntoModel(standardPatch, true);
for(int k = 0;k < (int)classifiers.size();k++){ for( int k = 0; k < (int)classifiers.size(); k++ )
classifiers[k].integrate(blurredPatch,true); classifiers[k].integrate(blurredPatch, true);
}
} }
} }
TLDDetector::generateScanGrid(image.rows,image.cols,minSize,scanGrid,true); TLDDetector::generateScanGrid(image.rows, image.cols, minSize, scanGrid, true);
negativeExamples.clear(); negativeExamples.clear();
negativeExamples.reserve(NEG_EXAMPLES_IN_INIT_MODEL); negativeExamples.reserve(NEG_EXAMPLES_IN_INIT_MODEL);
std::vector<int> indices; std::vector<int> indices;
indices.reserve(NEG_EXAMPLES_IN_INIT_MODEL); indices.reserve(NEG_EXAMPLES_IN_INIT_MODEL);
while(negativeExamples.size() < NEG_EXAMPLES_IN_INIT_MODEL){ while( negativeExamples.size() < NEG_EXAMPLES_IN_INIT_MODEL )
int i = rng.uniform((int)0,(int)scanGrid.size()); {
if(std::find(indices.begin(),indices.end(),i) == indices.end() && overlap(boundingBox,scanGrid[i]) < 0.2){ int i = rng.uniform((int)0, (int)scanGrid.size());
Mat_<uchar> standardPatch(STANDARD_PATCH_SIZE,STANDARD_PATCH_SIZE); if( std::find(indices.begin(), indices.end(), i) == indices.end() && overlap(boundingBox, scanGrid[i]) < NEXPERT_THRESHOLD )
resample(image,scanGrid[i],standardPatch); {
pushIntoModel(standardPatch,false); Mat_<uchar> standardPatch(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE);
resample(image, scanGrid[i], standardPatch);
resample(image_blurred,scanGrid[i],blurredPatch); pushIntoModel(standardPatch, false);
for(int k = 0;k < (int)classifiers.size();k++){
classifiers[k].integrate(blurredPatch,false); resample(image_blurred, scanGrid[i], blurredPatch);
} for( int k = 0; k < (int)classifiers.size(); k++ )
classifiers[k].integrate(blurredPatch, false);
} }
} }
dprintf(("positive patches: %d\nnegative patches: %d\n",(int)positiveExamples.size(),(int)negativeExamples.size())); dprintf(("positive patches: %d\nnegative patches: %d\n", (int)positiveExamples.size(), (int)negativeExamples.size()));
} }
void TLDDetector::generateScanGrid(int rows,int cols,Size initBox,std::vector<Rect2d>& res,bool withScaling){ void TLDDetector::generateScanGrid(int rows, int cols, Size initBox, std::vector<Rect2d>& res, bool withScaling)
{
res.clear(); res.clear();
//scales step: SCALE_STEP; hor step: 10% of width; verstep: 10% of height; minsize: 20pix //scales step: SCALE_STEP; hor step: 10% of width; verstep: 10% of height; minsize: 20pix
for(double h = initBox.height, w = initBox.width;h < cols && w < rows;){ for( double h = initBox.height, w = initBox.width; h < cols && w < rows; )
for( double x = 0; (x + w + 1.0) <= cols; x += (0.1 * w)) {
for( double x = 0; (x + w + 1.0) <= cols; x += (0.1 * w) )
{ {
for(double y = 0; (y + h + 1.0) <= rows; y += (0.1 * h)) for( double y = 0; (y + h + 1.0) <= rows; y += (0.1 * h) )
res.push_back(Rect2d(x,y,w,h)); res.push_back(Rect2d(x, y, w, h));
} }
if( withScaling ) if( withScaling )
{ {
...@@ -494,7 +516,7 @@ void TLDDetector::generateScanGrid(int rows,int cols,Size initBox,std::vector<Re ...@@ -494,7 +516,7 @@ void TLDDetector::generateScanGrid(int rows,int cols,Size initBox,std::vector<Re
if( h < 20 || w < 20 ) if( h < 20 || w < 20 )
{ {
h = initBox.height * SCALE_STEP; w = initBox.width * SCALE_STEP; h = initBox.height * SCALE_STEP; w = initBox.width * SCALE_STEP;
CV_Assert(h > initBox.height || w > initBox.width); CV_Assert( h > initBox.height || w > initBox.width);
} }
} }
else else
...@@ -507,61 +529,66 @@ void TLDDetector::generateScanGrid(int rows,int cols,Size initBox,std::vector<Re ...@@ -507,61 +529,66 @@ void TLDDetector::generateScanGrid(int rows,int cols,Size initBox,std::vector<Re
break; break;
} }
} }
dprintf(("%d rects in res\n",(int)res.size())); dprintf(("%d rects in res\n", (int)res.size()));
} }
bool TLDDetector::detect(const Mat& img,const Mat& imgBlurred,Rect2d& res,std::vector<LabeledPatch>& patches){ bool TLDDetector::detect(const Mat& img, const Mat& imgBlurred, Rect2d& res, std::vector<LabeledPatch>& patches)
{
TrackerTLDModel* tldModel = ((TrackerTLDModel*)static_cast<TrackerModel*>(model)); TrackerTLDModel* tldModel = ((TrackerTLDModel*)static_cast<TrackerModel*>(model));
Size initSize = tldModel->getMinSize(); Size initSize = tldModel->getMinSize();
patches.clear(); patches.clear();
Mat resized_img,blurred_img; Mat resized_img, blurred_img;
Mat_<uchar> standardPatch(STANDARD_PATCH_SIZE,STANDARD_PATCH_SIZE); Mat_<uchar> standardPatch(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE);
img.copyTo(resized_img); img.copyTo(resized_img);
imgBlurred.copyTo(blurred_img); imgBlurred.copyTo(blurred_img);
double originalVariance = tldModel->getOriginalVariance();; double originalVariance = tldModel->getOriginalVariance(); ;
int dx = initSize.width / 10, dy = initSize.height / 10; int dx = initSize.width / 10, dy = initSize.height / 10;
Size2d size = img.size(); Size2d size = img.size();
double scale = 1.0; double scale = 1.0;
int total = 0,pass = 0; int total = 0, pass = 0;
int npos = 0,nneg = 0; int npos = 0, nneg = 0;
double tmp = 0,maxSc = -5.0; double tmp = 0, maxSc = -5.0;
Rect2d maxScRect; Rect2d maxScRect;
START_TICK("detector"); START_TICK("detector");
do do
{ {
Mat_<double> intImgP,intImgP2; Mat_<double> intImgP, intImgP2;
computeIntegralImages(resized_img,intImgP,intImgP2); computeIntegralImages(resized_img, intImgP, intImgP2);
tldModel->prepareClassifiers((int)blurred_img.step[0]); tldModel->prepareClassifiers((int)blurred_img.step[0]);
for(int i = 0,imax = cvFloor((0.0 + resized_img.cols - initSize.width) / dx);i < imax;i++){ for( int i = 0, imax = cvFloor((0.0 + resized_img.cols - initSize.width) / dx); i < imax; i++ )
for(int j = 0,jmax = cvFloor((0.0 + resized_img.rows - initSize.height) / dy);j < jmax;j++){ {
for( int j = 0, jmax = cvFloor((0.0 + resized_img.rows - initSize.height) / dy); j < jmax; j++ )
{
LabeledPatch labPatch; LabeledPatch labPatch;
total++; total++;
if(!patchVariance(intImgP,intImgP2,originalVariance,Point(dx * i,dy * j),initSize)){ if( !patchVariance(intImgP, intImgP2, originalVariance, Point(dx * i, dy * j), initSize) )
continue; continue;
} if( tldModel->ensembleClassifierNum(&blurred_img.at<uchar>(dy * j, dx * i)) <= ENSEMBLE_THRESHOLD )
if(!(tldModel->ensembleClassifierNum(&blurred_img.at<uchar>(dy * j,dx * i)) > ENSEMBLE_THRESHOLD)){
continue; continue;
}
pass++; pass++;
labPatch.rect = Rect2d(dx * i * scale,dy * j * scale,initSize.width * scale,initSize.height * scale); labPatch.rect = Rect2d(dx * i * scale, dy * j * scale, initSize.width * scale, initSize.height * scale);
resample(resized_img,Rect2d(Point(dx * i,dy * j),initSize),standardPatch); resample(resized_img, Rect2d(Point(dx * i, dy * j), initSize), standardPatch);
tmp = tldModel->Sr(standardPatch); tmp = tldModel->Sr(standardPatch);
labPatch.isObject = tmp > THETA_NN; labPatch.isObject = tmp > THETA_NN;
labPatch.shouldBeIntegrated = abs(tmp - THETA_NN) < 0.1; labPatch.shouldBeIntegrated = abs(tmp - THETA_NN) < 0.1;
patches.push_back(labPatch); patches.push_back(labPatch);
if(!labPatch.isObject){ if( !labPatch.isObject )
{
nneg++; nneg++;
continue; continue;
}else{ }
else
{
npos++; npos++;
} }
tmp = tldModel->Sc(standardPatch); tmp = tldModel->Sc(standardPatch);
if(tmp > maxSc){ if( tmp > maxSc )
{
maxSc = tmp; maxSc = tmp;
maxScRect = labPatch.rect; maxScRect = labPatch.rect;
} }
...@@ -571,53 +598,54 @@ bool TLDDetector::detect(const Mat& img,const Mat& imgBlurred,Rect2d& res,std::v ...@@ -571,53 +598,54 @@ bool TLDDetector::detect(const Mat& img,const Mat& imgBlurred,Rect2d& res,std::v
size.width /= SCALE_STEP; size.width /= SCALE_STEP;
size.height /= SCALE_STEP; size.height /= SCALE_STEP;
scale *= SCALE_STEP; scale *= SCALE_STEP;
resize(img,resized_img,size,0,0,DOWNSCALE_MODE); resize(img, resized_img, size, 0, 0, DOWNSCALE_MODE);
GaussianBlur(resized_img,blurred_img,GaussBlurKernelSize,0.0f); GaussianBlur(resized_img, blurred_img, GaussBlurKernelSize, 0.0f);
} }
while( size.width >= initSize.width && size.height >= initSize.height ); while( size.width >= initSize.width && size.height >= initSize.height );
END_TICK("detector"); END_TICK("detector");
dfprintf((stdout,"after NCC: nneg = %d npos = %d\n",nneg,npos)); dfprintf((stdout, "after NCC: nneg = %d npos = %d\n", nneg, npos));
#if !0 #if !0
std::vector<Rect2d> poss,negs; std::vector<Rect2d> poss, negs;
for(int i = 0;i < (int)patches.size();i++){ for( int i = 0; i < (int)patches.size(); i++ )
if(patches[i].isObject) {
if( patches[i].isObject )
poss.push_back(patches[i].rect); poss.push_back(patches[i].rect);
else else
negs.push_back(patches[i].rect); negs.push_back(patches[i].rect);
} }
dfprintf((stdout,"%d pos and %d neg\n",(int)poss.size(),(int)negs.size())); dfprintf((stdout, "%d pos and %d neg\n", (int)poss.size(), (int)negs.size()));
drawWithRects(img,negs,poss,"tech"); drawWithRects(img, negs, poss, "tech");
#endif #endif
dfprintf((stdout,"%d after ensemble\n",pass)); dfprintf((stdout, "%d after ensemble\n", pass));
if(maxSc < 0){ if( maxSc < 0 )
return false; return false;
}
res = maxScRect; res = maxScRect;
return true; return true;
} }
/** Computes the variance of subimage given by box, with the help of two integral /** Computes the variance of subimage given by box, with the help of two integral
* images intImgP and intImgP2 (sum of squares), which should be also provided.*/ * images intImgP and intImgP2 (sum of squares), which should be also provided.*/
bool TLDDetector::patchVariance(Mat_<double>& intImgP,Mat_<double>& intImgP2,double originalVariance,Point pt,Size size){ bool TLDDetector::patchVariance(Mat_<double>& intImgP, Mat_<double>& intImgP2, double originalVariance, Point pt, Size size)
int x = (pt.x),y = (pt.y),width = (size.width),height = (size.height); {
int x = (pt.x), y = (pt.y), width = (size.width), height = (size.height);
CV_Assert( 0 <= x && (x + width) < intImgP.cols && (x + width) < intImgP2.cols ); CV_Assert( 0 <= x && (x + width) < intImgP.cols && (x + width) < intImgP2.cols );
CV_Assert( 0 <= y && (y + height) < intImgP.rows && (y + height) < intImgP2.rows ); CV_Assert( 0 <= y && (y + height) < intImgP.rows && (y + height) < intImgP2.rows );
double p = 0,p2 = 0; double p = 0, p2 = 0;
double A,B,C,D; double A, B, C, D;
A = intImgP(y,x); A = intImgP(y, x);
B = intImgP(y,x + width); B = intImgP(y, x + width);
C = intImgP(y + height,x); C = intImgP(y + height, x);
D = intImgP(y + height,x + width); D = intImgP(y + height, x + width);
p = (A + D - B - C) / (width * height); p = (A + D - B - C) / (width * height);
A = intImgP2(y,x); A = intImgP2(y, x);
B = intImgP2(y,x + width); B = intImgP2(y, x + width);
C = intImgP2(y + height,x); C = intImgP2(y + height, x);
D = intImgP2(y + height,x + width); D = intImgP2(y + height, x + width);
p2 = (A + D - B - C) / (width * height); p2 = (A + D - B - C) / (width * height);
return ((p2 - p * p) > VARIANCE_THRESHOLD * originalVariance); return ((p2 - p * p) > VARIANCE_THRESHOLD * originalVariance);
...@@ -636,9 +664,9 @@ double TrackerTLDModel::Sr(const Mat_<uchar>& patch) ...@@ -636,9 +664,9 @@ double TrackerTLDModel::Sr(const Mat_<uchar>& patch)
{ {
double splus = 0.0, sminus = 0.0; double splus = 0.0, sminus = 0.0;
for( int i = 0; i < (int)positiveExamples.size(); i++ ) for( int i = 0; i < (int)positiveExamples.size(); i++ )
splus = std::max(splus, 0.5 * (NCC(positiveExamples[i],patch) + 1.0)); splus = std::max(splus, 0.5 * (NCC(positiveExamples[i], patch) + 1.0));
for( int i = 0; i < (int)negativeExamples.size(); i++ ) for( int i = 0; i < (int)negativeExamples.size(); i++ )
sminus = std::max(sminus, 0.5 * (NCC(negativeExamples[i],patch) + 1.0)); sminus = std::max(sminus, 0.5 * (NCC(negativeExamples[i], patch) + 1.0));
if( splus + sminus == 0.0) if( splus + sminus == 0.0)
return 0.0; return 0.0;
return splus / (sminus + splus); return splus / (sminus + splus);
...@@ -646,38 +674,38 @@ double TrackerTLDModel::Sr(const Mat_<uchar>& patch) ...@@ -646,38 +674,38 @@ double TrackerTLDModel::Sr(const Mat_<uchar>& patch)
double TrackerTLDModel::Sc(const Mat_<uchar>& patch) double TrackerTLDModel::Sc(const Mat_<uchar>& patch)
{ {
double splus = 0.0,sminus = 0.0; double splus = 0.0, sminus = 0.0;
int med = getMedian(timeStampsPositive); int med = getMedian(timeStampsPositive);
for( int i = 0; i < (int)positiveExamples.size(); i++ ) for( int i = 0; i < (int)positiveExamples.size(); i++ )
{ {
if( (int)timeStampsPositive[i] <= med ) if( (int)timeStampsPositive[i] <= med )
splus = std::max(splus, 0.5 * (NCC(positiveExamples[i],patch) + 1.0)); splus = std::max(splus, 0.5 * (NCC(positiveExamples[i], patch) + 1.0));
} }
for( int i = 0; i < (int)negativeExamples.size(); i++ ) for( int i = 0; i < (int)negativeExamples.size(); i++ )
sminus = std::max(sminus, 0.5 * (NCC(negativeExamples[i],patch) + 1.0)); sminus = std::max(sminus, 0.5 * (NCC(negativeExamples[i], patch) + 1.0));
if( splus + sminus == 0.0 ) if( splus + sminus == 0.0 )
return 0.0; return 0.0;
return splus / (sminus + splus); return splus / (sminus + splus);
} }
void TrackerTLDModel::integrateRelabeled(Mat& img,Mat& imgBlurred,const std::vector<TLDDetector::LabeledPatch>& patches) void TrackerTLDModel::integrateRelabeled(Mat& img, Mat& imgBlurred, const std::vector<TLDDetector::LabeledPatch>& patches)
{ {
Mat_<uchar> standardPatch(STANDARD_PATCH_SIZE,STANDARD_PATCH_SIZE),blurredPatch(minSize_); Mat_<uchar> standardPatch(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE), blurredPatch(minSize_);
int positiveIntoModel = 0,negativeIntoModel = 0,positiveIntoEnsemble = 0,negativeIntoEnsemble = 0; int positiveIntoModel = 0, negativeIntoModel = 0, positiveIntoEnsemble = 0, negativeIntoEnsemble = 0;
for( int k = 0; k < (int)patches.size(); k++ ) for( int k = 0; k < (int)patches.size(); k++ )
{ {
if( patches[k].shouldBeIntegrated ) if( patches[k].shouldBeIntegrated )
{ {
resample(img,patches[k].rect,standardPatch); resample(img, patches[k].rect, standardPatch);
if( patches[k].isObject ) if( patches[k].isObject )
{ {
positiveIntoModel++; positiveIntoModel++;
pushIntoModel(standardPatch,true); pushIntoModel(standardPatch, true);
} }
else else
{ {
negativeIntoModel++; negativeIntoModel++;
pushIntoModel(standardPatch,false); pushIntoModel(standardPatch, false);
} }
} }
...@@ -687,31 +715,29 @@ void TrackerTLDModel::integrateRelabeled(Mat& img,Mat& imgBlurred,const std::vec ...@@ -687,31 +715,29 @@ void TrackerTLDModel::integrateRelabeled(Mat& img,Mat& imgBlurred,const std::vec
if( patches[k].shouldBeIntegrated ) if( patches[k].shouldBeIntegrated )
#endif #endif
{ {
resample(imgBlurred,patches[k].rect,blurredPatch); resample(imgBlurred, patches[k].rect, blurredPatch);
if( patches[k].isObject ) if( patches[k].isObject )
positiveIntoEnsemble++; positiveIntoEnsemble++;
else else
negativeIntoEnsemble++; negativeIntoEnsemble++;
for( int i = 0; i < (int)classifiers.size(); i++ ) for( int i = 0; i < (int)classifiers.size(); i++ )
{ classifiers[i].integrate(blurredPatch, patches[k].isObject);
classifiers[i].integrate(blurredPatch,patches[k].isObject);
}
} }
} }
if( negativeIntoModel > 0 ) if( negativeIntoModel > 0 )
dfprintf((stdout,"negativeIntoModel = %d ",negativeIntoModel)); dfprintf((stdout, "negativeIntoModel = %d ", negativeIntoModel));
if( positiveIntoModel > 0) if( positiveIntoModel > 0)
dfprintf((stdout,"positiveIntoModel = %d ",positiveIntoModel)); dfprintf((stdout, "positiveIntoModel = %d ", positiveIntoModel));
if( negativeIntoEnsemble > 0 ) if( negativeIntoEnsemble > 0 )
dfprintf((stdout,"negativeIntoEnsemble = %d ",negativeIntoEnsemble)); dfprintf((stdout, "negativeIntoEnsemble = %d ", negativeIntoEnsemble));
if( positiveIntoEnsemble > 0 ) if( positiveIntoEnsemble > 0 )
dfprintf((stdout,"positiveIntoEnsemble = %d ",positiveIntoEnsemble)); dfprintf((stdout, "positiveIntoEnsemble = %d ", positiveIntoEnsemble));
dfprintf((stdout,"\n")); dfprintf((stdout, "\n"));
} }
void TrackerTLDModel::integrateAdditional(const std::vector<Mat_<uchar> >& eForModel,const std::vector<Mat_<uchar> >& eForEnsemble,bool isPositive) void TrackerTLDModel::integrateAdditional(const std::vector<Mat_<uchar> >& eForModel, const std::vector<Mat_<uchar> >& eForEnsemble, bool isPositive)
{ {
int positiveIntoModel = 0,negativeIntoModel = 0,positiveIntoEnsemble = 0,negativeIntoEnsemble = 0; int positiveIntoModel = 0, negativeIntoModel = 0, positiveIntoEnsemble = 0, negativeIntoEnsemble = 0;
for( int k = 0; k < (int)eForModel.size(); k++ ) for( int k = 0; k < (int)eForModel.size(); k++ )
{ {
double sr = Sr(eForModel[k]); double sr = Sr(eForModel[k]);
...@@ -720,17 +746,17 @@ void TrackerTLDModel::integrateAdditional(const std::vector<Mat_<uchar> >& eForM ...@@ -720,17 +746,17 @@ void TrackerTLDModel::integrateAdditional(const std::vector<Mat_<uchar> >& eForM
if( isPositive ) if( isPositive )
{ {
positiveIntoModel++; positiveIntoModel++;
pushIntoModel(eForModel[k],true); pushIntoModel(eForModel[k], true);
} }
else else
{ {
negativeIntoModel++; negativeIntoModel++;
pushIntoModel(eForModel[k],false); pushIntoModel(eForModel[k], false);
} }
} }
double p = 0; double p = 0;
for( int i = 0; i < (int)classifiers.size(); i++ ) for( int i = 0; i < (int)classifiers.size(); i++ )
p += classifiers[i].posteriorProbability(eForEnsemble[k].data,(int)eForEnsemble[k].step[0]); p += classifiers[i].posteriorProbability(eForEnsemble[k].data, (int)eForEnsemble[k].step[0]);
p /= classifiers.size(); p /= classifiers.size();
if( (p > ENSEMBLE_THRESHOLD) != isPositive ) if( (p > ENSEMBLE_THRESHOLD) != isPositive )
{ {
...@@ -739,32 +765,32 @@ void TrackerTLDModel::integrateAdditional(const std::vector<Mat_<uchar> >& eForM ...@@ -739,32 +765,32 @@ void TrackerTLDModel::integrateAdditional(const std::vector<Mat_<uchar> >& eForM
else else
negativeIntoEnsemble++; negativeIntoEnsemble++;
for( int i = 0; i < (int)classifiers.size(); i++ ) for( int i = 0; i < (int)classifiers.size(); i++ )
classifiers[i].integrate(eForEnsemble[k],isPositive); classifiers[i].integrate(eForEnsemble[k], isPositive);
} }
} }
if( negativeIntoModel > 0 ) if( negativeIntoModel > 0 )
dfprintf((stdout,"negativeIntoModel = %d ",negativeIntoModel)); dfprintf((stdout, "negativeIntoModel = %d ", negativeIntoModel));
if( positiveIntoModel > 0 ) if( positiveIntoModel > 0 )
dfprintf((stdout,"positiveIntoModel = %d ",positiveIntoModel)); dfprintf((stdout, "positiveIntoModel = %d ", positiveIntoModel));
if( negativeIntoEnsemble > 0 ) if( negativeIntoEnsemble > 0 )
dfprintf((stdout,"negativeIntoEnsemble = %d ",negativeIntoEnsemble)); dfprintf((stdout, "negativeIntoEnsemble = %d ", negativeIntoEnsemble));
if( positiveIntoEnsemble > 0 ) if( positiveIntoEnsemble > 0 )
dfprintf((stdout,"positiveIntoEnsemble = %d ",positiveIntoEnsemble)); dfprintf((stdout, "positiveIntoEnsemble = %d ", positiveIntoEnsemble));
dfprintf((stdout,"\n")); dfprintf((stdout, "\n"));
} }
int TrackerTLDImpl::Pexpert::additionalExamples(std::vector<Mat_<uchar > >& examplesForModel,std::vector<Mat_<uchar > >& examplesForEnsemble) int TrackerTLDImpl::Pexpert::additionalExamples(std::vector<Mat_<uchar> >& examplesForModel, std::vector<Mat_<uchar> >& examplesForEnsemble)
{ {
examplesForModel.clear();examplesForEnsemble.clear(); examplesForModel.clear(); examplesForEnsemble.clear();
examplesForModel.reserve(100);examplesForEnsemble.reserve(100); examplesForModel.reserve(100); examplesForEnsemble.reserve(100);
std::vector<Rect2d> closest,scanGrid; std::vector<Rect2d> closest, scanGrid;
Mat scaledImg,blurredImg; Mat scaledImg, blurredImg;
double scale = scaleAndBlur(img_,cvRound(log(1.0 * resultBox_.width / (initSize_.width)) / log(SCALE_STEP)), double scale = scaleAndBlur(img_, cvRound(log(1.0 * resultBox_.width / (initSize_.width)) / log(SCALE_STEP)),
scaledImg,blurredImg,GaussBlurKernelSize,SCALE_STEP); scaledImg, blurredImg, GaussBlurKernelSize, SCALE_STEP);
TLDDetector::generateScanGrid(img_.rows,img_.cols,initSize_,scanGrid); TLDDetector::generateScanGrid(img_.rows, img_.cols, initSize_, scanGrid);
getClosestN(scanGrid,Rect2d(resultBox_.x / scale,resultBox_.y / scale,resultBox_.width / scale,resultBox_.height / scale),10,closest); getClosestN(scanGrid, Rect2d(resultBox_.x / scale, resultBox_.y / scale, resultBox_.width / scale, resultBox_.height / scale), 10, closest);
for( int i = 0; i < (int)closest.size(); i++ ) for( int i = 0; i < (int)closest.size(); i++ )
{ {
...@@ -772,27 +798,27 @@ int TrackerTLDImpl::Pexpert::additionalExamples(std::vector<Mat_<uchar > >& exam ...@@ -772,27 +798,27 @@ int TrackerTLDImpl::Pexpert::additionalExamples(std::vector<Mat_<uchar > >& exam
{ {
Point2f center; Point2f center;
Size2f size; Size2f size;
Mat_<uchar> standardPatch(STANDARD_PATCH_SIZE,STANDARD_PATCH_SIZE),blurredPatch(initSize_); Mat_<uchar> standardPatch(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE), blurredPatch(initSize_);
center.x = (float)(closest[i].x + closest[i].width * (0.5 + rng.uniform(-0.01,0.01))); center.x = (float)(closest[i].x + closest[i].width * (0.5 + rng.uniform(-0.01, 0.01)));
center.y = (float)(closest[i].y + closest[i].height * (0.5 + rng.uniform(-0.01,0.01))); center.y = (float)(closest[i].y + closest[i].height * (0.5 + rng.uniform(-0.01, 0.01)));
size.width = (float)(closest[i].width * rng.uniform((double)0.99,(double)1.01)); size.width = (float)(closest[i].width * rng.uniform((double)0.99, (double)1.01));
size.height = (float)(closest[i].height * rng.uniform((double)0.99,(double)1.01)); size.height = (float)(closest[i].height * rng.uniform((double)0.99, (double)1.01));
float angle = (float)rng.uniform(-5.0,5.0); float angle = (float)rng.uniform(-5.0, 5.0);
for( int y = 0; y < standardPatch.rows; y++ ) for( int y = 0; y < standardPatch.rows; y++ )
{ {
for( int x = 0; x < standardPatch.cols; x++ ) for( int x = 0; x < standardPatch.cols; x++ )
{ {
standardPatch(x,y) += (uchar)rng.gaussian(5.0); standardPatch(x, y) += (uchar)rng.gaussian(5.0);
} }
} }
#ifdef BLUR_AS_VADIM #ifdef BLUR_AS_VADIM
GaussianBlur(standardPatch,blurredPatch,GaussBlurKernelSize,0.0); GaussianBlur(standardPatch, blurredPatch, GaussBlurKernelSize, 0.0);
resize(blurredPatch,blurredPatch,initSize_); resize(blurredPatch, blurredPatch, initSize_);
#else #else
resample(blurredImg,RotatedRect(center,size,angle),blurredPatch); resample(blurredImg, RotatedRect(center, size, angle), blurredPatch);
#endif #endif
resample(scaledImg,RotatedRect(center,size,angle),standardPatch); resample(scaledImg, RotatedRect(center, size, angle), standardPatch);
examplesForModel.push_back(standardPatch); examplesForModel.push_back(standardPatch);
examplesForEnsemble.push_back(blurredPatch); examplesForEnsemble.push_back(blurredPatch);
} }
...@@ -802,7 +828,7 @@ int TrackerTLDImpl::Pexpert::additionalExamples(std::vector<Mat_<uchar > >& exam ...@@ -802,7 +828,7 @@ int TrackerTLDImpl::Pexpert::additionalExamples(std::vector<Mat_<uchar > >& exam
bool TrackerTLDImpl::Nexpert::operator()(Rect2d box) bool TrackerTLDImpl::Nexpert::operator()(Rect2d box)
{ {
if( overlap(resultBox_,box) < NEXPERT_THRESHOLD ) if( overlap(resultBox_, box) < NEXPERT_THRESHOLD )
return false; return false;
else else
return true; return true;
...@@ -810,31 +836,31 @@ bool TrackerTLDImpl::Nexpert::operator()(Rect2d box) ...@@ -810,31 +836,31 @@ bool TrackerTLDImpl::Nexpert::operator()(Rect2d box)
Data::Data(Rect2d initBox) Data::Data(Rect2d initBox)
{ {
double minDim = std::min(initBox.width,initBox.height); double minDim = std::min(initBox.width, initBox.height);
scale = 20.0 / minDim; scale = 20.0 / minDim;
minSize.width = (int)(initBox.width * 20.0 / minDim); minSize.width = (int)(initBox.width * 20.0 / minDim);
minSize.height = (int)(initBox.height * 20.0 / minDim); minSize.height = (int)(initBox.height * 20.0 / minDim);
frameNum = 0; frameNum = 0;
dprintf(("minSize = %dx%d\n",minSize.width,minSize.height)); dprintf(("minSize = %dx%d\n", minSize.width, minSize.height));
} }
void Data::printme(FILE* port) void Data::printme(FILE* port)
{ {
dfprintf((port,"Data:\n")); dfprintf((port, "Data:\n"));
dfprintf((port,"\tframeNum = %d\n",frameNum)); dfprintf((port, "\tframeNum = %d\n", frameNum));
dfprintf((port,"\tconfident = %s\n",confident?"true":"false")); dfprintf((port, "\tconfident = %s\n", confident?"true":"false"));
dfprintf((port,"\tfailedLastTime = %s\n",failedLastTime?"true":"false")); dfprintf((port, "\tfailedLastTime = %s\n", failedLastTime?"true":"false"));
dfprintf((port,"\tminSize = %dx%d\n",minSize.width,minSize.height)); dfprintf((port, "\tminSize = %dx%d\n", minSize.width, minSize.height));
} }
void TrackerTLDModel::printme(FILE* port) void TrackerTLDModel::printme(FILE* port)
{ {
dfprintf((port,"TrackerTLDModel:\n")); dfprintf((port, "TrackerTLDModel:\n"));
dfprintf((port,"\tpositiveExamples.size() = %d\n",(int)positiveExamples.size())); dfprintf((port, "\tpositiveExamples.size() = %d\n", (int)positiveExamples.size()));
dfprintf((port,"\tnegativeExamples.size() = %d\n",(int)negativeExamples.size())); dfprintf((port, "\tnegativeExamples.size() = %d\n", (int)negativeExamples.size()));
} }
void MyMouseCallbackDEBUG::onMouse( int event, int x, int y) void MyMouseCallbackDEBUG::onMouse(int event, int x, int y)
{ {
if( event == EVENT_LBUTTONDOWN ) if( event == EVENT_LBUTTONDOWN )
{ {
...@@ -842,39 +868,39 @@ void MyMouseCallbackDEBUG::onMouse( int event, int x, int y) ...@@ -842,39 +868,39 @@ void MyMouseCallbackDEBUG::onMouse( int event, int x, int y)
img_.copyTo(imgCanvas); img_.copyTo(imgCanvas);
TrackerTLDModel* tldModel = ((TrackerTLDModel*)static_cast<TrackerModel*>(detector_->model)); TrackerTLDModel* tldModel = ((TrackerTLDModel*)static_cast<TrackerModel*>(detector_->model));
Size initSize = tldModel->getMinSize(); Size initSize = tldModel->getMinSize();
Mat_<uchar> standardPatch(STANDARD_PATCH_SIZE,STANDARD_PATCH_SIZE); Mat_<uchar> standardPatch(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE);
double originalVariance = tldModel->getOriginalVariance();; double originalVariance = tldModel->getOriginalVariance();
double tmp; double tmp;
Mat resized_img,blurred_img; Mat resized_img, blurred_img;
double scale = SCALE_STEP; double scale = SCALE_STEP;
//double scale = SCALE_STEP * SCALE_STEP * SCALE_STEP * SCALE_STEP; //double scale = SCALE_STEP * SCALE_STEP * SCALE_STEP * SCALE_STEP;
Size2d size(img_.cols / scale,img_.rows / scale); Size2d size(img_.cols / scale, img_.rows / scale);
resize(img_,resized_img,size); resize(img_, resized_img, size);
resize(imgBlurred_,blurred_img,size); resize(imgBlurred_, blurred_img, size);
Mat_<double> intImgP,intImgP2; Mat_<double> intImgP, intImgP2;
detector_->computeIntegralImages(resized_img,intImgP,intImgP2); detector_->computeIntegralImages(resized_img, intImgP, intImgP2);
int dx = initSize.width / 10, dy = initSize.height / 10, int dx = initSize.width / 10, dy = initSize.height / 10,
i = (int)(x / scale / dx), j = (int)(y / scale / dy); i = (int)(x / scale / dx), j = (int)(y / scale / dy);
dfprintf((stderr,"patchVariance = %s\n",(detector_->patchVariance(intImgP,intImgP2,originalVariance, dfprintf((stderr, "patchVariance = %s\n", (detector_->patchVariance(intImgP, intImgP2, originalVariance,
Point(dx * i,dy * j),initSize))?"true":"false")); Point(dx * i, dy * j), initSize))?"true":"false"));
tldModel->prepareClassifiers((int)blurred_img.step[0]); tldModel->prepareClassifiers((int)blurred_img.step[0]);
dfprintf((stderr,"p = %f\n",(tldModel->ensembleClassifierNum(&blurred_img.at<uchar>(dy * j,dx * i))))); dfprintf((stderr, "p = %f\n", (tldModel->ensembleClassifierNum(&blurred_img.at<uchar>(dy * j, dx * i)))));
fprintf(stderr,"ensembleClassifier = %s\n", fprintf(stderr, "ensembleClassifier = %s\n",
(!(tldModel->ensembleClassifierNum(&blurred_img.at<uchar>(dy * j,dx * i)) > ENSEMBLE_THRESHOLD))?"true":"false"); (!(tldModel->ensembleClassifierNum(&blurred_img.at<uchar>(dy * j, dx * i)) > ENSEMBLE_THRESHOLD))?"true":"false");
resample(resized_img,Rect2d(Point(dx * i,dy * j),initSize),standardPatch); resample(resized_img, Rect2d(Point(dx * i, dy * j), initSize), standardPatch);
tmp = tldModel->Sr(standardPatch); tmp = tldModel->Sr(standardPatch);
dfprintf((stderr,"Sr = %f\n",tmp)); dfprintf((stderr, "Sr = %f\n", tmp));
dfprintf((stderr,"isObject = %s\n",(tmp > THETA_NN)?"true":"false")); dfprintf((stderr, "isObject = %s\n", (tmp > THETA_NN)?"true":"false"));
dfprintf((stderr,"shouldBeIntegrated = %s\n",(abs(tmp - THETA_NN) < 0.1)?"true":"false")); dfprintf((stderr, "shouldBeIntegrated = %s\n", (abs(tmp - THETA_NN) < 0.1)?"true":"false"));
dfprintf((stderr,"Sc = %f\n",tldModel->Sc(standardPatch))); dfprintf((stderr, "Sc = %f\n", tldModel->Sc(standardPatch)));
rectangle(imgCanvas,Rect2d(Point2d(scale * dx * i,scale * dy * j),Size2d(initSize.width * scale,initSize.height * scale)), 0, 2, 1 ); rectangle(imgCanvas, Rect2d(Point2d(scale * dx * i, scale * dy * j), Size2d(initSize.width * scale, initSize.height * scale)), 0, 2, 1 );
imshow("picker",imgCanvas); imshow("picker", imgCanvas);
waitKey(); waitKey();
} }
} }
...@@ -903,7 +929,7 @@ void TrackerTLDModel::pushIntoModel(const Mat_<uchar>& example, bool positive) ...@@ -903,7 +929,7 @@ void TrackerTLDModel::pushIntoModel(const Mat_<uchar>& example, bool positive)
} }
else else
{ {
int index = rng.uniform((int)0,(int)proxyV->size()); int index = rng.uniform((int)0, (int)proxyV->size());
(*proxyV)[index] = example; (*proxyV)[index] = example;
(*proxyT)[index] = (*proxyN); (*proxyT)[index] = (*proxyN);
} }
......
...@@ -57,60 +57,67 @@ namespace cv {namespace tld ...@@ -57,60 +57,67 @@ namespace cv {namespace tld
#define dfprintf(x) #define dfprintf(x)
#define dprintf(x) #define dprintf(x)
#endif #endif
#define MEASURE_TIME(a) {\ #define MEASURE_TIME(a)\
clock_t start;float milisec = 0.0;\ {\
start = clock();{a} milisec = 1000.0 * (clock() - start) / CLOCKS_PER_SEC;\ clock_t start; float milisec = 0.0; \
dprintf(("%-90s took %f milis\n",#a,milisec)); } start = clock(); {a} milisec = 1000.0 * (clock() - start) / CLOCKS_PER_SEC; \
#define HERE dprintf(("line %d\n",__LINE__));fflush(stderr); dprintf(("%-90s took %f milis\n", #a, milisec));\
#define START_TICK(name) { clock_t start;double milisec = 0.0; start = clock(); }
#define END_TICK(name) milisec = 1000.0 * (clock() - start) / CLOCKS_PER_SEC;\ #define HERE dprintf(("line %d\n", __LINE__)); fflush(stderr);
dprintf(("%s took %f milis\n",name,milisec)); } #define START_TICK(name)\
{ \
clock_t start; double milisec = 0.0; start = clock();
#define END_TICK(name) milisec = 1000.0 * (clock() - start) / CLOCKS_PER_SEC; \
dprintf(("%s took %f milis\n", name, milisec)); \
}
extern Rect2d etalon; extern Rect2d etalon;
void myassert(const Mat& img); void myassert(const Mat& img);
void printPatch(const Mat_<uchar>& standardPatch); void printPatch(const Mat_<uchar>& standardPatch);
std::string type2str(const Mat& mat); 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, Rect2d whiteOne = Rect2d(-1.0, -1.0, -1.0, -1.0));
void drawWithRects(const Mat& img,std::vector<Rect2d>& blackOnes,std::vector<Rect2d>& whiteOnes,String fileName = ""); void drawWithRects(const Mat& img, std::vector<Rect2d>& blackOnes, std::vector<Rect2d>& whiteOnes, String fileName = "");
//aux functions and variables //aux functions and variables
template<typename T> inline T CLIP(T x,T a,T b){return std::min(std::max(x,a),b);} template<typename T> inline T CLIP(T x, T a, T b){ return std::min(std::max(x, a), b); }
/** Computes overlap between the two given rectangles. Overlap is computed as ratio of rectangles' intersection to that /** Computes overlap between the two given rectangles. Overlap is computed as ratio of rectangles' intersection to that
* of their union.*/ * of their union.*/
double overlap(const Rect2d& r1,const Rect2d& r2); double overlap(const Rect2d& r1, const Rect2d& r2);
/** Resamples the area surrounded by r2 in img so it matches the size of samples, where it is written.*/ /** Resamples the area surrounded by r2 in img so it matches the size of samples, where it is written.*/
void resample(const Mat& img,const RotatedRect& r2,Mat_<uchar>& samples); void resample(const Mat& img, const RotatedRect& r2, Mat_<uchar>& samples);
/** Specialization of resample() for rectangles without retation for better performance and simplicity.*/ /** Specialization of resample() for rectangles without retation for better performance and simplicity.*/
void resample(const Mat& img,const Rect2d& r2,Mat_<uchar>& samples); void resample(const Mat& img, const Rect2d& r2, Mat_<uchar>& samples);
/** Computes the variance of single given image.*/ /** Computes the variance of single given image.*/
double variance(const Mat& img); double variance(const Mat& img);
/** Computes normalized corellation coefficient between the two patches (they should be /** Computes normalized corellation coefficient between the two patches (they should be
* of the same size).*/ * of the same size).*/
double NCC(const Mat_<uchar>& patch1,const Mat_<uchar>& patch2); double NCC(const Mat_<uchar>& patch1, const Mat_<uchar>& patch2);
void getClosestN(std::vector<Rect2d>& scanGrid,Rect2d bBox,int n,std::vector<Rect2d>& res); 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, double scaleStep); double scaleAndBlur(const Mat& originalImg, int scale, Mat& scaledImg, Mat& blurredImg, Size GaussBlurKernelSize, double scaleStep);
int getMedian(const std::vector<int>& values, int size = -1); int getMedian(const std::vector<int>& values, int size = -1);
class TLDEnsembleClassifier{ class TLDEnsembleClassifier
{
public: public:
static int makeClassifiers(Size size,int measurePerClassifier,int gridSize,std::vector<TLDEnsembleClassifier>& classifiers); static int makeClassifiers(Size size, int measurePerClassifier, int gridSize, std::vector<TLDEnsembleClassifier>& classifiers);
void integrate(const Mat_<uchar>& patch,bool isPositive); void integrate(const Mat_<uchar>& patch, bool isPositive);
double posteriorProbability(const uchar* data,int rowstep)const; double posteriorProbability(const uchar* data, int rowstep) const;
double posteriorProbabilityFast(const uchar* data)const; double posteriorProbabilityFast(const uchar* data) const;
void prepareClassifier(int rowstep); void prepareClassifier(int rowstep);
private: private:
TLDEnsembleClassifier(const std::vector<Vec4b>& meas,int beg,int end); TLDEnsembleClassifier(const std::vector<Vec4b>& meas, int beg, int end);
static void stepPrefSuff(std::vector<Vec4b> & arr,int pos,int len,int gridSize); static void stepPrefSuff(std::vector<Vec4b> & arr, int pos, int len, int gridSize);
int code(const uchar* data,int rowstep)const; int code(const uchar* data, int rowstep) const;
int codeFast(const uchar* data)const; int codeFast(const uchar* data) const;
std::vector<Point2i> posAndNeg; std::vector<Point2i> posAndNeg;
std::vector<Vec4b> measurements; std::vector<Vec4b> measurements;
std::vector<Point2i> offset; std::vector<Point2i> offset;
int lastStep_; int lastStep_;
}; };
class TrackerProxy{ class TrackerProxy
{
public: public:
virtual bool init( const Mat& image, const Rect2d& boundingBox) = 0; virtual bool init(const Mat& image, const Rect2d& boundingBox) = 0;
virtual bool update(const Mat& image, Rect2d& boundingBox) = 0; virtual bool update(const Mat& image, Rect2d& boundingBox) = 0;
virtual ~TrackerProxy(){} virtual ~TrackerProxy(){}
}; };
......
...@@ -53,58 +53,61 @@ namespace cv {namespace tld ...@@ -53,58 +53,61 @@ namespace cv {namespace tld
{ {
//debug functions and variables //debug functions and variables
Rect2d etalon(14.0,110.0,20.0,20.0); Rect2d etalon(14.0, 110.0, 20.0, 20.0);
void drawWithRects(const Mat& img,std::vector<Rect2d>& blackOnes,Rect2d whiteOne){ void drawWithRects(const Mat& img, std::vector<Rect2d>& blackOnes, Rect2d whiteOne)
{
Mat image; Mat image;
img.copyTo(image); img.copyTo(image);
if(whiteOne.width >= 0){ if( whiteOne.width >= 0 )
rectangle( image,whiteOne, 255, 1, 1 ); rectangle( image, whiteOne, 255, 1, 1 );
} for( int i = 0; i < (int)blackOnes.size(); i++ )
for(int i = 0;i < (int)blackOnes.size();i++){ rectangle( image, blackOnes[i], 0, 1, 1 );
rectangle( image,blackOnes[i], 0, 1, 1 ); imshow("img", image);
}
imshow("img",image);
} }
void drawWithRects(const Mat& img,std::vector<Rect2d>& blackOnes,std::vector<Rect2d>& whiteOnes,String filename){ void drawWithRects(const Mat& img, std::vector<Rect2d>& blackOnes, std::vector<Rect2d>& whiteOnes, String filename)
{
Mat image; Mat image;
static int frameCounter = 1; static int frameCounter = 1;
img.copyTo(image); img.copyTo(image);
for(int i = 0;i < (int)whiteOnes.size();i++){ for( int i = 0; i < (int)whiteOnes.size(); i++ )
rectangle( image,whiteOnes[i], 255, 1, 1 ); rectangle( image, whiteOnes[i], 255, 1, 1 );
} for( int i = 0; i < (int)blackOnes.size(); i++ )
for(int i = 0;i < (int)blackOnes.size();i++){ rectangle( image, blackOnes[i], 0, 1, 1 );
rectangle( image,blackOnes[i], 0, 1, 1 ); imshow("img", image);
} if( filename.length() > 0 )
imshow("img",image); {
if(filename.length() > 0){
char inbuf[100]; char inbuf[100];
sprintf(inbuf,"%s%d.jpg",filename.c_str(),frameCounter); sprintf(inbuf, "%s%d.jpg", filename.c_str(), frameCounter);
imwrite(inbuf,image); imwrite(inbuf, image);
frameCounter++; frameCounter++;
} }
} }
void myassert(const Mat& img){ void myassert(const Mat& img)
{
int count = 0; int count = 0;
for(int i = 0;i < img.rows;i++){ for( int i = 0; i < img.rows; i++ )
for(int j = 0;j < img.cols;j++){ {
if(img.at<uchar>(i,j) == 0){ for( int j = 0; j < img.cols; j++ )
{
if( img.at<uchar>(i, j) == 0 )
count++; count++;
}
} }
} }
dprintf(("black: %d out of %d (%f)\n",count,img.rows * img.cols,1.0 * count / img.rows / img.cols)); dprintf(("black: %d out of %d (%f)\n", count, img.rows * img.cols, 1.0 * count / img.rows / img.cols));
} }
void printPatch(const Mat_<uchar>& standardPatch){ void printPatch(const Mat_<uchar>& standardPatch)
for(int i = 0;i < standardPatch.rows;i++){ {
for(int j = 0;j < standardPatch.cols;j++){ for( int i = 0; i < standardPatch.rows; i++ )
dprintf(("%5.2f, ",(double)standardPatch(i,j))); {
} for( int j = 0; j < standardPatch.cols; j++ )
dprintf(("%5.2f, ", (double)standardPatch(i, j)));
dprintf(("\n")); dprintf(("\n"));
} }
} }
std::string type2str(const Mat& mat){ std::string type2str(const Mat& mat)
{
int type = mat.type(); int type = mat.type();
std::string r; std::string r;
...@@ -129,59 +132,63 @@ std::string type2str(const Mat& mat){ ...@@ -129,59 +132,63 @@ std::string type2str(const Mat& mat){
} }
//generic functions //generic functions
double scaleAndBlur(const Mat& originalImg,int scale,Mat& scaledImg,Mat& blurredImg,Size GaussBlurKernelSize, double scaleStep){ double scaleAndBlur(const Mat& originalImg, int scale, Mat& scaledImg, Mat& blurredImg, Size GaussBlurKernelSize, double scaleStep)
{
double dScale = 1.0; double dScale = 1.0;
for(int i = 0; i < scale; i++, dScale *= scaleStep); for( int i = 0; i < scale; i++, dScale *= scaleStep );
Size2d size = originalImg.size(); Size2d size = originalImg.size();
size.height /= dScale; size.width /= dScale; size.height /= dScale; size.width /= dScale;
resize(originalImg,scaledImg,size); resize(originalImg, scaledImg, size);
GaussianBlur(scaledImg,blurredImg,GaussBlurKernelSize,0.0); GaussianBlur(scaledImg, blurredImg, GaussBlurKernelSize, 0.0);
return dScale; return dScale;
} }
void getClosestN(std::vector<Rect2d>& scanGrid,Rect2d bBox,int n,std::vector<Rect2d>& res){ void getClosestN(std::vector<Rect2d>& scanGrid, Rect2d bBox, int n, std::vector<Rect2d>& res)
if(n >= (int)scanGrid.size()){ {
res.assign(scanGrid.begin(),scanGrid.end()); if( n >= (int)scanGrid.size() )
{
res.assign(scanGrid.begin(), scanGrid.end());
return; return;
} }
std::vector<double> overlaps; std::vector<double> overlaps;
overlaps.assign(n,0.0); overlaps.assign(n, 0.0);
res.assign(scanGrid.begin(),scanGrid.begin() + n); res.assign(scanGrid.begin(), scanGrid.begin() + n);
for(int i = 0;i < n;i++){ for( int i = 0; i < n; i++ )
overlaps[i] = overlap(res[i],bBox); overlaps[i] = overlap(res[i], bBox);
}
double otmp; double otmp;
Rect2d rtmp; Rect2d rtmp;
for (int i = 1; i < n; i++){ for (int i = 1; i < n; i++)
{
int j = i; int j = i;
while (j > 0 && overlaps[j - 1] > overlaps[j]) { while (j > 0 && overlaps[j - 1] > overlaps[j]) {
otmp = overlaps[j];overlaps[j] = overlaps[j - 1];overlaps[j - 1] = otmp; otmp = overlaps[j]; overlaps[j] = overlaps[j - 1]; overlaps[j - 1] = otmp;
rtmp = res[j];res[j] = res[j - 1];res[j - 1] = rtmp; rtmp = res[j]; res[j] = res[j - 1]; res[j - 1] = rtmp;
j--; j--;
} }
} }
for(int i = n;i < (int)scanGrid.size();i++){ for( int i = n; i < (int)scanGrid.size(); i++ )
{
double o = 0.0; double o = 0.0;
if((o = overlap(scanGrid[i],bBox)) <= overlaps[0]){ if( (o = overlap(scanGrid[i], bBox)) <= overlaps[0] )
continue; continue;
}
int j = 0; int j = 0;
while( j < n && overlaps[j] < o ) while( j < n && overlaps[j] < o )
{
j++; j++;
}
j--; j--;
for(int k = 0;k < j;overlaps[k] = overlaps[k + 1],res[k] = res[k + 1],k++); for( int k = 0; k < j; overlaps[k] = overlaps[k + 1], res[k] = res[k + 1], k++ );
overlaps[j] = o;res[j] = scanGrid[i]; overlaps[j] = o; res[j] = scanGrid[i];
} }
} }
double variance(const Mat& img){ double variance(const Mat& img)
double p = 0,p2 = 0; {
for(int i = 0;i < img.rows;i++){ double p = 0, p2 = 0;
for(int j = 0;j < img.cols;j++){ for( int i = 0; i < img.rows; i++ )
p += img.at<uchar>(i,j); {
p2 += img.at<uchar>(i,j) * img.at<uchar>(i,j); for( int j = 0; j < img.cols; j++ )
{
p += img.at<uchar>(i, j);
p2 += img.at<uchar>(i, j) * img.at<uchar>(i, j);
} }
} }
p /= (img.cols * img.rows); p /= (img.cols * img.rows);
...@@ -189,87 +196,96 @@ double variance(const Mat& img){ ...@@ -189,87 +196,96 @@ double variance(const Mat& img){
return p2 - p * p; return p2 - p * p;
} }
double NCC(const Mat_<uchar>& patch1,const Mat_<uchar>& patch2){ double NCC(const Mat_<uchar>& patch1, const Mat_<uchar>& patch2)
CV_Assert(patch1.rows == patch2.rows); {
CV_Assert(patch1.cols == patch2.cols); CV_Assert( patch1.rows == patch2.rows );
CV_Assert( patch1.cols == patch2.cols );
int N = patch1.rows * patch1.cols; int N = patch1.rows * patch1.cols;
int s1 = 0,s2 = 0,n1 = 0,n2 = 0,prod = 0; int s1 = 0, s2 = 0, n1 = 0, n2 = 0, prod = 0;
for(int i = 0;i < patch1.rows;i++){ for( int i = 0; i < patch1.rows; i++ )
for(int j = 0;j < patch1.cols;j++){ {
int p1 = patch1(i,j), p2 = patch2(i,j); for( int j = 0; j < patch1.cols; j++ )
{
int p1 = patch1(i, j), p2 = patch2(i, j);
s1 += p1; s2 += p2; s1 += p1; s2 += p2;
n1 += (p1 * p1); n2 += (p2 * p2); n1 += (p1 * p1); n2 += (p2 * p2);
prod += (p1 * p2); prod += (p1 * p2);
} }
} }
double sq1 = sqrt(std::max(0.0,n1 - 1.0 * s1 * s1 / N)),sq2 = sqrt(std::max(0.0,n2 - 1.0 * s2 * s2 / N)); double sq1 = sqrt(std::max(0.0, n1 - 1.0 * s1 * s1 / N)), sq2 = sqrt(std::max(0.0, n2 - 1.0 * s2 * s2 / N));
double ares = (sq2 == 0) ? sq1 / abs(sq1) : (prod - s1 * s2 / N) / sq1 / sq2; double ares = (sq2 == 0) ? sq1 / abs(sq1) : (prod - s1 * s2 / N) / sq1 / sq2;
return ares; return ares;
} }
int getMedian(const std::vector<int>& values, int size){ int getMedian(const std::vector<int>& values, int size)
if(size == -1){ {
if( size == -1 )
size = (int)values.size(); size = (int)values.size();
} std::vector<int> copy(values.begin(), values.begin() + size);
std::vector<int> copy(values.begin(),values.begin() + size); std::sort(copy.begin(), copy.end());
std::sort(copy.begin(),copy.end()); if( size % 2 == 0 )
if(size % 2 == 0){
return (copy[size / 2 - 1] + copy[size / 2]) / 2; return (copy[size / 2 - 1] + copy[size / 2]) / 2;
}else{ else
return copy[(size - 1) / 2]; return copy[(size - 1) / 2];
}
} }
double overlap(const Rect2d& r1,const Rect2d& r2){ double overlap(const Rect2d& r1, const Rect2d& r2)
{
double a1 = r1.area(), a2 = r2.area(), a0 = (r1&r2).area(); double a1 = r1.area(), a2 = r2.area(), a0 = (r1&r2).area();
return a0 / (a1 + a2 - a0); return a0 / (a1 + a2 - a0);
} }
void resample(const Mat& img,const RotatedRect& r2,Mat_<uchar>& samples){ void resample(const Mat& img, const RotatedRect& r2, Mat_<uchar>& samples)
Mat_<float> M(2,3),R(2,2),Si(2,2),s(2,1),o(2,1); {
R(0,0) = (float)cos(r2.angle * CV_PI / 180);R(0,1) = (float)(-sin(r2.angle * CV_PI / 180)); Mat_<float> M(2, 3), R(2, 2), Si(2, 2), s(2, 1), o(2, 1);
R(1,0) = (float)sin(r2.angle * CV_PI / 180);R(1,1) = (float)cos(r2.angle * CV_PI / 180); R(0, 0) = (float)cos(r2.angle * CV_PI / 180); R(0, 1) = (float)(-sin(r2.angle * CV_PI / 180));
Si(0,0) = (float)(samples.cols / r2.size.width); Si(0,1) = 0.0f; R(1, 0) = (float)sin(r2.angle * CV_PI / 180); R(1, 1) = (float)cos(r2.angle * CV_PI / 180);
Si(1,0) = 0.0f; Si(1,1) = (float)(samples.rows / r2.size.height); Si(0, 0) = (float)(samples.cols / r2.size.width); Si(0, 1) = 0.0f;
s(0,0) = (float)samples.cols; s(1,0) = (float)samples.rows; Si(1, 0) = 0.0f; Si(1, 1) = (float)(samples.rows / r2.size.height);
o(0,0) = r2.center.x;o(1,0) = r2.center.y; s(0, 0) = (float)samples.cols; s(1, 0) = (float)samples.rows;
Mat_<float> A(2,2),b(2,1); o(0, 0) = r2.center.x; o(1, 0) = r2.center.y;
Mat_<float> A(2, 2), b(2, 1);
A = Si * R; A = Si * R;
b = s / 2.0 - Si * R * o; b = s / 2.0 - Si * R * o;
A.copyTo(M.colRange(Range(0,2))); A.copyTo(M.colRange(Range(0, 2)));
b.copyTo(M.colRange(Range(2,3))); b.copyTo(M.colRange(Range(2, 3)));
warpAffine(img,samples,M,samples.size()); warpAffine(img, samples, M, samples.size());
} }
void resample(const Mat& img,const Rect2d& r2,Mat_<uchar>& samples){ void resample(const Mat& img, const Rect2d& r2, Mat_<uchar>& samples)
Mat_<float> M(2,3); {
M(0,0) = (float)(samples.cols / r2.width); M(0,1) = 0.0f; M(0,2) = (float)(-r2.x * samples.cols / r2.width); Mat_<float> M(2, 3);
M(1,0) = 0.0f; M(1,1) = (float)(samples.rows / r2.height); M(1,2) = (float)(-r2.y * samples.rows / r2.height); M(0, 0) = (float)(samples.cols / r2.width); M(0, 1) = 0.0f; M(0, 2) = (float)(-r2.x * samples.cols / r2.width);
warpAffine(img,samples,M,samples.size()); M(1, 0) = 0.0f; M(1, 1) = (float)(samples.rows / r2.height); M(1, 2) = (float)(-r2.y * samples.rows / r2.height);
warpAffine(img, samples, M, samples.size());
} }
//other stuff //other stuff
void TLDEnsembleClassifier::stepPrefSuff(std::vector<Vec4b>& arr,int pos,int len,int gridSize){ void TLDEnsembleClassifier::stepPrefSuff(std::vector<Vec4b>& arr, int pos, int len, int gridSize)
{
#if 0 #if 0
int step = len / (gridSize - 1), pref = (len - step * (gridSize - 1)) / 2; int step = len / (gridSize - 1), pref = (len - step * (gridSize - 1)) / 2;
for(int i = 0;i < (int)(sizeof(x1) / sizeof(x1[0]));i++){ for( int i = 0; i < (int)(sizeof(x1) / sizeof(x1[0])); i++ )
arr[i] = pref + arr[i] * step; arr[i] = pref + arr[i] * step;
}
#else #else
int total = len - gridSize; int total = len - gridSize;
int quo = total / (gridSize - 1),rem = total % (gridSize - 1); int quo = total / (gridSize - 1), rem = total % (gridSize - 1);
int smallStep = quo,bigStep = quo + 1; int smallStep = quo, bigStep = quo + 1;
int bigOnes = rem,smallOnes = gridSize - bigOnes - 1; int bigOnes = rem, smallOnes = gridSize - bigOnes - 1;
int bigOnes_front = bigOnes / 2, bigOnes_back = bigOnes - bigOnes_front; int bigOnes_front = bigOnes / 2, bigOnes_back = bigOnes - bigOnes_front;
for(int i = 0;i < (int)arr.size();i++){ for( int i = 0; i < (int)arr.size(); i++ )
if(arr[i].val[pos] < bigOnes_back){ {
if( arr[i].val[pos] < bigOnes_back )
{
arr[i].val[pos] = (uchar)(arr[i].val[pos] * bigStep + arr[i].val[pos]); arr[i].val[pos] = (uchar)(arr[i].val[pos] * bigStep + arr[i].val[pos]);
continue; continue;
} }
if(arr[i].val[pos] < (bigOnes_front + smallOnes)){ if( arr[i].val[pos] < (bigOnes_front + smallOnes) )
{
arr[i].val[pos] = (uchar)(bigOnes_front * bigStep + (arr[i].val[pos] - bigOnes_front) * smallStep + arr[i].val[pos]); arr[i].val[pos] = (uchar)(bigOnes_front * bigStep + (arr[i].val[pos] - bigOnes_front) * smallStep + arr[i].val[pos]);
continue; continue;
} }
if(arr[i].val[pos] < (bigOnes_front + smallOnes + bigOnes_back)){ if( arr[i].val[pos] < (bigOnes_front + smallOnes + bigOnes_back) )
{
arr[i].val[pos] = arr[i].val[pos] =
(uchar)(bigOnes_front * bigStep + smallOnes * smallStep + (uchar)(bigOnes_front * bigStep + smallOnes * smallStep +
(arr[i].val[pos] - (bigOnes_front + smallOnes)) * bigStep + arr[i].val[pos]); (arr[i].val[pos] - (bigOnes_front + smallOnes)) * bigStep + arr[i].val[pos]);
...@@ -279,62 +295,69 @@ void TLDEnsembleClassifier::stepPrefSuff(std::vector<Vec4b>& arr,int pos,int len ...@@ -279,62 +295,69 @@ void TLDEnsembleClassifier::stepPrefSuff(std::vector<Vec4b>& arr,int pos,int len
} }
#endif #endif
} }
void TLDEnsembleClassifier::prepareClassifier(int rowstep){ void TLDEnsembleClassifier::prepareClassifier(int rowstep)
if(lastStep_ != rowstep){ {
if( lastStep_ != rowstep )
{
lastStep_ = rowstep; lastStep_ = rowstep;
for(int i = 0;i < (int)offset.size();i++){ for( int i = 0; i < (int)offset.size(); i++ )
{
offset[i].x = rowstep * measurements[i].val[0] + measurements[i].val[1]; offset[i].x = rowstep * measurements[i].val[0] + measurements[i].val[1];
offset[i].y = rowstep * measurements[i].val[2] + measurements[i].val[3]; offset[i].y = rowstep * measurements[i].val[2] + measurements[i].val[3];
} }
} }
} }
TLDEnsembleClassifier::TLDEnsembleClassifier(const std::vector<Vec4b>& meas,int beg,int end):lastStep_(-1){ TLDEnsembleClassifier::TLDEnsembleClassifier(const std::vector<Vec4b>& meas, int beg, int end):lastStep_(-1)
{
int posSize = 1, mpc = end - beg; int posSize = 1, mpc = end - beg;
for( int i = 0; i < mpc; i++ ) for( int i = 0; i < mpc; i++ )
posSize *= 2; posSize *= 2;
posAndNeg.assign(posSize,Point2i(0,0)); posAndNeg.assign(posSize, Point2i(0, 0));
measurements.assign(meas.begin() + beg,meas.begin() + end); measurements.assign(meas.begin() + beg, meas.begin() + end);
offset.assign(mpc,Point2i(0,0)); offset.assign(mpc, Point2i(0, 0));
} }
void TLDEnsembleClassifier::integrate(const Mat_<uchar>& patch,bool isPositive){ void TLDEnsembleClassifier::integrate(const Mat_<uchar>& patch, bool isPositive)
int position = code(patch.data,(int)patch.step[0]); {
if(isPositive){ int position = code(patch.data, (int)patch.step[0]);
if( isPositive )
posAndNeg[position].x++; posAndNeg[position].x++;
}else{ else
posAndNeg[position].y++; posAndNeg[position].y++;
}
} }
double TLDEnsembleClassifier::posteriorProbability(const uchar* data,int rowstep)const{ double TLDEnsembleClassifier::posteriorProbability(const uchar* data, int rowstep) const
int position = code(data,rowstep); {
int position = code(data, rowstep);
double posNum = (double)posAndNeg[position].x, negNum = (double)posAndNeg[position].y; double posNum = (double)posAndNeg[position].x, negNum = (double)posAndNeg[position].y;
if(posNum == 0.0 && negNum == 0.0){ if( posNum == 0.0 && negNum == 0.0 )
return 0.0; return 0.0;
}else{ else
return posNum / (posNum + negNum); return posNum / (posNum + negNum);
}
} }
double TLDEnsembleClassifier::posteriorProbabilityFast(const uchar* data)const{ double TLDEnsembleClassifier::posteriorProbabilityFast(const uchar* data) const
{
int position = codeFast(data); int position = codeFast(data);
double posNum = (double)posAndNeg[position].x, negNum = (double)posAndNeg[position].y; double posNum = (double)posAndNeg[position].x, negNum = (double)posAndNeg[position].y;
if(posNum == 0.0 && negNum == 0.0){ if( posNum == 0.0 && negNum == 0.0 )
return 0.0; return 0.0;
}else{ else
return posNum / (posNum + negNum); return posNum / (posNum + negNum);
}
} }
int TLDEnsembleClassifier::codeFast(const uchar* data)const{ int TLDEnsembleClassifier::codeFast(const uchar* data) const
{
int position = 0; int position = 0;
for(int i = 0;i < (int)measurements.size();i++){ for( int i = 0; i < (int)measurements.size(); i++ )
{
position = position << 1; position = position << 1;
if(data[offset[i].x] < data[offset[i].y]){ if( data[offset[i].x] < data[offset[i].y] )
position++; position++;
}
} }
return position; return position;
} }
int TLDEnsembleClassifier::code(const uchar* data,int rowstep)const{ int TLDEnsembleClassifier::code(const uchar* data, int rowstep) const
{
int position = 0; int position = 0;
for(int i = 0;i < (int)measurements.size();i++){ for( int i = 0; i < (int)measurements.size(); i++ )
{
position = position << 1; position = position << 1;
if( *(data + rowstep * measurements[i].val[0] + measurements[i].val[1]) < if( *(data + rowstep * measurements[i].val[0] + measurements[i].val[1]) <
*(data + rowstep * measurements[i].val[2] + measurements[i].val[3]) ) *(data + rowstep * measurements[i].val[2] + measurements[i].val[3]) )
...@@ -344,34 +367,37 @@ int TLDEnsembleClassifier::code(const uchar* data,int rowstep)const{ ...@@ -344,34 +367,37 @@ int TLDEnsembleClassifier::code(const uchar* data,int rowstep)const{
} }
return position; return position;
} }
int TLDEnsembleClassifier::makeClassifiers(Size size,int measurePerClassifier,int gridSize, int TLDEnsembleClassifier::makeClassifiers(Size size, int measurePerClassifier, int gridSize,
std::vector<TLDEnsembleClassifier>& classifiers){ std::vector<TLDEnsembleClassifier>& classifiers)
{
std::vector<Vec4b> measurements; std::vector<Vec4b> measurements;
for(int i = 0;i < gridSize;i++){ for( int i = 0; i < gridSize; i++ )
for(int j = 0;j < gridSize;j++){ {
for(int k = 0;k < j;k++){ for( int j = 0; j < gridSize; j++ )
{
for( int k = 0; k < j; k++ )
{
Vec4b m; Vec4b m;
m.val[0] = m.val[2] = i; m.val[0] = m.val[2] = i;
m.val[1] = j;m.val[3] = k; m.val[1] = j; m.val[3] = k;
measurements.push_back(m); measurements.push_back(m);
m.val[1] = m.val[3] = i; m.val[1] = m.val[3] = i;
m.val[0] = j;m.val[2] = k; m.val[0] = j; m.val[2] = k;
measurements.push_back(m); measurements.push_back(m);
} }
} }
} }
random_shuffle(measurements.begin(),measurements.end()); random_shuffle(measurements.begin(), measurements.end());
stepPrefSuff(measurements,0,size.width,gridSize); stepPrefSuff(measurements, 0, size.width, gridSize);
stepPrefSuff(measurements,1,size.width,gridSize); stepPrefSuff(measurements, 1, size.width, gridSize);
stepPrefSuff(measurements,2,size.height,gridSize); stepPrefSuff(measurements, 2, size.height, gridSize);
stepPrefSuff(measurements,3,size.height,gridSize); stepPrefSuff(measurements, 3, size.height, gridSize);
for(int i = 0,howMany = measurements.size() / measurePerClassifier;i < howMany;i++){ for( int i = 0, howMany = measurements.size() / measurePerClassifier; i < howMany; i++ )
classifiers.push_back(TLDEnsembleClassifier(measurements,i * measurePerClassifier, (i + 1) * measurePerClassifier)); classifiers.push_back(TLDEnsembleClassifier(measurements, i * measurePerClassifier, (i + 1) * measurePerClassifier));
}
return (int)classifiers.size(); return (int)classifiers.size();
} }
......
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