天天看點

TLD特征點跟蹤TLD(Tracking-Learning-Detection)

 TLD(Tracking-Learning-Detection)實作

         TLD(Tracking-Learning-Detection)是英國薩裡大學的一個捷克籍博士生Zdenek Kalal在其攻讀博士學位期間提出的一種新的單目标長時間(long term tracking)跟蹤算法。該算法與傳統跟蹤算法的顯著差別在于将傳統的跟蹤算法和傳統的檢測算法相結合來解決被跟蹤目标在被跟蹤過程中發生的形變、部分遮擋等問題。同時,通過一種改進的線上學習機制不斷更新跟蹤子產品的“顯著特征點”和檢測子產品的目标模型及相關參數,進而使得跟蹤效果更加穩定、魯棒、可靠。

(作者網站的連結http://info.ee.surrey.ac.uk/Personal/Z.Kalal/)

TLD跟蹤的步驟:

(1)讀取兩幅相鄰的影像對(本文以相鄰的視訊幀為例)

frame1 = cvQueryFrame(m_capture) ;  
           

(2)對影像對進行灰階轉換

cvCvtColor( imgi,img_prev ,CV_BGR2GRAY);  
           

(3)采用GFTT特征點檢測算法進行特征點檢測

cvGoodFeaturesToTrack(……)
           
(4)亞像素級角點定位
           
cvFindCornerSubPix(……);
           
(5)特征點追蹤cvCalcOpticalFlowPyrLK(……)
           

opencv函數介紹

(1) void cvGoodFeaturesToTrack( const CvArr* image, CvArr* eig_image, CvArr* temp_image, CvPoint2D32f* corners, int* corner_count, double quality_level, double min_distance, const CvArr* mask=NULL, int block_size = NULL, int use_harris = 0, double k = 0.4 ); image 輸入圖像,8-位或浮點32-比特,單通道; eig_image 臨時浮點32-位圖像,尺寸與輸入圖像一緻; temp_image 另外一個臨時圖像,格式與尺寸與 eig_image 一緻 ;corners 輸出參數,檢測到的 角點 ;corner_count 輸出參數,檢測到的角點數目 ;quality_level 最大最小 特征值 的乘法因子。定義可接受圖像角點的最小品質因子。 ;min_distance 限制因子 。得到的角點的最小距離。使用 Euclidian 距離 ;mask ROI:感興趣區域。函數在ROI中計算 角點 ,如果 mask 為 NULL,則選擇整個圖像。 (2) void cvFindCornerSubPix( const CvArr* image, CvPoint2D32f* corners, int count, CvSize win, CvSize zero_zone, CvTermCriteria criteria ); image 輸入的圖像,必須是8位的 灰階 或者彩色圖像; corners 輸入 角點 的初始坐标,也存儲精确的輸出坐标; count 角點數目; win 搜尋視窗的一半尺寸。如果win=(5,5)那麼使用(5*2+1)×(5*2+1)=11×11大小的搜尋視窗; zero_zone 死區的一半尺寸,死區為不對搜尋區的中央位置做求和運算的區域。它是用來避免 自相關矩陣 出現的某些可能的奇異性。當值為(-1,-1)表示沒有 死區; criteria 求角點的 疊代 過程的終止條件。即角點位置的确定,要麼疊代數大于某個設定值,或者是精确懂達到某個設定值。criteria可以是最大疊代數目,或者是設定的 精确度 ,也可以是它們的組合。 (3) void cvCalcOpticalFlowPyrLK(  const CvArr* prev,  const CvArr* curr,  CvArr* prev_pyr,  CvArr* curr_pyr,  const CvPoint2D32f* prev_features,  CvPoint2D32f* curr_features,  int count,  CvSize win_size,  int level,  char* status,  float* track_error,  CvTermCriteria criteria,  int flags ); prev 在時間 t 的第一幀; curr 在時間 t + dt 的第二幀; prev_pyr 第一幀的金字塔緩存. 如果指針非 NULL , 則緩存必須有足夠的空間來存儲金字塔從層 1 到層 #level 的内容。尺寸 (image_width+8)*image_height/3 比特足夠了; curr_pyr 與 prev_pyr 類似, 用于第二幀; prev_features 需要發現光流的點集; curr_features 包含新計算出來的位置的 點集; count 特征點的數目; win_size 每個金字塔層的搜尋視窗尺寸; level 最大的金字塔層數。如果為 0 , 不使用金字塔 (即金字塔為單層), 如果為 1 , 使用兩層,下面依次類推; status 數組。如果對應特征的光流被發現,數組中的每一個元素都被設定為 1, 否則設定為 0。 error 雙精度數組,包含原始圖像碎片與移動點之間的差。為可選參數,可以是 NULL .; criteria 準則,指定在每個金字塔層,為某點尋找光流的疊代過程的終止條件。

C++主要代碼如下:

m_capture = cvCaptureFromAVI(m_filename) ;              //<span style="font-family: Calibri;">m_filename為</span>視訊檔案路徑
<pre name="code" class="cpp" style="color: rgb(0, 0, 255); font-size: 18px; line-height: 26px;">
           
frame1 = cvQueryFrame(m_capture) ;                      //擷取一幀圖像
           

imgi = cvCreateImage(cvGetSize(frame), 8, 3 ) ; //建立imgi cvCopyImage(frame,imgi) ; //将前一幀存入imgiframe1 = cvQueryFrame(m_capture) ;if (frame != NULL){ cvReleaseImage(&frame) ;}frame = cvCreateImage(I_size1, frame1->depth, frame1->nChannels) ;cvResize(frame1, frame , CV_INTER_NN) ;imgi1 = cvCreateImage( cvGetSize(frame), 8, 3 ); //建立imgi1cvCopyImage(frame,imgi1); //将目前幀存入imgi1

IplImage* img_prev = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,1) ;  
		cvCvtColor( imgi,img_prev ,CV_BGR2GRAY);  
		IplImage* img_curr = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,1) ;  
		cvCvtColor( imgi1,img_curr ,CV_BGR2GRAY);  

		IplImage* img_eig = cvCreateImage(cvGetSize(frame),IPL_DEPTH_32F,1) ;  
		IplImage* img_temp = cvCreateImage(cvGetSize(frame),IPL_DEPTH_32F,1) ; 
                //用GFTT檢測特征點
		cvGoodFeaturesToTrack(  
			img_prev,  
			img_eig,  
			img_temp,  
			features_prev,  
			&corner_count,  
			0.01,  
			5.0,  
			0,  
			3,  
			0,  
			0.4  
			);  

		cvFindCornerSubPix(  
			img_prev,  
			features_prev,  
			corner_count,  
			cvSize(10,10),  
			cvSize(-1,-1),  
			cvTermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER,20,0.03)  
			); 

		CvSize pyr_sz = cvSize( frame->width + 8 ,frame->height / 3 ) ;  

		IplImage* pyr_prev = cvCreateImage(cvGetSize(frame),IPL_DEPTH_32F,1) ;  
		IplImage* pyr_cur = cvCreateImage(cvGetSize(frame),IPL_DEPTH_32F,1) ;  
		//追蹤特征點
		cvCalcOpticalFlowPyrLK(  
			img_prev,  
			img_curr,  
			pyr_prev,  
			pyr_cur,  
			features_prev,           
			features_cur,  
			corner_count,  
			cvSize(10,10),  
			5,  
			feature_found,  
			feature_errors,  
			cvTermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER,20,0.3),  
			0  
			);  

		//features_cur[];features_prev[]即為追蹤到的角點。
           

繼續閱讀