Mean Shift算法(CamShift)

轉自http://hi.baidu.com/www_djh/blog/item/6ff6c063b060d454eaf8f85e.html

/*****************************************************************************/
CamShift算法,即"Continuously Apative Mean-Shift"算法,是一種運動跟蹤算法。它主要通過視頻圖像中運動物體的顏色信息來達到跟蹤的目的。我把這個算法分解成三個部分,便於理解:
1) Back Projection計算
2) Mean Shift算法
3) CamShift算法
在這裏主要討論Back Projection,在隨後的文章中繼續討論後面兩個算法。

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即爲我們需要的.

算法分析
用在cvCalcBackProject處理中的模板是目標圖像色調(HUE)的直方圖,而直方圖可以看作是一種概率分佈圖。在處理前,目標圖像中的每一個象素的值描述的在這一點的顏色信息,而處理後,圖像中每一個象素的值就變成了這個顏色信息出現在此處的可能性的一種離散化的度量,出現的可能性大,象素的值就大,反之則小。這樣就爲後面的匹配和跟蹤提供了線索。
這裏來到了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:迭代的次數。

實現代碼:暫時缺

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:包含被跟蹤物體的最小矩形。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章