Camshift算法原理及其Opencv實現

Camshift原理

camshift利用目標的顏色直方圖模型將圖像轉換爲顏色概率分佈圖,初始化一個搜索窗的大小和位置,並根據上一幀得到的結果自適應調整搜索窗口的位置和大小,從而定位出當前圖像中目標的中心位置。

分爲三個部分:
1--色彩投影圖(反向投影):
(1).RGB顏色空間對光照亮度變化較爲敏感,爲了減少此變化對跟蹤效果的影響,首先將圖像從RGB空間轉換到HSV空間。(2).然後對其中的H分量作直方圖,在直方圖中代表了不同H分量值出現的概率或者像素個數,就是說可以查找出H分量大小爲h的概率或者像素個數,即得到了顏色概率查找表。(3).將圖像中每個像素的值用其顏色出現的概率對替換,就得到了顏色概率分佈圖。這個過程就叫反向投影,顏色概率分佈圖是一個灰度圖像。

2--meanshift
meanshift算法是一種密度函數梯度估計的非參數方法,通過迭代尋優找到概率分佈的極值來定位目標。
算法過程爲:
(1).在顏色概率分佈圖中選取搜索窗W
(2).計算零階距:

計算一階距:

計算搜索窗的質心:

(3).調整搜索窗大小
寬度爲;長度爲1.2s;
(4).移動搜索窗的中心到質心,如果移動距離大於預設的固定閾值,則重複2)3)4),直到搜索窗的中心與質心間的移動距離小於預設的固定閾值,或者循環運算的次數達到某一最大值,停止計算。關於meanshift的收斂性證明可以google相關文獻。

3--camshift
將meanshift算法擴展到連續圖像序列,就是camshift算法。它將視頻的所有幀做meanshift運算,並將上一幀的結果,即搜索窗的大小和中心,作爲下一幀meanshift算法搜索窗的初始值。如此迭代下去,就可以實現對目標的跟蹤。
算法過程爲:
(1).初始化搜索窗
(2).計算搜索窗的顏色概率分佈(反向投影)
(3).運行meanshift算法,獲得搜索窗新的大小和位置。
(4).在下一幀視頻圖像中用(3)中的值重新初始化搜索窗的大小和位置,再跳轉到(2)繼續進行。

camshift能有效解決目標變形和遮擋的問題,對系統資源要求不高,時間複雜度低,在簡單背景下能夠取得良好的跟蹤效果。但當背景較爲複雜,或者有許多與目標顏色相似像素干擾的情況下,會導致跟蹤失敗。因爲它單純的考慮顏色直方圖,忽略了目標的空間分佈特性,所以這種情況下需加入對跟蹤目標的預測算法。



Camshift的opencv實現

原文http://blog.csdn.net/houdy/archive/2004/11/10/175739.aspx

1--Back Projection
計算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]。

(3).計算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);
(4). result即爲我們需要的.

2--Mean Shift算法
質心可以通過以下公式來計算:
(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

在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)。

3--CamShift算法
整個算法的具體步驟分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繼續運行。

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

更多參考:

帶有註釋的camshift算法的opencv實現代碼見:
http://download.csdn.net/source/1663015
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章