1. 程式人生 > >CamShift 目標跟蹤演算法研究(轉)

CamShift 目標跟蹤演算法研究(轉)

CamShift演算法:
    CamShift演算法,即"Continuously Apative Mean-Shift"演算法,是一種運動跟蹤演算法。它主要通過視訊影象中運動物體的顏色資訊來達到跟蹤的目的。
    我把這個演算法分解成三個部分,便於理解:
    1) Back Projection(背景放映)計算
    2) Mean Shift(平均轉換)演算法
    3) CamShift演算法
(注意:上面的翻譯純屬個人理解!)
1)Back Projection:
計算Back Projection的步驟是這樣的:
1. 計算被跟蹤目標的色彩直方圖。在各種色彩空間中,只有HSI空間(或與HSI類似的色彩空間)中的H分量可以表示顏色資訊。所以在具體的計算過程中,首先將其他的色彩空間的值轉化到HSI空間,然後會其中的H分量做1D直方圖計算。


2. 根據獲得的色彩直方圖將原始影象轉化成色彩概率分佈圖像,這個過程就被稱作"Back Projection"。
在OpenCV中的直方圖函式中,包含Back Projection的函式,函式原型是:
   void cvCalcBackProject(IplImage** img, CvArr** backproject, const CvHistogram* hist);
傳遞給這個函式的引數有三個:
1. IplImage** img:存放原始影象,輸入。
2. CvArr** backproject:存放Back Projection結果,輸出。
3. CvHistogram* hist:存放直方圖,輸入

下面就給出計算Back Projection的OpenCV程式碼。
1.準備一張只包含被跟蹤目標的圖片,將色彩空間轉化到HSI空間,獲得其中的H分量:
IplImage* target=cvLoadImage("target.bmp",-1); //裝載圖片
IplImage* target_hsv=cvCreateImage( cvGetSize(target), IPL_DEPTH_8U, 3 );
IplImage* target_hue=cvCreateImage( cvGetSize(target), IPL_DEPTH_8U, 3 );
cvCvtColor(target,target_hsv,CV_BGR2HSV);       //轉化到HSV空間
cvSplit( target_hsv, target_hue, NULL, NULL, NULL );    //獲得H分量


2.計算H分量的直方圖,即1D直方圖:
IplImage* h_plane=cvCreateImage( cvGetSize(target_hsv),IPL_DEPTH_8U,1 );
int hist_size[]={255};          //將H分量的值量化到[0,255]
float* ranges[]={ {0,360} };    //H分量的取值範圍是[0,360)
CvHistogram* hist=cvCreateHist(1, hist_size, ranges, 1);
cvCalcHist(&target_hue, hist, 0, NULL);

在這裡需要考慮H分量的取值範圍的問題,H分量的取值範圍是[0,360),這個取值範圍的值不能用一個byte來表示,為了能用一個byte表示,需要將H值做適當的量化處理,在這裡我們將H分量的範圍量化到[0,255].
4.計算Back Projection:
IplImage* rawImage;
//----------------------------------------------
//get from video frame,unsigned byte,one channel
//----------------------------------------------
IplImage* result=cvCreateImage(cvGetSize(rawImage),IPL_DEPTH_8U,1);
cvCalcBackProject(&rawImage,result,hist);

5.結果:result即為我們需要的.

2.Mean Shift:

CamShift演算法,OpenCV實現2-Mean Shift演算法
這裡來到了CamShift演算法,OpenCV實現的第二部分,這一次重點討論Mean Shift演算法。
在討論Mean Shift演算法之前,首先討論在2D概率分佈圖像中,如何計算某個區域的重心(Mass Center)的問題,重心可以通過以下公式來計算:
1.計算區域內0階矩
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
     M00+=I(i,j)
2.區域內1階矩:
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
{
    M10+=i*I(i,j);
    M01+=j*I(i,j);
}
3.則Mass Center為:
Xc=M10/M00; Yc=M01/M00
接下來,討論Mean Shift演算法的具體步驟,Mean Shift演算法可以分為以下4步:
1.選擇窗的大小和初始位置.
2.計算此時視窗內的Mass Center.
3.調整視窗的中心到Mass Center.
4.重複2和3,直到視窗中心"會聚",即每次視窗移動的距離小於一定的閾值。

在OpenCV中,提供Mean Shift演算法的函式,函式的原型是:
int cvMeanShift(IplImage* imgprob,CvRect windowIn,
                    CvTermCriteria criteria,CvConnectedComp* out);

需要的引數為:
1.IplImage* imgprob:2D概率分佈圖像,傳入;
2.CvRect windowIn:初始的視窗,傳入;
3.CvTermCriteria criteria:停止迭代的標準,傳入;
4.CvConnectedComp* out:查詢結果,傳出。
(注:構造CvTermCriteria變數需要三個引數,一個是型別,另一個是迭代的最大次數,最後一個表示特定的閾值。例如可以這樣構造criteria:criteria=cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,10,0.1)。)

返回的引數:
1.int:迭代的次數。

實現程式碼:暫時缺

3.CamShift:

CamShift演算法,OpenCV實現(3):CamShift演算法

1.原理
在瞭解了MeanShift演算法以後,我們將MeanShift演算法擴充套件到連續影象序列(一般都是指視訊影象序列),這樣就形成了CamShift演算法。CamShift演算法的全稱是"Continuously Apaptive Mean-SHIFT",它的基本思想是視訊影象的所有幀作MeanShift運算,並將上一幀的結果(即Search Window的中心和大小)作為下一幀MeanShift演算法的Search Window的初始值,如此迭代下去,就可以實現對目標的跟蹤。整個演算法的具體步驟分5步:
Step 1:將整個影象設為搜尋區域。
Step 2:初始話Search Window的大小和位置。
Step 3:計算Search Window內的彩色概率分佈,此區域的大小比Search Window要稍微大一點。
Step 4:執行MeanShift。獲得Search Window新的位置和大小。
Step 5:在下一幀視訊影象中,用Step 3獲得的值初始化Search Window的位置和大小。跳轉到Step 3繼續執行。

2.實現
在OpenCV中,有實現CamShift演算法的函式,此函式的原型是:
cvCamShift(IplImage* imgprob, CvRect windowIn,
                CvTermCriteria criteria,
                CvConnectedComp* out, CvBox2D* box=0);
其中:
   imgprob:色彩概率分佈圖像。
   windowIn:Search Window的初始值。
   Criteria:用來判斷搜尋是否停止的一個標準。
   out:儲存運算結果,包括新的Search Window的位置和麵積。
   box:包含被跟蹤物體的最小矩形。

說明:
1.在OpenCV 3.1 beta的目錄中,有CamShift的例子。遺憾的是這個例子目標的跟蹤是半自動的,即需要人手工選定一個目標。我正在努力嘗試全自動的目標跟蹤,希望可以和大家能在這方面與大家交流。(已經實現自動的東西)