將KCF應用於Tracking by detection的總結

1、前言

由於目前基於深度學習的detection在實際使用中仍然存在很多的誤檢和漏檢,顯然在實際使用中無法只依賴detection模塊作爲感知,而傳統MOT也存很多因素導致追蹤目標丟失必須重新手動選擇的問題,因此,Tracking by detection成爲一個很重要的研究方向,而Tracking by detection中前後幀的目標匹配算法成爲研究重點,目前已經有很多相關的研究,諸如前幾年的Beyond Pixels: Leveraging Geometry and Shape Cues for OnlineMulti-Object Tracking,和最近利用深度學習提取特徵的Towards Real-Time Multi-Object Tracking,前者同時利用了先驗的幾何信息結合深度學習提取特徵,但由於計算量大,幾乎無法實現real-time,autoware的開源代碼中實現了一版將其深度學習部分去掉的版本,實際應用效果不錯,由於只涉及幾何計算,速度很快,幾乎無延遲,但對於場景和設備安裝要求很高;後者是一個很有前景的方向,將檢測與特徵提取集成在一個網絡中實現,是一個很有前景的發展方向,但是目前其數據集有限,檢測目標種類較少,需要自行籌備數據集進行訓練,因此先持觀望態度。
最終選擇了apollo系統中應用的方案,將前幾年十分火爆的KCF算法中的部分提取出來,作爲目標匹配算法使用,結合一個單獨的檢測器,整體效果還算不錯。

2、KCF

關於KCF的詳細解析已有很多文章加以描述,這裏主要記錄下自己學習中的一些理解和遇到的坑,具體就不擴充了。論文主要介紹了一種使用核方法來區分目標是否是追蹤目標或是背景的方法,其主要使用方法很簡單,是一種基於核方法的嶺迴歸,整體的訓練方式和預測都跟嶺迴歸基本相同(因此論文第二部分詳細介紹了嶺迴歸),其最大的亮點在於使用循環矩陣和傅立葉變換的思路大大加快了計算。其整體流程如下:

  • 1、遵循循環矩陣的方式擴展樣本
    如下圖所示
    樣本擴充假如追蹤塊是m*n矩陣,則可以擴充爲m*n個樣本,每個樣本大小都跟追蹤塊一樣大爲m*n,生成的樣本矩陣叫做塊循環矩陣,詳見循環矩陣傅里葉對角化中二維的部分。
  • 2、使用樣本矩陣計算核矩陣
    關於核方法,其本質是將一個非線性可分問題轉化爲一個線性可分問題,當樣本在其原本空間(低維度)中線性不可分時,使用一個ϕ(x)\phi(x)將其轉化到高維空間中,使原問題在高維空間變成一個線性可分問題,核方法使得我們並不需要對所有樣本調用ϕ(x)\phi(x),因爲模型的訓練和使用過程中都只需要用到zTz,z=ϕ(x)z^Tz,z=\phi(x),因此定義K(x,y)=ϕ(x)Tϕ(y)K(x,y)=\phi(x)^T\phi(y),K爲使用的具體核函數,例如高斯核函數,其本質上就是將原樣本提高了維度(反推可以得到ϕ(x)\phi(x))因此我們整個過程中只需要使用這個核函數即可。論文中關於核方法的嶺迴歸,其訓練模型主要是爲了得到α\alpha,可以對應爲嶺迴歸中的權重w,而α\alpha的求解與核矩陣K(核矩陣可以對應爲嶺迴歸中的樣本矩陣X)直接相關,而核矩陣實際上就是每個樣本依次與所有樣本作覈計算得到的向量疊成的矩陣,原樣本爲x0,x1,...,xn1x_0,x_1,...,x_{n-1},則核矩陣如下:
    X=[k(x0,x0)k(x0,x1)k(x0,xn1)k(x1,x0)k(x1,x1)k(x1,xn1)k(xn1,x0)k(xn1,x1)k(xn1,xn1)] (1) X=\begin{bmatrix}\\ k(x_0,x_0) & k(x_0,x_1) & \dots & k(x_0,x_{n-1}) \\ k(x_1,x_0) & k(x_1,x_1) & \dots &k(x_1,x_{n-1}) \\ \vdots & \vdots & \ddots & \vdots \\ k(x_{n-1},x_0) & k(x_{n-1},x_1) & \dots &k(x_{n-1},x_{n-1}) \\ \end{bmatrix} \ (1)
    由於樣本是循環的,則有Pkx=PkmodnxP^{k}x=P^{kmodn}x,主要用於k爲負數時計算,若核函數滿足k(x,y)=k(Pnx,Pny)k(x,y)=k(P^nx,P^ny)(其中P爲初等行變換矩陣)則可以寫成如下形式:
    X=[k(x0,x0)k(x0,x1)k(x0,xn1)k(x0,xn1)k(x0,x0)k(x0,xn2)k(x0,x1)k(x0,x2)k(x0,x0)] (2) X=\begin{bmatrix}\\ k(x_0,x_0) & k(x_0,x_1) & \dots & k(x_0,x_{n-1}) \\ k(x_0,x_{n-1}) & k(x_0,x_0) & \dots &k(x_0,x_{n-2}) \\ \vdots & \vdots & \ddots & \vdots \\ k(x_{0},x_1) & k(x_{0},x_2) & \dots &k(x_{0},x_{0}) \\ \end{bmatrix}\ (2)
    K即爲循環矩陣。
    這個一維形式還比較容易推導和理解,而二維形式個人花了很多時間去理解,實際上其推導與一維形式基本一致,只是在表現形式上不同,一維原樣本集可以寫成:
    X=[x0,x1,...,xn1]T K=ϕ(X)ϕ(X)T X=[x_0,x_1,...,x_{n-1}]^T \ \\ K=\phi(X)\phi(X)^T
    二維原樣本集爲:
    X=[x11x12x1nx21x22x2nxm1xm2xmn] X=\begin{bmatrix}\\ x_{11} & x_{12} & \dots & x_{1n} \\ x_{21} & x_{22} & \dots & x_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ x_{m1} & x_{m2} & \dots & x_{mn} \\ \end{bmatrix}
    其中每個元素爲m*n矩陣,X爲塊循環矩陣,共有m*n個樣本。
    接下來可以完全按照一維核矩陣的計算方式即式(1)進行計算,且將α\alpha和標籤y視爲一維列向量,只是核函數輸入爲兩個矩陣而不是兩個向量,其輸出仍爲一個固定值,得到的K爲mn*mn大小的矩陣(一維例子中樣本數爲n而二維爲mn),但這樣計算很麻煩且無法加速,因此將K中的每一列(mn個元素)轉爲一個m*n的矩陣,如下:
    Xj=[k(x11,xij)k(x12,xij)k(xmn,xij)] >[k(x11,xij)k(x12,xij)k(x1n,xij)k(x21,xij)k(x22,xij)k(x2n,xij)k(xm1,xij)k(xm2,xij)k(xmn,xij)] (1) X_j=\begin{bmatrix}\\ k(x_{11},x_{ij}) \\ k(x_{12},x_{ij}) \\ \vdots \\ k(x_{mn},x_{ij}) \\ \end{bmatrix} \ -> \begin{bmatrix}\\ k(x_{11},x_{ij}) & k(x_{12},x_{ij}) & \dots & k(x_{1n},x_{ij}) \\ k(x_{21},x_{ij}) & k(x_{22},x_{ij}) & \dots &k(x_{2n},x_{ij}) \\ \vdots & \vdots & \ddots & \vdots \\ k(x_{m1},x_{ij}) & k(x_{m2},x_{ij}) & \dots &k(x_{mn},x_{ij}) \\ \end{bmatrix} \ (1)
    這樣組成的mn個矩陣,按照X的結構重新組成新的K‘,同時,將α\alpha和標籤y也轉爲二維矩陣,則y爲K’和α\alpha的循環卷積,所有計算均可以按照一維的方式進行。
    此外需要注意的是,在訓練過程計算核矩陣時,由於兩個輸入都是同一個矩陣,即KCF在初始化時提供的目標框像素提取得到的特徵,其輸入順序並不重要,但其實核矩陣計算函數中的一個參數是要進行樣本擴充操作的(由於使用循環矩陣的特性計算,實際並不需要,但在轉化爲頻域計算時它要求共扼),而另一個輸入不需要,因此其輸入順序是有要求的,這在預測過程中需要注意(兩個輸入一個爲原樣本特徵,一個爲待預測樣本特徵)。
  • 3、將得到的K帶入計算,得到α\alpha(訓練過程),或結合訓練得到的α\alpha計算預測結果y矩陣(預測過程)
    儘管2的整個推導中一直提到擴充樣本,並利用擴充樣本矩陣進行訓練和預測,但實際代碼中從未出現擴充樣本的操作,而一直只使用唯一的生成矩陣進行計算,這是爲什麼呢?
    如果不使用循環矩陣的特性加速計算,正常是需要先得到擴充的樣本矩陣的,並按照一般流程進行大量的訓練計算和預測計算。但是因爲擴充樣本矩陣和得到的核矩陣均爲循環矩陣,而根據循環矩陣的特性,在固定的某一些計算中,只需要將生成向量或生成矩陣進行DFT參與計算後再IDFT,即可得到與完整的循環矩陣參與計算同樣的結果,大大加速了計算。從另一個角度理解,其實就是因爲完整的循環矩陣都可以由生成向量或者矩陣表示,而計算時採用時頻領域的一些特性即可。

3、Tracking by detection

Tracking by detection的核心在於目標匹配算法,即能夠將前後兩幀中的同一目標匹配上,而原KCF算法中,其預測部分實際上就是使用訓練得到的模型,計算待檢測樣本與原樣本之間的關聯度,並預測目標所在待測框中的真實位置(response矩陣中最大值所在位置),由於Tracking by detection中每一幀的檢測都可以認爲是已知目標在圖像中的真實位置,雖然存在誤差,但該誤差爲絕對誤差而非累計誤差,因此只需要用到KCF計算不同目標關聯度的功能。當然也有使用KCF與檢測同時進行,並對於檢測中識別的目標與KCF追蹤到的目標匹配上時,將兩者得到的同一目標位置進行卡爾曼濾波的做法,這裏不予討論。將KCF應用於計算Tracking by detection單次流程如下:

Created with Raphaël 2.2.0開始檢測器檢測目標所有已有KCF追蹤器對所有目標計算關聯度,得到關聯矩陣關聯度大於閾值且使用Hungrian算法能分配到已有軌跡?將新檢測到目標加入對應軌跡中並使用新樣本更新追蹤器結束使用新樣本訓練一個追蹤器並加入已有追蹤器池中yesno

上述使用KCF追蹤器計算關聯度即提取目標樣本特徵,使用該特徵與追蹤器原有樣本特徵計算核矩陣K,使用K結合追蹤器已有的α\alpha計算response矩陣,取response矩陣中最大值作爲目標樣本與原樣本關聯度值。

4、與直接使用KCF的區別

上文已經提到過,直接使用KCF需要手動初始化一個檢測框作爲原樣本訓練,下一幀計算中仍以該檢測框位置進行循環樣本擴充,利用已訓練模型在循環樣本中找一個與原樣本關聯度最大的樣本作爲新樣本輸出,同時以該樣本位置更新檢測框,並再訓練模型,如此循環重複,知道找不到目標(最大關聯度小於一個閾值)。
在Tracking by detection中,KCF的位置更新和初始化都由detection完成,其內部不做位置更新,detection提供一個目標位置初始化一個KCF追蹤器,下一幀中detection給出N個可能樣本讓追蹤器判斷關聯性,樣本k如果得到最大關聯度,則用該樣本更新追蹤器,並用於之後的計算,如此重複。

5、將KCF原有功能用於補充detection漏檢目標

仔細觀察3中流程可以發現,在已有追蹤器池中存在一些未匹配到新目標的追蹤器,即上一幀檢測到了某些目標並與已有追蹤器關聯,但下一幀由於檢測器漏檢,這部分追蹤器沒有關聯到任何目標,這個時候可以使用KCF原有的流程對這些追蹤器進行更新,並預測一個目標位置填充到最終檢測結果,用於補充漏檢目標,以上流程可以更新爲:

Created with Raphaël 2.2.0開始檢測器檢測目標所有已有KCF追蹤器對所有目標計算關聯度,得到關聯矩陣關聯度大於閾值且使用Hungrian算法能分配到已有軌跡?將新檢測到目標加入對應軌跡中並使用新樣本更新追蹤器未關聯任何目標的追蹤器使用KCF原有流程更新目標位置,並將結果加入檢測結果結束使用新樣本訓練一個追蹤器並加入已有追蹤器池中yesno

6、總結

目前使用以上流程得到的追蹤器效果還是不錯的,KCF使用循環矩陣大大加速了計算,實測正常道路上以上追蹤流程用時不超過10ms,基本可以滿足需要,有空再放一個demo上來。

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