這幾個月一直在忙着做大論文,一個基於 SVM 的新的目標檢測算法。為了做性能對比,我必須訓練一個經典的 Dalal05 提出的行人檢測器,我原以為這個任務很簡單,但是我錯了。
為了訓練出一個性能達標的行人檢測器,我花了半個月的時間,中間遇到各種 BUG 我就不提了,下面只說正確的步驟。(基於 MATLAB 環境,但是沒有代碼,請您自己寫~)
步驟
1. 訓練數據集及其它准備工作
訓練檢測器的正例(Positive examples)數據庫最好采用“全圖+標注”的形式,不要是那種切出來的行人小圖片,這有助於后續的 bootstrap 操作(當然,在 Daimler 這樣的數據庫上似乎無法做到),初始的負例(Negative examples)采用一組不包含行人的場景圖片。其實負例的選擇並不重要,因為在 bootstrap 環節,真正影響性能的,靠近分類超平面的數據點會被自動找到。
大多數靠譜的數據庫都有自帶的標注讀取工具庫,或者遵循某種標注格式(例如 PASCAL),你也可以使用進一步封裝的標注讀取工具,例如 Dollar 的 toolbox。
為了計算 HOG 特征,你可以采用 VLFeat 的 HOG 計算函數,這個 HOG 是我見過的檢測性能最好的之一(比 OpenCV 的 HOG 好很多,性能提高超過 5%)。
2. 訓練
訓練必須進行兩輪:初始訓練,以及 bootstrap 訓練。下面的所說的“切圖”操作,就是從某個位置切一個 128 * 64 的子圖片的意思,當然,你也可以采用其他的切圖尺寸。下面,談一個很重要的問題,就是標注(ground truth)尺寸的歸一化,以及標注的外邊距(padding)對訓練結果的影響。
由於數據庫中的行人標注,並不是依照某種固定的長寬比,而 Dalal 檢測器的輸出是固定長寬比的,所以,在切圖之前,必須將標注框(bounding box)的尺寸調整到統一比例。你也許會試圖不調整標注框,而是按照原始標注框切出圖片,然后再將圖片縮放到 128 * 64,但是這樣是不對的!檢測結果會打折扣。
此外,Dalal 論文里還指出,如果將行人周圍的一圈背景也包含到訓練子圖片里,那么檢測器效果又會提升幾個百分點,並且論文指出上下左右個加 16 像素的外邊距(padding)效果最好,我做了一下實驗,確實如此。
調整標注框可以采用 Dollar 工具箱里的 bbApply 函數。下面是我采用的標注框預處理策略:
- 計算不包含 padding 時的行人長寬比 r,即(128 - 32):(64 - 32)
- 使用 bbApply 將標注框的長寬比調整到 r
- 再使用 bbApply 將標注框的高度和寬度分別放大 128 / (128 - 32),以及 64 / (64 - 32) 倍。
經過上述步驟,所有標注框的比例都一致了,並且包含了 padding。
2.1 初始訓練
正例直接從訓練集中切出來,負例隨機從場景圖片中切取,假設我需要 9000 個負例,數據集中有 1000 個場景圖片,那么平均每幅圖片隨機切九個即可。切負例時沒必要考慮尺度,因為初始負例對整體訓練而言沒有顯著影響,所以隨便切即可,任性。
對切出來的數據提取特征,然后丟到 liblinear 里訓練一個 SVM,參數:
-B 1 -c 0.01
其中-B 1是為了讓 SVM 具有 bias term(就是 wx+b 中的那個 b),-c 0.01 是 Dalal 論文里的 C 參數(你可以試着調一下,不過我試了一下,的確 0.01 最好)。
於是,我們得到了一個初始的檢測器。SVM 的支撐矢量個數大概在 1000 ~ 3000 個不等。
2.2 Bootstrap 訓練
初始檢測器是一個非常非常差的檢測器,所以千萬不要試圖一次訓練后就直接拿來用。我們需要新一輪 bootstrap 訓練。
所謂 Bootstrap 訓練,就是用初始檢測器在訓練數據集中進行檢測,搜集所有的誤檢,將它們作為額外的新的負例加入先前的負例集合,然后再次訓練一個 SVM。所謂誤檢,就是一個與所有標注位置重合都小於 50% 的檢測結果,這個“重合”可以用 area(B1 & B2) / area(B1 | B2) 來計算,其中 B1 和 B2 都是矩形框,“與”運算符是矩形框的交疊,“或”運算符是兩個矩形框覆蓋的區域相加。
一般來說,初始檢測器在訓練集上能找到大量誤檢,例如,我在 INRIA 上訓練時就有 2 萬個誤檢,這是正常的(所以你一定要把電腦的虛擬內存調大,否則 MATLAB 會掛),bootstrap 訓練后,得到的新的 SVM 的支撐矢量個數將達到 6000 個以上,這從一個側面說明了,該輪訓練找到的負例重新約束了分類超平面的位置。
3. 檢測
前面我提到,訓練時需要將標注框擴大,但是,擴大的標注框,將使檢測結果也被擴大,這時,你需要按照與擴大框的步驟相反的方式,將檢測結果框縮小。而且,為了使圖片邊緣的行人不被漏掉,你可以將輸入圖片的四周都加上 padding 后再進行檢測。
4. 性能
按照這種策略訓練出來的檢測器,在 INRIA 上達到了 Precision:50%,Recall:71% 的性能,超過了 OpenCV 自帶的 HOG Detector(其實沒有可比性,因為我用了更好的 HOG 特征),如果您有更好的方案,請告訴我,謝謝。
