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

coding style

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