轉自:http://blog.csdn.net/zouxy09/article/details/7893056
下面是自己在看論文和這些大牛的分析過程中,對代碼進行了一些了解,但是由于自己接觸圖像處理和機器視覺沒多久,另外由于自己程式設計能力比較弱,是以分析過程可能會有不少的錯誤,希望各位不吝指正。而且,因為程式設計很多地方不懂,是以注釋得非常亂,還海涵。
LKTracker.h
[cpp] view plain copy print ?
- #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;}
- };
#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 ?
- #include <LKTracker.h>
- using namespace cv;
- //金字塔LK光流法跟蹤
- //Media Flow 中值光流跟蹤 加 跟蹤錯誤檢測
- //構造函數,初始化成員變量
- LKTracker::LKTracker(){
- 該類變量需要3個參數,一個是類型,第二個參數為疊代的最大次數,最後一個是特定的門檻值。
- term_criteria = TermCriteria( TermCriteria::COUNT + TermCriteria::EPS, 20, 0.03);
- window_size = Size(4,4);
- level = 5;
- lambda = 0.5;
- }
- bool LKTracker::trackf2f(const Mat& img1, const Mat& img2, vector<Point2f> &points1, vector<cv::Point2f> &points2){
- //TODO!:implement c function cvCalcOpticalFlowPyrLK() or Faster tracking function
- //Forward-Backward tracking
- //基于Forward-Backward Error的中值流跟蹤方法
- //金字塔LK光流法跟蹤
- //forward trajectory 前向軌迹跟蹤
- calcOpticalFlowPyrLK( img1,img2, points1, points2, status, similarity, window_size, level, term_criteria, lambda, 0);
- //backward trajectory 後向軌迹跟蹤
- calcOpticalFlowPyrLK( img2,img1, points2, pointsFB, FB_status,FB_error, window_size, level, term_criteria, lambda, 0);
- //Compute the real FB-error
- //原理很簡單:從t時刻的圖像的A點,跟蹤到t+1時刻的圖像B點;然後倒回來,從t+1時刻的圖像的B點往回跟蹤,
- //假如跟蹤到t時刻的圖像的C點,這樣就産生了前向和後向兩個軌迹,比較t時刻中 A點 和 C點 的距離,如果距離
- //小于一個門檻值,那麼就認為前向跟蹤是正确的;這個距離就是FB_error
- //計算 前向 與 後向 軌迹的誤差
- for( int i= 0; i<points1.size(); ++i ){
- FB_error[i] = norm(pointsFB[i]-points1[i]); //norm()求矩陣或向量的範數??絕對值?
- }
- //Filter out points with FB_error[i] <= median(FB_error) && points with sim_error[i] > median(sim_error)
- normCrossCorrelation(img1, img2, points1, points2);
- return filterPts(points1, points2);
- }
- //利用NCC把跟蹤預測的結果周圍取10*10的小圖檔與原始位置周圍10*10的小圖檔(使用函數getRectSubPix得到)進
- //行模闆比對(調用matchTemplate)
- void LKTracker::normCrossCorrelation(const Mat& img1,const Mat& img2, vector<Point2f>& points1, vector<Point2f>& points2) {
- Mat rec0(10,10,CV_8U);
- Mat rec1(10,10,CV_8U);
- Mat res(1,1,CV_32F);
- for (int i = 0; i < points1.size(); i++) {
- if (status[i] == 1) { //為1表示該特征點跟蹤成功
- //從前一幀和目前幀圖像中(以每個特征點為中心?)提取10x10象素矩形,使用亞象素精度
- getRectSubPix( img1, Size(10,10), points1[i],rec0 );
- getRectSubPix( img2, Size(10,10), points2[i],rec1);
- //比對前一幀和目前幀中提取的10x10象素矩形,得到比對後的映射圖像
- //CV_TM_CCOEFF_NORMED 歸一化相關系數比對法
- //參數分别為:欲搜尋的圖像。搜尋模闆。比較結果的映射圖像。指定比對方法
- matchTemplate( rec0,rec1, res, CV_TM_CCOEFF_NORMED);
- similarity[i] = ((float *)(res.data))[0]; //得到各個特征點的相似度大小
- } else {
- similarity[i] = 0.0;
- }
- }
- rec0.release();
- rec1.release();
- res.release();
- }
- //篩選出 FB_error[i] <= median(FB_error) 和 sim_error[i] > median(sim_error) 的特征點
- //得到NCC和FB error結果的中值,分别去掉中值一半的跟蹤結果不好的點
- bool LKTracker::filterPts(vector<Point2f>& points1,vector<Point2f>& points2){
- //Get Error Medians
- simmed = median(similarity); //找到相似度的中值
- size_t i, k;
- for( i=k = 0; i<points2.size(); ++i ){
- if( !status[i])
- continue;
- if(similarity[i]> simmed){ //剩下 similarity[i]> simmed 的特征點
- points1[k] = points1[i];
- points2[k] = points2[i];
- FB_error[k] = FB_error[i];
- k++;
- }
- }
- if (k==0)
- return false;
- points1.resize(k);
- points2.resize(k);
- FB_error.resize(k);
- fbmed = median(FB_error); //找到FB_error的中值
- for( i=k = 0; i<points2.size(); ++i ){
- if( !status[i])
- continue;
- if(FB_error[i] <= fbmed){ /
- points1[k] = points1[i]; //再對上一步剩下的特征點進一步篩選,剩下 FB_error[i] <= fbmed 的特征點
- points2[k] = points2[i];
- k++;
- }
- }
- points1.resize(k);
- points2.resize(k);
- if (k>0)
- return true;
- else
- return false;
- }