注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

BeyondEgo

Welcome to Winsolider's yard! 超越自我,谁与争锋?

 
 
 

日志

 
 
关于我

本博为记事、畅聊、交友博客,邀你共同探讨人生、探讨成长,广交天下有志之士!愿与有相同兴趣爱好的你,共同学习、一起成长、收获喜悦!

网易考拉推荐

TLD源码理解之TLD.cpp(一)  

2013-05-20 15:46:56|  分类: TLD算法 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

TLD.cpp

  1. /* 
  2.  * TLD.cpp 
  3.  * 
  4.  *  Created on: Jun 9, 2011 
  5.  *      Author: alantrrs 
  6.  */  
  7.   
  8. #include <TLD.h>   
  9. #include <stdio.h>   
  10. using namespace cv;  
  11. using namespace std;  
  12.   
  13.   
  14. TLD::TLD()  
  15. {  
  16. }  
  17. TLD::TLD(const FileNode& file){  
  18.   read(file);  
  19. }  
  20.   
  21. void TLD::read(const FileNode& file){  
  22.   ///Bounding Box Parameters   
  23.   min_win = (int)file["min_win"];  
  24.   ///Genarator Parameters   
  25.   //initial parameters for positive examples  
  26.   patch_size = (int)file["patch_size"];  
  27.   num_closest_init = (int)file["num_closest_init"];  
  28.   num_warps_init = (int)file["num_warps_init"];  
  29.   noise_init = (int)file["noise_init"];  
  30.   angle_init = (float)file["angle_init"];  
  31.   shift_init = (float)file["shift_init"];  
  32.   scale_init = (float)file["scale_init"];  
  33.   //update parameters for positive examples  
  34.   num_closest_update = (int)file["num_closest_update"];  
  35.   num_warps_update = (int)file["num_warps_update"];  
  36.   noise_update = (int)file["noise_update"];  
  37.   angle_update = (float)file["angle_update"];  
  38.   shift_update = (float)file["shift_update"];  
  39.   scale_update = (float)file["scale_update"];  
  40.   //parameters for negative examples   
  41.   bad_overlap = (float)file["overlap"];  
  42.   bad_patches = (int)file["num_patches"];  
  43.   classifier.read(file);  
  44. }  
  45.   
  46. //此函数完成准备工作   
  47. void TLD::init(const Mat& frame1, const Rect& box, FILE* bb_file){  
  48.   //bb_file = fopen("bounding_boxes.txt","w");  
  49.   //Get Bounding Boxes   
  50.   //此函数根据传入的box(目标边界框)在传入的图像frame1中构建全部的扫描窗口,并计算重叠度  
  51.     buildGrid(frame1, box);  
  52.     printf("Created %d bounding boxes\n",(int)grid.size());  //vector的成员size()用于获取向量元素的个数  
  53.       
  54.   ///Preparation   
  55.   //allocation   
  56.   //积分图像,用以计算2bitBP特征(类似于haar特征的计算)   
  57.   //Mat的创建,方式有两种:1.调用create(行,列,类型)2.Mat(行,列,类型(值))。  
  58.   iisum.create(frame1.rows+1, frame1.cols+1, CV_32F);  
  59.   iisqsum.create(frame1.rows+1, frame1.cols+1, CV_64F);  
  60.     
  61.   //Detector data中定义:std::vector<float> dconf;  检测确信度??  
  62.   //vector 的reserve增加了vector的capacity,但是它的size没有改变!而resize改变了vector  
  63.   //的capacity同时也增加了它的size!reserve是容器预留空间,但在空间内不真正创建元素对象,  
  64.   //所以在没有添加新的对象之前,不能引用容器内的元素。   
  65.   //不管是调用resize还是reserve,二者对容器原有的元素都没有影响。  
  66.   //myVec.reserve( 100 );     // 新元素还没有构造, 此时不能用[]访问元素  
  67.   //myVec.resize( 100 );      // 用元素的默认构造函数构造了100个新的元素,可以直接操作新元素  
  68.   dconf.reserve(100);  
  69.   dbb.reserve(100);  
  70.   bbox_step =7;  
  71.     
  72.   //以下在Detector data中定义的容器都给其分配grid.size()大小(这个是一幅图像中全部的扫描窗口个数)的容量  
  73.   //Detector data中定义TempStruct tmp;    
  74.   //tmp.conf.reserve(grid.size());   
  75.   tmp.conf = vector<float>(grid.size());  
  76.   tmp.patt = vector<vector<int> >(grid.size(), vector<int>(10,0));  
  77.   //tmp.patt.reserve(grid.size());  
  78.   dt.bb.reserve(grid.size());  
  79.   good_boxes.reserve(grid.size());  
  80.   bad_boxes.reserve(grid.size());  
  81.     
  82.   //TLD中定义:cv::Mat pEx;  //positive NN example 大小为15*15图像片  
  83.   pEx.create(patch_size, patch_size, CV_64F);  
  84.     
  85.   //Init Generator   
  86.   //TLD中定义:cv::PatchGenerator generator;  //PatchGenerator类用来对图像区域进行仿射变换  
  87.   /* 
  88.   cv::PatchGenerator::PatchGenerator (     
  89.       double     _backgroundMin, 
  90.       double     _backgroundMax, 
  91.       double     _noiseRange, 
  92.       bool     _randomBlur = true, 
  93.       double     _lambdaMin = 0.6, 
  94.       double     _lambdaMax = 1.5, 
  95.       double     _thetaMin = -CV_PI, 
  96.       double     _thetaMax = CV_PI, 
  97.       double     _phiMin = -CV_PI, 
  98.       double     _phiMax = CV_PI  
  99.    )  
  100.    一般的用法是先初始化一个PatchGenerator的实例,然后RNG一个随机因子,再调用()运算符产生一个变换后的正样本。 
  101.   */  
  102.   generator = PatchGenerator (0,0,noise_init,true,1-scale_init,1+scale_init,-angle_init*CV_PI/180,  
  103.                                 angle_init*CV_PI/180,-angle_init*CV_PI/180,angle_init*CV_PI/180);  
  104.     
  105.   //此函数根据传入的box(目标边界框),在整帧图像中的全部窗口中寻找与该box距离最小(即最相似,  
  106.   //重叠度最大)的num_closest_init个窗口,然后把这些窗口 归入good_boxes容器  
  107.   //同时,把重叠度小于0.2的,归入 bad_boxes 容器  
  108.   //首先根据overlap的比例信息选出重复区域比例大于60%并且前num_closet_init= 10个的最接近box的RectBox,  
  109.   //相当于对RectBox进行筛选。并通过BBhull函数得到这些RectBox的最大边界。  
  110.   getOverlappingBoxes(box, num_closest_init);  
  111.   printf("Found %d good boxes, %d bad boxes\n",(int)good_boxes.size(),(int)bad_boxes.size());  
  112.   printf("Best Box: %d %d %d %d\n",best_box.x, best_box.y, best_box.width, best_box.height);  
  113.   printf("Bounding box hull: %d %d %d %d\n", bbhull.x, bbhull.y, bbhull.width, bbhull.height);  
  114.     
  115.   //Correct Bounding Box   
  116.   lastbox=best_box;  
  117.   lastconf=1;  
  118.   lastvalid=true;  
  119.   //Print   
  120.   fprintf(bb_file,"%d,%d,%d,%d,%f\n",lastbox.x,lastbox.y,lastbox.br().x,lastbox.br().y,lastconf);  
  121.     
  122.   //Prepare Classifier 准备分类器   
  123.   //scales容器里是所有扫描窗口的尺度,由buildGrid()函数初始化  
  124.   classifier.prepare(scales);  
  125.     
  126.   ///Generate Data   
  127.   // Generate positive data   
  128.   generatePositiveData(frame1, num_warps_init);  
  129.     
  130.   // Set variance threshold   
  131.   Scalar stdev, mean;  
  132.   //统计best_box的均值和标准差   
  133.   ////例如需要提取图像A的某个ROI(感兴趣区域,由矩形框)的话,用Mat类的B=img(ROI)即可提取  
  134.   //frame1(best_box)就表示在frame1中提取best_box区域(目标区域)的图像片  
  135.   meanStdDev(frame1(best_box), mean, stdev);  
  136.     
  137.   //利用积分图像去计算每个待检测窗口的方差   
  138.   //cvIntegral( const CvArr* image, CvArr* sum, CvArr* sqsum=NULL, CvArr* tilted_sum=NULL );  
  139.   //计算积分图像,输入图像,sum积分图像, W+1×H+1,sqsum对象素值平方的积分图像,tilted_sum旋转45度的积分图像  
  140.   //利用积分图像,可以计算在某象素的上-右方的或者旋转的矩形区域中进行求和、求均值以及标准方差的计算,  
  141.   //并且保证运算的复杂度为O(1)。     
  142.   integral(frame1, iisum, iisqsum);  
  143.   //级联分类器模块一:方差检测模块,利用积分图计算每个待检测窗口的方差,方差大于var阈值(目标patch方差的50%)的,  
  144.   //则认为其含有前景目标方差;var 为标准差的平方   
  145.   var = pow(stdev.val[0],2) * 0.5; //getVar(best_box,iisum,iisqsum);  
  146.   cout << "variance: " << var << endl;  
  147.     
  148.   //check variance   
  149.   //getVar函数通过积分图像计算输入的best_box的方差  
  150.   double vr =  getVar(best_box, iisum, iisqsum)*0.5;  
  151.   cout << "check variance: " << vr << endl;  
  152.     
  153.   // Generate negative data   
  154.   generateNegativeData(frame1);  
  155.     
  156.   //Split Negative Ferns into Training and Testing sets (they are already shuffled)  
  157.   //将负样本放进 训练和测试集   
  158.   int half = (int)nX.size()*0.5f;  
  159.   //vector::assign函数将区间[start, end)中的值赋值给当前的vector.  
  160.   //将一半的负样本集 作为 测试集   
  161.   nXT.assign(nX.begin()+half, nX.end());  //nXT; //negative data to Test  
  162.   //然后将剩下的一半作为训练集   
  163.   nX.resize(half);  
  164.     
  165.   ///Split Negative NN Examples into Training and Testing sets  
  166.   half = (int)nEx.size()*0.5f;  
  167.   nExT.assign(nEx.begin()+half,nEx.end());  
  168.   nEx.resize(half);  
  169.     
  170.   //Merge Negative Data with Positive Data and shuffle it  
  171.   //将负样本和正样本合并,然后打乱   
  172.   vector<pair<vector<int>,int> > ferns_data(nX.size()+pX.size());  
  173.   vector<int> idx = index_shuffle(0, ferns_data.size());  
  174.   int a=0;  
  175.   for (int i=0;i<pX.size();i++){  
  176.       ferns_data[idx[a]] = pX[i];  
  177.       a++;  
  178.   }  
  179.   for (int i=0;i<nX.size();i++){  
  180.       ferns_data[idx[a]] = nX[i];  
  181.       a++;  
  182.   }  
  183.     
  184.   //Data already have been shuffled, just putting it in the same vector  
  185.   vector<cv::Mat> nn_data(nEx.size()+1);  
  186.   nn_data[0] = pEx;  
  187.   for (int i=0;i<nEx.size();i++){  
  188.       nn_data[i+1]= nEx[i];  
  189.   }  
  190.     
  191.   ///Training     
  192.   //训练 集合分类器(森林) 和 最近邻分类器    
  193.   classifier.trainF(ferns_data, 2); //bootstrap = 2  
  194.   classifier.trainNN(nn_data);  
  195.     
  196.   ///Threshold Evaluation on testing sets   
  197.   //用样本在上面得到的 集合分类器(森林) 和 最近邻分类器 中分类,评价得到最好的阈值  
  198.   classifier.evaluateTh(nXT, nExT);  
  199. }  
  200.   
  201. /* Generate Positive data 
  202.  * Inputs: 
  203.  * - good_boxes (bbP) 
  204.  * - best_box (bbP0) 
  205.  * - frame (im0) 
  206.  * Outputs: 
  207.  * - Positive fern features (pX) 
  208.  * - Positive NN examples (pEx) 
  209.  */  
  210. void TLD::generatePositiveData(const Mat& frame, int num_warps){  
  211.     /* 
  212.     CvScalar定义可存放1—4个数值的数值,常用来存储像素,其结构体如下: 
  213.     typedef struct CvScalar 
  214.     { 
  215.         double val[4]; 
  216.     }CvScalar; 
  217.     如果使用的图像是1通道的,则s.val[0]中存储数据 
  218.     如果使用的图像是3通道的,则s.val[0],s.val[1],s.val[2]中存储数据 
  219.     */  
  220.   Scalar mean;   //均值   
  221.   Scalar stdev;   //标准差   
  222.     
  223.   //此函数将frame图像best_box区域的图像片归一化为均值为0的15*15大小的patch,存在pEx正样本中  
  224.   getPattern(frame(best_box), pEx, mean, stdev);  
  225.     
  226.   //Get Fern features on warped patches   
  227.   Mat img;  
  228.   Mat warped;  
  229.   //void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0,   
  230.   //                                    int borderType=BORDER_DEFAULT ) ;  
  231.   //功能:对输入的图像src进行高斯滤波后用dst输出。  
  232.   //src和dst当然分别是输入图像和输出图像。Ksize为高斯滤波器模板大小,sigmaX和sigmaY分别为高斯滤  
  233.   //波在横向和竖向的滤波系数。borderType为边缘扩展点插值类型。  
  234.   //用9*9高斯核模糊输入帧,存入img  去噪??   
  235.   GaussianBlur(frame, img, Size(9,9), 1.5);  
  236.     
  237.   //在img图像中截取bbhull信息(bbhull是包含了位置和大小的矩形框)的图像赋给warped  
  238.   //例如需要提取图像A的某个ROI(感兴趣区域,由矩形框)的话,用Mat类的B=img(ROI)即可提取  
  239.   warped = img(bbhull);  
  240.   RNG& rng = theRNG();  //生成一个随机数   
  241.   Point2f pt(bbhull.x + (bbhull.width-1)*0.5f, bbhull.y+(bbhull.height-1)*0.5f);  //取矩形框中心的坐标  int i(2)  
  242.     
  243.   //nstructs树木(由一个特征组构建,每组特征代表图像块的不同视图表示)的个数  
  244.   //fern[nstructs] nstructs棵树的森林的数组??   
  245.   vector<int> fern(classifier.getNumStructs());  
  246.   pX.clear();  
  247.   Mat patch;  
  248.   
  249.   //pX为处理后的RectBox最大边界处理后的像素信息,pEx最近邻的RectBox的Pattern,bbP0为最近邻的RectBox。  
  250.   if (pX.capacity() < num_warps * good_boxes.size())  
  251.     pX.reserve(num_warps * good_boxes.size());  //pX正样本个数为 仿射变换个数 * good_box的个数,故需分配至少这么大的空间  
  252.   int idx;  
  253.   for (int i=0; i< num_warps; i++){  
  254.      if (i>0)  
  255.      //PatchGenerator类用来对图像区域进行仿射变换,先RNG一个随机因子,再调用()运算符产生一个变换后的正样本。  
  256.        generator(frame, pt, warped, bbhull.size(), rng);  
  257.        for (int b=0; b < good_boxes.size(); b++){  
  258.          idx = good_boxes[b];  //good_boxes容器保存的是 grid 的索引  
  259.          patch = img(grid[idx]);  //把img的 grid[idx] 区域(也就是bounding box重叠度高的)这一块图像片提取出来  
  260.          //getFeatures函数得到输入的patch的用于树的节点,也就是特征组的特征fern(13位的二进制代码)  
  261.          classifier.getFeatures(patch, grid[idx].sidx, fern);  //grid[idx].sidx 对应的尺度索引  
  262.          pX.push_back(make_pair(fern, 1));   //positive ferns <features, labels=1>  正样本  
  263.      }  
  264.   }  
  265.   printf("Positive examples generated: ferns:%d NN:1\n",(int)pX.size());  
  266. }  
  267.   
  268. //先对最接近box的RectBox区域得到其patch ,然后将像素信息转换为Pattern,  
  269. //具体的说就是归一化RectBox对应的patch的size(放缩至patch_size = 15*15),将2维的矩阵变成一维的向量信息,  
  270. //然后将向量信息均值设为0,调整为zero mean and unit variance(ZMUV)  
  271. //Output: resized Zero-Mean patch  
  272. void TLD::getPattern(const Mat& img, Mat& pattern, Scalar& mean, Scalar& stdev){  
  273.   //将img放缩至patch_size = 15*15,存到pattern中  
  274.   resize(img, pattern, Size(patch_size, patch_size));  
  275.     
  276.   //计算pattern这个矩阵的均值和标准差   
  277.   //Computes a mean value and a standard deviation of matrix elements.  
  278.   meanStdDev(pattern, mean, stdev);  
  279.   pattern.convertTo(pattern, CV_32F);  
  280.     
  281.   //opencv中Mat的运算符有重载, Mat可以 + Mat; + Scalar; + int / float / double 都可以  
  282.   //将矩阵所有元素减去其均值,也就是把patch的均值设为零   
  283.   pattern = pattern - mean.val[0];  
  284. }  
  285.   
  286. /* Inputs: 
  287.  * - Image 
  288.  * - bad_boxes (Boxes far from the bounding box) 
  289.  * - variance (pEx variance) 
  290.  * Outputs 
  291.  * - Negative fern features (nX) 
  292.  * - Negative NN examples (nEx) 
  293.  */  
  294. void TLD::generateNegativeData(const Mat& frame){  
  295.   //由于之前重叠度小于0.2的,都归入 bad_boxes了,所以数量挺多,下面的函数用于打乱顺序,也就是为了  
  296.   //后面随机选择bad_boxes   
  297.   random_shuffle(bad_boxes.begin(), bad_boxes.end());//Random shuffle bad_boxes indexes  
  298.   int idx;  
  299.   //Get Fern Features of the boxes with big variance (calculated using integral images)  
  300.   int a=0;  
  301.   //int num = std::min((int)bad_boxes.size(),(int)bad_patches*100); //limits the size of bad_boxes to try  
  302.   printf("negative data generation started.\n");  
  303.   vector<int> fern(classifier.getNumStructs());  
  304.   nX.reserve(bad_boxes.size());  
  305.   Mat patch;  
  306.   for (int j=0;j<bad_boxes.size();j++){  //把方差较大的bad_boxes加入负样本  
  307.       idx = bad_boxes[j];  
  308.           if (getVar(grid[idx],iisum,iisqsum)<var*0.5f)  
  309.             continue;  
  310.       patch =  frame(grid[idx]);  
  311.       classifier.getFeatures(patch, grid[idx].sidx, fern);  
  312.       nX.push_back(make_pair(fern, 0)); //得到负样本  
  313.       a++;  
  314.   }  
  315.   printf("Negative examples generated: ferns: %d ", a);  
  316.     
  317.   //random_shuffle(bad_boxes.begin(),bad_boxes.begin()+bad_patches);//Randomly selects 'bad_patches' and get the patterns for NN;  
  318.   Scalar dum1, dum2;  
  319.   //bad_patches = (int)file["num_patches"]; 在参数文件中 num_patches = 100  
  320.   nEx=vector<Mat>(bad_patches);  
  321.   for (int i=0;i<bad_patches;i++){  
  322.       idx=bad_boxes[i];  
  323.       patch = frame(grid[idx]);  
  324.       //具体的说就是归一化RectBox对应的patch的size(放缩至patch_size = 15*15)  
  325.       //由于负样本不需要均值和方差,所以就定义dum,将其舍弃  
  326.       getPattern(patch,nEx[i],dum1,dum2);  
  327.   }  
  328.   printf("NN: %d\n",(int)nEx.size());  
  329. }  
  330.   
  331. //该函数通过积分图像计算输入的box的方差   
  332. double TLD::getVar(const BoundingBox& box, const Mat& sum, const Mat& sqsum){  
  333.   double brs = sum.at<int>(box.y+box.height, box.x+box.width);  
  334.   double bls = sum.at<int>(box.y+box.height, box.x);  
  335.   double trs = sum.at<int>(box.y,box.x + box.width);  
  336.   double tls = sum.at<int>(box.y,box.x);  
  337.   double brsq = sqsum.at<double>(box.y+box.height,box.x+box.width);  
  338.   double blsq = sqsum.at<double>(box.y+box.height,box.x);  
  339.   double trsq = sqsum.at<double>(box.y,box.x+box.width);  
  340.   double tlsq = sqsum.at<double>(box.y,box.x);  
  341.     
  342.   double mean = (brs+tls-trs-bls)/((double)box.area());  
  343.   double sqmean = (brsq+tlsq-trsq-blsq)/((double)box.area());  
  344.   //方差=E(X^2)-(EX)^2   EX表示均值   
  345.   return sqmean-mean*mean;  
  346. }  
  347.   
  348. void TLD::processFrame(const cv::Mat& img1,const cv::Mat& img2,vector<Point2f>& points1,vector<Point2f>& points2,BoundingBox& bbnext, bool& lastboxfound, bool tl, FILE* bb_file){  
  349.   vector<BoundingBox> cbb;  
  350.   vector<float> cconf;  
  351.   int confident_detections=0;  
  352.   int didx; //detection index  
  353.     
  354.   ///Track  跟踪模块   
  355.   if(lastboxfound && tl){   //tl: train and learn  
  356.       //跟踪   
  357.       track(img1, img2, points1, points2);  
  358.   }  
  359.   else{  
  360.       tracked = false;  
  361.   }  
  362.     
  363.   ///Detect   检测模块   
  364.   detect(img2);  
  365.     
  366.   ///Integration   综合模块   
  367.   //TLD只跟踪单目标,所以综合模块综合跟踪器跟踪到的单个目标和检测器检测到的多个目标,然后只输出保守相似度最大的一个目标  
  368.   if (tracked){  
  369.       bbnext=tbb;  
  370.       lastconf=tconf;   //表示相关相似度的阈值   
  371.       lastvalid=tvalid;  //表示保守相似度的阈值  
  372.       printf("Tracked\n");  
  373.       if(detected){                                               //   if Detected  
  374.           //通过 重叠度 对检测器检测到的目标bounding box进行聚类,每个类其重叠度小于0.5  
  375.           clusterConf(dbb, dconf, cbb, cconf);                       //   cluster detections  
  376.           printf("Found %d clusters\n",(int)cbb.size());  
  377.           for (int i=0;i<cbb.size();i++){  
  378.               //找到与跟踪器跟踪到的box距离比较远的类(检测器检测到的box),而且它的相关相似度比跟踪器的要大  
  379.               if (bbOverlap(tbb, cbb[i])<0.5 && cconf[i]>tconf){  //  Get index of a clusters that is far from tracker and are more confident than the tracker  
  380.                   confident_detections++;  //记录满足上述条件,也就是可信度比较高的目标box的个数  
  381.                   didx=i; //detection index  
  382.               }  
  383.           }  
  384.           //如果只有一个满足上述条件的box,那么就用这个目标box来重新初始化跟踪器(也就是用检测器的结果去纠正跟踪器)  
  385.           if (confident_detections==1){                                //if there is ONE such a cluster, re-initialize the tracker  
  386.               printf("Found a better match..reinitializing tracking\n");  
  387.               bbnext=cbb[didx];  
  388.               lastconf=cconf[didx];  
  389.               lastvalid=false;  
  390.           }  
  391.           else {  
  392.               printf("%d confident cluster was found\n", confident_detections);  
  393.               int cx=0,cy=0,cw=0,ch=0;  
  394.               int close_detections=0;  
  395.               for (int i=0;i<dbb.size();i++){  
  396.                   //找到检测器检测到的box与跟踪器预测到的box距离很近(重叠度大于0.7)的box,对其坐标和大小进行累加  
  397.                   if(bbOverlap(tbb,dbb[i])>0.7){                     // Get mean of close detections  
  398.                       cx += dbb[i].x;  
  399.                       cy +=dbb[i].y;  
  400.                       cw += dbb[i].width;  
  401.                       ch += dbb[i].height;  
  402.                       close_detections++;   //记录最近邻box的个数  
  403.                       printf("weighted detection: %d %d %d %d\n",dbb[i].x,dbb[i].y,dbb[i].width,dbb[i].height);  
  404.                   }  
  405.               }  
  406.               if (close_detections>0){  
  407.                   //对与跟踪器预测到的box距离很近的box 和 跟踪器本身预测到的box 进行坐标与大小的平均作为最终的  
  408.                   //目标bounding box,但是跟踪器的权值较大  
  409.                   bbnext.x = cvRound((float)(10*tbb.x+cx)/(float)(10+close_detections));   // weighted average trackers trajectory with the close detections  
  410.                   bbnext.y = cvRound((float)(10*tbb.y+cy)/(float)(10+close_detections));  
  411.                   bbnext.width = cvRound((float)(10*tbb.width+cw)/(float)(10+close_detections));  
  412.                   bbnext.height =  cvRound((float)(10*tbb.height+ch)/(float)(10+close_detections));  
  413.                   printf("Tracker bb: %d %d %d %d\n",tbb.x,tbb.y,tbb.width,tbb.height);  
  414.                   printf("Average bb: %d %d %d %d\n",bbnext.x,bbnext.y,bbnext.width,bbnext.height);  
  415.                   printf("Weighting %d close detection(s) with tracker..\n",close_detections);  
  416.               }  
  417.               else{  
  418.                 printf("%d close detections were found\n",close_detections);  
  419.   
  420.               }  
  421.           }  
  422.       }  
  423.   }  
  424.   else{                                       //   If NOT tracking  
  425.       printf("Not tracking..\n");  
  426.       lastboxfound = false;  
  427.       lastvalid = false;  
  428.       //如果跟踪器没有跟踪到目标,但是检测器检测到了一些可能的目标box,那么同样对其进行聚类,但只是简单的  
  429.       //将聚类的cbb[0]作为新的跟踪目标box(不比较相似度了??还是里面已经排好序了??),重新初始化跟踪器  
  430.       if(detected){                           //  and detector is defined  
  431.           clusterConf(dbb,dconf,cbb,cconf);   //  cluster detections  
  432.           printf("Found %d clusters\n",(int)cbb.size());  
  433.           if (cconf.size()==1){  
  434.               bbnext=cbb[0];  
  435.               lastconf=cconf[0];  
  436.               printf("Confident detection..reinitializing tracker\n");  
  437.               lastboxfound = true;  
  438.           }  
  439.       }  
  440.   }  
  441.   lastbox=bbnext;  
  442.   if (lastboxfound)  
  443.     fprintf(bb_file,"%d,%d,%d,%d,%f\n",lastbox.x,lastbox.y,lastbox.br().x,lastbox.br().y,lastconf);  
  444.   else  
  445.     fprintf(bb_file,"NaN,NaN,NaN,NaN,NaN\n");  
  446.       
  447.   ///learn 学习模块   
  448.   if (lastvalid && tl)  
  449.     learn(img2);  
  450. }  
  451.   
  452. /*Inputs: 
  453. * -current frame(img2), last frame(img1), last Bbox(bbox_f[0]). 
  454. *Outputs: 
  455. *- Confidence(tconf), Predicted bounding box(tbb), Validity(tvalid), points2 (for display purposes only) 
  456. */  
  457. void TLD::track(const Mat& img1, const Mat& img2, vector<Point2f>& points1, vector<Point2f>& points2){  
  458.     
  459.   //Generate points   
  460.   //网格均匀撒点(均匀采样),在lastbox中共产生最多10*10=100个特征点,存于points1  
  461.   bbPoints(points1, lastbox);  
  462.   if (points1.size()<1){  
  463.       printf("BB= %d %d %d %d, Points not generated\n",lastbox.x,lastbox.y,lastbox.width,lastbox.height);  
  464.       tvalid=false;  
  465.       tracked=false;  
  466.       return;  
  467.   }  
  468.   vector<Point2f> points = points1;  
  469.     
  470.   //Frame-to-frame tracking with forward-backward error cheking  
  471.   //trackf2f函数完成:跟踪、计算FB error和匹配相似度sim,然后筛选出 FB_error[i] <= median(FB_error) 和   
  472.   //sim_error[i] > median(sim_error) 的特征点(跟踪结果不好的特征点),剩下的是不到50%的特征点  
  473.   tracked = tracker.trackf2f(img1, img2, points, points2);  
  474.   if (tracked){  
  475.       //Bounding box prediction  
  476.       //利用剩下的这不到一半的跟踪点输入来预测bounding box在当前帧的位置和大小 tbb  
  477.       bbPredict(points, points2, lastbox, tbb);  
  478.       //跟踪失败检测:如果FB error的中值大于10个像素(经验值),或者预测到的当前box的位置移出图像,则  
  479.       //认为跟踪错误,此时不返回bounding box;Rect::br()返回的是右下角的坐标  
  480.       //getFB()返回的是FB error的中值   
  481.       if (tracker.getFB()>10 || tbb.x>img2.cols ||  tbb.y>img2.rows || tbb.br().x < 1 || tbb.br().y <1){  
  482.           tvalid =false//too unstable prediction or bounding box out of image  
  483.           tracked = false;  
  484.           printf("Too unstable predictions FB error=%f\n", tracker.getFB());  
  485.           return;  
  486.       }  
  487.         
  488.       //Estimate Confidence and Validity   
  489.       //评估跟踪确信度和有效性   
  490.       Mat pattern;  
  491.       Scalar mean, stdev;  
  492.       BoundingBox bb;  
  493.       bb.x = max(tbb.x,0);  
  494.       bb.y = max(tbb.y,0);  
  495.       bb.width = min(min(img2.cols-tbb.x,tbb.width), min(tbb.width, tbb.br().x));  
  496.       bb.height = min(min(img2.rows-tbb.y,tbb.height),min(tbb.height,tbb.br().y));  
  497.       //归一化img2(bb)对应的patch的size(放缩至patch_size = 15*15),存入pattern  
  498.       getPattern(img2(bb),pattern,mean,stdev);  
  499.       vector<int> isin;  
  500.       float dummy;  
  501.       //计算图像片pattern到在线模型M的保守相似度  
  502.       classifier.NNConf(pattern,isin,dummy,tconf); //Conservative Similarity  
  503.       tvalid = lastvalid;  
  504.       //保守相似度大于阈值,则评估跟踪有效   
  505.       if (tconf>classifier.thr_nn_valid){  
  506.           tvalid =true;  
  507.       }  
  508.   }  
  509.   else  
  510.     printf("No points tracked\n");  
  511.   
  512. }  
《TLD源码理解之TLD.cpp(二)》
  评论这张
 
阅读(1709)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017