天天看點

TLD(Tracking-Learning-Detection)學習與源碼了解之(五) .

轉自:http://blog.csdn.net/zouxy09/article/details/7893056

下面是自己在看論文和這些大牛的分析過程中,對代碼進行了一些了解,但是由于自己接觸圖像處理和機器視覺沒多久,另外由于自己程式設計能力比較弱,是以分析過程可能會有不少的錯誤,希望各位不吝指正。而且,因為程式設計很多地方不懂,是以注釋得非常亂,還海涵。

LKTracker.h

[cpp] view plain copy print ?

  1. #include<tld_utils.h>   
  2. #include <opencv2/opencv.hpp>   
  3. //使用金字塔LK光流法跟蹤,是以類的成員變量很多都是OpenCV中calcOpticalFlowPyrLK()函數的參數   
  4. class LKTracker{  
  5. private:  
  6.   std::vector<cv::Point2f> pointsFB;  
  7.   cv::Size window_size;  //每個金字塔層的搜尋視窗尺寸   
  8.   int level;            //最大的金字塔層數   
  9.   std::vector<uchar> status;   //數組。如果對應特征的光流被發現,數組中的每一個元素都被設定為 1, 否則設定為 0   
  10.   std::vector<uchar> FB_status;     
  11.   std::vector<float> similarity;  //相似度   
  12.   std::vector<float> FB_error;   //Forward-Backward error方法,求FB_error的結果與原始位置的歐式距離   
  13.                                  //做比較,把距離過大的跟蹤結果舍棄   
  14.   float simmed;  
  15.   float fbmed;  
  16.   //TermCriteria模闆類,取代了之前的CvTermCriteria,這個類是作為疊代算法的終止條件的   
  17.   //該類變量需要3個參數,一個是類型,第二個參數為疊代的最大次數,最後一個是特定的門檻值。   
  18.   //指定在每個金字塔層,為某點尋找光流的疊代過程的終止條件。   
  19.   cv::TermCriteria term_criteria;  
  20.   float lambda;   //某門檻值??Lagrangian 乘子   
  21.   // NCC 歸一化交叉相關,FB error與NCC結合,使跟蹤更穩定  交叉相關的圖像比對算法??   
  22.   //交叉相關法的作用是進行雲團移動的短時預測。選取連續兩個時次的GMS-5衛星雲圖,将雲圖區域劃分為32×32像素   
  23.   //的圖像子集,采用交叉相關法計算擷取兩幅雲圖的最佳比對區域,根據前後雲圖比對區域的位置和時間間隔,确   
  24.   //定出每個圖像子集的移動矢量(速度和方向),并對圖像子集的移動矢量進行客觀分析,其後,基于檢驗後的雲   
  25.   //圖移動矢量集,利用後向軌迹方法對雲圖作短時外推預測。   
  26.   void normCrossCorrelation(const cv::Mat& img1, const cv::Mat& img2, std::vector<cv::Point2f>& points1, std::vector<cv::Point2f>& points2);  
  27.   bool filterPts(std::vector<cv::Point2f>& points1,std::vector<cv::Point2f>& points2);  
  28. public:  
  29.   LKTracker();  
  30.   //特征點的跟蹤??   
  31.   bool trackf2f(const cv::Mat& img1, const cv::Mat& img2,  
  32.                 std::vector<cv::Point2f> &points1, std::vector<cv::Point2f> &points2);  
  33.   float getFB(){return fbmed;}  
  34. };  
#include<tld_utils.h>
#include <opencv2/opencv.hpp>

//使用金字塔LK光流法跟蹤,是以類的成員變量很多都是OpenCV中calcOpticalFlowPyrLK()函數的參數
class LKTracker{
private:
  std::vector<cv::Point2f> pointsFB;
  cv::Size window_size;  //每個金字塔層的搜尋視窗尺寸
  int level;            //最大的金字塔層數
  std::vector<uchar> status;   //數組。如果對應特征的光流被發現,數組中的每一個元素都被設定為 1, 否則設定為 0
  std::vector<uchar> FB_status;   
  std::vector<float> similarity;  //相似度
  std::vector<float> FB_error;   //Forward-Backward error方法,求FB_error的結果與原始位置的歐式距離
                                 //做比較,把距離過大的跟蹤結果舍棄
  float simmed;
  float fbmed;
  //TermCriteria模闆類,取代了之前的CvTermCriteria,這個類是作為疊代算法的終止條件的
  //該類變量需要3個參數,一個是類型,第二個參數為疊代的最大次數,最後一個是特定的門檻值。
  //指定在每個金字塔層,為某點尋找光流的疊代過程的終止條件。
  cv::TermCriteria term_criteria;
  float lambda;   //某門檻值??Lagrangian 乘子
  // NCC 歸一化交叉相關,FB error與NCC結合,使跟蹤更穩定  交叉相關的圖像比對算法??
  //交叉相關法的作用是進行雲團移動的短時預測。選取連續兩個時次的GMS-5衛星雲圖,将雲圖區域劃分為32×32像素
  //的圖像子集,采用交叉相關法計算擷取兩幅雲圖的最佳比對區域,根據前後雲圖比對區域的位置和時間間隔,确
  //定出每個圖像子集的移動矢量(速度和方向),并對圖像子集的移動矢量進行客觀分析,其後,基于檢驗後的雲
  //圖移動矢量集,利用後向軌迹方法對雲圖作短時外推預測。
  void normCrossCorrelation(const cv::Mat& img1, const cv::Mat& img2, std::vector<cv::Point2f>& points1, std::vector<cv::Point2f>& points2);
  bool filterPts(std::vector<cv::Point2f>& points1,std::vector<cv::Point2f>& points2);
public:
  LKTracker();
  //特征點的跟蹤??
  bool trackf2f(const cv::Mat& img1, const cv::Mat& img2,
                std::vector<cv::Point2f> &points1, std::vector<cv::Point2f> &points2);
  float getFB(){return fbmed;}
};

           

LKTracker.cpp

[cpp] view plain copy print ?

  1. #include <LKTracker.h>   
  2. using namespace cv;  
  3. //金字塔LK光流法跟蹤   
  4. //Media Flow 中值光流跟蹤 加 跟蹤錯誤檢測   
  5. //構造函數,初始化成員變量   
  6. LKTracker::LKTracker(){  
  7.   該類變量需要3個參數,一個是類型,第二個參數為疊代的最大次數,最後一個是特定的門檻值。   
  8.   term_criteria = TermCriteria( TermCriteria::COUNT + TermCriteria::EPS, 20, 0.03);  
  9.   window_size = Size(4,4);  
  10.   level = 5;  
  11.   lambda = 0.5;  
  12. }  
  13. bool LKTracker::trackf2f(const Mat& img1, const Mat& img2, vector<Point2f> &points1, vector<cv::Point2f> &points2){  
  14.   //TODO!:implement c function cvCalcOpticalFlowPyrLK() or Faster tracking function   
  15.   //Forward-Backward tracking   
  16.   //基于Forward-Backward Error的中值流跟蹤方法   
  17.   //金字塔LK光流法跟蹤   
  18.   //forward trajectory 前向軌迹跟蹤   
  19.   calcOpticalFlowPyrLK( img1,img2, points1, points2, status, similarity, window_size, level, term_criteria, lambda, 0);  
  20.   //backward trajectory 後向軌迹跟蹤   
  21.   calcOpticalFlowPyrLK( img2,img1, points2, pointsFB, FB_status,FB_error, window_size, level, term_criteria, lambda, 0);  
  22.   //Compute the real FB-error   
  23.   //原理很簡單:從t時刻的圖像的A點,跟蹤到t+1時刻的圖像B點;然後倒回來,從t+1時刻的圖像的B點往回跟蹤,   
  24.   //假如跟蹤到t時刻的圖像的C點,這樣就産生了前向和後向兩個軌迹,比較t時刻中 A點 和 C點 的距離,如果距離   
  25.   //小于一個門檻值,那麼就認為前向跟蹤是正确的;這個距離就是FB_error   
  26.   //計算 前向 與 後向 軌迹的誤差   
  27.   for( int i= 0; i<points1.size(); ++i ){  
  28.         FB_error[i] = norm(pointsFB[i]-points1[i]);   //norm()求矩陣或向量的範數??絕對值?   
  29.   }  
  30.   //Filter out points with FB_error[i] <= median(FB_error) && points with sim_error[i] > median(sim_error)   
  31.   normCrossCorrelation(img1, img2, points1, points2);  
  32.   return filterPts(points1, points2);  
  33. }  
  34. //利用NCC把跟蹤預測的結果周圍取10*10的小圖檔與原始位置周圍10*10的小圖檔(使用函數getRectSubPix得到)進   
  35. //行模闆比對(調用matchTemplate)   
  36. void LKTracker::normCrossCorrelation(const Mat& img1,const Mat& img2, vector<Point2f>& points1, vector<Point2f>& points2) {  
  37.         Mat rec0(10,10,CV_8U);  
  38.         Mat rec1(10,10,CV_8U);  
  39.         Mat res(1,1,CV_32F);  
  40.         for (int i = 0; i < points1.size(); i++) {  
  41.                 if (status[i] == 1) {  //為1表示該特征點跟蹤成功   
  42.                         //從前一幀和目前幀圖像中(以每個特征點為中心?)提取10x10象素矩形,使用亞象素精度   
  43.                         getRectSubPix( img1, Size(10,10), points1[i],rec0 );     
  44.                         getRectSubPix( img2, Size(10,10), points2[i],rec1);  
  45.                         //比對前一幀和目前幀中提取的10x10象素矩形,得到比對後的映射圖像   
  46.                         //CV_TM_CCOEFF_NORMED 歸一化相關系數比對法   
  47.                         //參數分别為:欲搜尋的圖像。搜尋模闆。比較結果的映射圖像。指定比對方法   
  48.                         matchTemplate( rec0,rec1, res, CV_TM_CCOEFF_NORMED);   
  49.                         similarity[i] = ((float *)(res.data))[0];  //得到各個特征點的相似度大小   
  50.                 } else {  
  51.                         similarity[i] = 0.0;  
  52.                 }  
  53.         }  
  54.         rec0.release();  
  55.         rec1.release();  
  56.         res.release();  
  57. }  
  58. //篩選出 FB_error[i] <= median(FB_error) 和 sim_error[i] > median(sim_error) 的特征點   
  59. //得到NCC和FB error結果的中值,分别去掉中值一半的跟蹤結果不好的點   
  60. bool LKTracker::filterPts(vector<Point2f>& points1,vector<Point2f>& points2){  
  61.   //Get Error Medians   
  62.   simmed = median(similarity);   //找到相似度的中值   
  63.   size_t i, k;  
  64.   for( i=k = 0; i<points2.size(); ++i ){  
  65.         if( !status[i])  
  66.           continue;  
  67.         if(similarity[i]> simmed){   //剩下 similarity[i]> simmed 的特征點   
  68.           points1[k] = points1[i];     
  69.           points2[k] = points2[i];  
  70.           FB_error[k] = FB_error[i];  
  71.           k++;  
  72.         }  
  73.     }  
  74.   if (k==0)  
  75.     return false;  
  76.   points1.resize(k);  
  77.   points2.resize(k);  
  78.   FB_error.resize(k);  
  79.   fbmed = median(FB_error);     //找到FB_error的中值   
  80.   for( i=k = 0; i<points2.size(); ++i ){  
  81.       if( !status[i])  
  82.         continue;  
  83.       if(FB_error[i] <= fbmed){   /  
  84.         points1[k] = points1[i];   //再對上一步剩下的特征點進一步篩選,剩下 FB_error[i] <= fbmed 的特征點   
  85.         points2[k] = points2[i];  
  86.         k++;  
  87.       }  
  88.   }  
  89.   points1.resize(k);  
  90.   points2.resize(k);  
  91.   if (k>0)  
  92.     return true;  
  93.   else  
  94.     return false;  
  95. }  

繼續閱讀