1. 程式人生 > >TLD目標跟蹤演算法學習(三)程式碼理解

TLD目標跟蹤演算法學習(三)程式碼理解

(2)利用金字塔LK光流法跟蹤這些特徵點,並預測當前幀的特徵點(見下面的解釋)、計算FB error和匹配相似度sim,然後篩選出 FB_error[i] <= median(FB_error) 和 sim_error[i] > median(sim_error) 的特徵點(捨棄跟蹤結果不好的特徵點),剩下的是不到50%的特徵點:
  tracker.trackf2f(img1, img2, points, points2);

(3)利用剩下的這不到一半的跟蹤點輸入來預測bounding box在當前幀的位置和大小 tbb:
  bbPredict(points, points2, lastbox, tbb);

(4)跟蹤失敗檢測:如果FB error的中值大於10個畫素(經驗值),或者預測到的當前box的位置移出影象,則認為跟蹤錯誤,此時不返回bounding box:
  if (tracker.getFB()>10 || tbb.x>img2.cols ||  tbb.y>img2.rows || tbb.br().x < 1 || tbb.br().y <1)

(5)歸一化img2(bb)對應的patch的size(放縮至patch_size = 15*15),存入pattern:
  getPattern(img2(bb),pattern,mean,stdev);

(6)計算影象片pattern到線上模型M的保守相似度:
  classifier.NNConf(pattern,isin,dummy,tconf);

(7)如果保守相似度大於閾值,則評估本次跟蹤有效,否則跟蹤無效:
  if (tconf>classifier.thr_nn_valid) tvalid =true;

6.1.2、TLD跟蹤模組的實現原理和trackf2f函式的實現:
  TLD跟蹤模組的實現是利用了Media Flow 中值光流跟蹤和跟蹤錯誤檢測演算法的結合。中值流跟蹤方法是基於Forward-Backward Error和NNC的。原理很簡單:從t時刻的影象的A點,跟蹤到t+1時刻的影象B點;然後倒回來,從t+1時刻的影象的B點往回跟蹤,假如跟蹤到t時刻的影象的C點,這樣就產生了前向和後向兩個軌跡,比較t時刻中 A點和C點的距離,如果距離小於一個閾值,那麼就認為前向跟蹤是正確的;這個距離就是FB_error;
  bool LKTracker::trackf2f(const Mat& img1, const Mat& img2, vector<Point2f> &points1, vector<cv::Point2f> &points2)
函式實現過程如下:
(1)先利用金字塔LK光流法跟蹤預測前向軌跡:
  calcOpticalFlowPyrLK( img1,img2, points1, points2, status, similarity, window_size, level, term_criteria, lambda, 0);

(2)再往回跟蹤,產生後向軌跡:
  calcOpticalFlowPyrLK( img2,img1, points2, pointsFB, FB_status,FB_error, window_size, level, term_criteria, lambda, 0);

(3)然後計算 FB-error:前向與 後向 軌跡的誤差:
  for( int i= 0; i<points1.size(); ++i )
        FB_error[i] = norm(pointsFB[i]-points1[i]);     

(4)再從前一幀和當前幀影象中(以每個特徵點為中心)使用亞象素精度提取10x10象素矩形(使用函式getRectSubPix得到),匹配前一幀和當前幀中提取的10x10象素矩形,得到匹配後的對映影象(呼叫matchTemplate),得到每一個點的NCC相關係數(也就是相似度大小)。
  normCrossCorrelation(img1, img2, points1, points2);

(5)然後篩選出 FB_error[i] <= median(FB_error) 和 sim_error[i] > median(sim_error) 的特徵點(捨棄跟蹤結果不好的特徵點),剩下的是不到50%的特徵點;
  filterPts(points1, points2);