光流(四)--Kanade-Lucas-Tomasi(KLT)目標跟蹤
原文:
http://www.cnblogs.com/moondark/archive/2012/05/12/2497391.html
近來在研究跟蹤,跟蹤的方法其實有很多,如粒子濾波(pf)、meanshift跟蹤,以及KLT跟蹤或叫Lucas光流法,這些方法各自有各自的有點,對於粒子濾波而言,它能夠比較好的在全域性搜尋到最優解,但其求解速度相對較慢,由於其是基於顏色直方圖的計算,所以對相同顏色東西不太能夠區別,meanshift方法很容易陷入區域性最優,但速度還是挺快,所以現在很有一些人是將meanshift跟pf結合做跟蹤,恰好在很多方面能夠互補。
Kanade-Lucas-Tomasi方法,在跟蹤方面表現的也不錯,尤其在實時計算速度上,用它來得到的,是很多點的軌跡“trajectory”,並且還有一些發生了漂移的點,所以,得到跟蹤點之後要進行一些後期的處理,說到Kanade-Lucas-Tomasi方法,首先要追溯到Kanade-Lucas兩人在上世紀80年代發表的paper:An Iterative Image Registration Technique with an Application to Stereo Vision,這裡講的是一種影象點定位的方法,即影象的區域性匹配,將影象匹配問題,從傳統的滑動視窗搜尋方法變為一個求解偏移量d的過程,後來Jianbo Shi和Carlo Tomasi兩人發表了一篇CVPR(94')的文章Good Features To Track,這篇文章,主要就是講,在求解d的過程中,哪些情況下可以保證一定能夠得到d的解,這些情況的點有什麼特點(後來會發現,很多時候都是尋找的角點)。
PS: 其實我很奇怪這個演算法為什麼叫做KLT演算法,而不加上Jianbo Shi的名字~
好吧,前戲就這麼多,接下來進入正題,KLT是如何實現跟蹤的?
先說KLT演算法的幾個前提假設:
1)亮度恆定
2)時間連續或者是運動是“小運動”
3)空間一致,臨近點有相似運動,保持相鄰
這幾個為什麼要這麼假設,我在後面來解釋,很直觀的講,如果判斷一個視訊的相鄰兩幀I、J在某區域性視窗w上是一樣的,則在視窗w內有:I(x, y, t) = J(x', y', t+τ),亮度恆定的假設(假設1)即為了保證其等號成立不受亮度的影響,假設2是為了保證KLT能夠找到點,假設3則為以下原因假設(即對於同一個視窗中,所有點的偏移量都相等):
在視窗w上,所有(x, y)都往一個方向移動了(dx, dy),從而得到(x', y'),即t時刻的(x, y)點在t+τ時刻為(x+dx, y+dy),所以尋求匹配的問題可化為對以下的式子尋求最小值,或叫做最小化以下式子:
用積分來表示上述式子,以上式子可等效為:
這個式子的含義,即找到兩副影象中,在W視窗中,I、J的差異,其中I以x-d/2為中心,J以x+d/2為中心,w/2為半徑的一個矩形視窗間的差異,好吧,結合我們微積分的知識,函式ε(d)要取得最小值,這個極值點的導數一定為0,即
的值為0,由泰勒展開的性質:
可以得到:
於是,問題轉化為:
其中:
從而,問題即為:
=>
即其等式可看作為:
其中,Z為一個2*2的矩陣,e為一個2*1的向量,
為了要使d能夠得到解,則Z需要滿足條件,即Z*Z'矩陣可逆,其中Z'為Z矩陣的轉置(ZT),在一般情況下,角點具有這樣的特點。
在OpenCV裡面,找角點的函式可用
void cvGoodFeaturesToTrack( const CvArr* image CvArr* eigImage, CvArr* tempImage CvPoint2D32f* corners int* cornerCount double qualityLevel double minDistance const CvArr* mask=NULL int blockSize=3 int useHarris=0 //一般採用Harris角點 double k=0.04 );
然後可以通過函式cvCalcOpticalFlowPyrLK進行跟蹤(好像OpenCV裡面呼叫LK的函式不止這一個,這個是金字塔計算):
void cvCalcOpticalFlowPyrLK( const CvArr* prev, const CvArr* curr, CvArr* prevPyr, CvArr* currPyr, const CvPoint2D32f* prevFeatures, CvPoint2D32f* currFeatures, int count, CvSize winSize, int level, char* status, float* track error, CvTermCriteria criteria, int flags );
OK,KLT演算法的原理基本就這樣,其實其跟蹤效果並非太準,後來有很多提出的校正的方法,其中我目前看到比較實用的就是TLD演算法的作者Zdenek Kalal在他2010年ICPR上的文章Forward-Backward Error: Automatic Detection of Tracking Failures提出的方法看起來非常不錯,我正動手實現之。