使用Adaboost訓練檢測器

        做了一段時間的adaboost訓練一個可以檢測張開的手掌的檢測器,最後訓練出來的效果不錯,在保證較高的檢測率的情況下還能保持幾乎沒有誤檢的情況出現,adaboost用在物體檢測上的效果讓我大吃一驚。adaboost的特點是誤檢測少,且速度快,因爲在檢測的時候採用滑窗法對窗口挨個進行一個二分類(是手掌或者不是手掌),但是大多數窗口無法通過前面幾個stage的分類器就直接被判斷爲負樣本了,因此有着速度快的特點,但是限於檢測過程是在手機端運行的,手機的計算能力不比電腦,所以fps還是會存在一點問題,對此我也進行了相應的方法來加速檢測的過程,以提高檢測速度。這篇博客分爲兩個部分,一部分是如何準備數據集,包括正樣本和負樣本,另一個部分是如何進行訓練以及訓練過程中一些需要注意的地方。下面開始啦~

        一、準備數據集

        數據集包括了正樣本和負樣本,正樣本毫無疑問就是真正包括想要檢測的物體。舉個栗子:

         截圖工具大概就是QQ截圖之類的東西了。。圖像的大小可以不一樣,也可以都縮放爲一個尺寸,最好是縮放爲一個尺寸,方便後面準備info.data文件,但原則上是隻要保證正樣本圖像中基本恰好包括了想檢測的物體即可。把它們放在一個叫做pos的文件夾中。我用到的正樣本個數是1400個。正樣本這樣截好圖放在pos文件夾之後就告一段落了,接下來是負樣本。關於負樣本,有一點值得注意,就是負樣本不需要自己去截取,可以拿任何不包括正樣本圖像的大圖作爲負樣本,再舉個栗子,我想檢測的是手掌,那麼只要一張圖片中沒有手掌,我就可以把這張圖片拿來當做負樣本的一部分。也就是說,負樣本是大圖而不是截圖,只要這個大圖不包括正樣本。還是拿圖舉個栗子:

      

       這是拿視頻存成圖片來作爲負樣本的,圖片的個數是1180張,但是圖片的個數不代表負樣本的個數,這點後面會解釋到。把這些圖片放在一個叫做neg的文件夾中,pos和neg文件夾在同一個目錄下。還是上圖吧:

     

      現在有了數據集,還差描述這些正負樣本的文件。正樣本需要一個叫做info.dat(也可以是info.txt)的文件,這個文件表達了什麼含義呢?上個info.dat的圖:

           可以看到inf.dat描述了正樣本所在的目錄以及正樣本的文件名字,後面的1表示這個圖裏面有一個正樣本,它在圖中的位置是起點是左上角的座標是(0,0),然後寬高是24,24。這裏寬高之所以是24,24的原因是我把所有正樣本都縮放到了24,24的尺寸,所以正樣本圖片就是整個圖片。如何快速生成這個info.dat文件呢?在Ubuntu下可以使用在工作目錄下面(也就是pos和neg文件夾所在的文件夾)打開終端輸入以下指令:

     ls pos/*.jpg > info.dat

    這就可以把文件所在目錄和文件名的信息寫到info.dat文件中,然後再使用文本替換,把info.dat中的所有jpg替換爲jpg 1 0 0 24 24,就可以得到上圖info.dat文件形式了。這下就可以解釋爲什麼建議先把所有正樣本縮放到一個尺寸了,因爲方便最後統一替換。現在有了正樣本的描述文件了,還差負樣本的了,在同樣的工作目錄下打開終端輸入以下指令:

     ls neg/*.jpg > neg.txt

     這樣就可以生成負樣本描述文件neg.txt,如下圖所示:

          neg.txt描述了負樣本文件所在的目錄和名字。

     還差最後一步就可以完成數據集的準備了。需要opencv中的一個可執行文件,叫做opencv_createsamples,可以從opencv的bin目錄中拷貝到工作目錄下,然後打開終端輸入以下指令:

    ./opencv_createsamples  -info info.dat -vec pos.vec -num 1400 -w 24 -h 24
     1400這個數字是你有的正樣本的總數,後面訓練的時候還會涉及到比這個1400少一點的數,是一次訓練中真正使用到的正樣本的個數。-w -h的參數是程序會將你的正樣本縮放到指定的wh尺度,我這裏圖像本身就是24*24的,再縮放到24*24。執行這個指令後就可以得到一個pos.vec文件,它是一個二進制文件,包含了正樣本數據的像素值,具體含義參考另一篇博客。也就是說pos.vec是訓練的時候真正讀取的數據,包括了正樣本的長寬以及像素值的信息。下面進行第二步,訓練檢測器:

     二、訓練檢測器

      在準備好了數據集之後,就要開始訓練檢測器了,用到的工具是opencv提供的可執行文件opencv_traincascade,同樣可以將其拷貝到工作目錄下面來。然後在工作目錄打開終端,輸入指令./opencv_traincascade,就可以查看使用這個可執行文件需要什麼參數了。如下圖:

     

     下面主要來解釋這些參數的含義,以便我們可以正確的選擇參數。

     -data是訓練生成的檢測器存放的目錄,你可以自己在工作目錄下面建一個叫做cascade的目錄,然後訓練的時候就可以使用這個作爲參數填進去,-vec就是正樣本的vec文件,也就是前面說的pos.vec文件,-bg是負樣本描述文件,即neg.txt。[]中的是可以選擇填的參數,比較重要的有:

      -numPos:訓練的時候用到的正樣本的個數 ,這個個數要比你實際擁有的正樣本的個數少個100到200個,因爲每一個stage的分類器會將少量正樣本識別爲負樣本,因此需要新的正樣本補充進來,也就是那100到200個,如果你這裏填的-numPos參數是你實際擁有的也就是pos.vec文件中包含的正樣本個數,那麼當需要補充正樣本的時候你就沒有新的正樣本可以來補充了。我總共有1400個正樣本,所以這裏我可以填寫1200作爲訓練時候的正樣本數,留下200個正樣本做替補隊員。

      -numNeg:訓練的時候用到的負樣本個數,這個個數和你neg.txt中負樣本大圖片的個數沒什麼直接關係,舉個栗子我這裏填的是6000,那麼程序會從neg.txt中的大圖中按照某種規則摳出指定個數以及w和h的小圖作爲負樣本,也就是說一張負樣本大圖可以產生數十上百個負樣本小圖,這些小圖纔是真正在訓練的時候作爲負樣本出現的。一個經驗的填法是-numNeg是-numPos的5倍左右。比例太低導致虛警高,太高了導致檢測率低。正負比爲1:5挺合適的。

       -numStages:是你想生成多少個stage的分類器,並將它們級聯起來,經驗值是20,也就是默認值。太低了會導致虛警高。

        -featureType:是你可以選擇的特徵的種類,總共3種特徵可以選擇,harr,lbp以及hog。我訓練過手掌和人頭的檢測器,實踐表明,harr特徵往往在adaboost中有着更好的表現,因此這裏我填的是HARR,也就是默認值其實可以不填的。

         -w -h也就是你想扣出多大的圖作爲負樣本。一般正負樣本的尺度保持一致,我這裏使用的24 24。

         -bt:全名boost type,即boost的幾種方法,選擇默認的即可,也可以去查下這幾個分別是什麼意思,我查過然後忘記了。。

          -minHitRate以及-maxFalseAlarmRate。這裏的參數表示的是一個stage訓練到什麼程度就結束,然後開始訓練下一個stage呢?標準就是在這個stage的正負樣本中,檢測率不能小於-minHitRate,虛警率不能高於-maxFalseAlarmRate。比如這裏我們都採用默認值,-maxFalseAlarmRate爲0.995,-maxFalseAlarmRate爲0.5,表示的就是給出1000個正樣本,至少分類器要將其中的995個樣本判斷爲正樣本,如果給出1000個負樣本,最多隻能將500個判斷爲正樣本。

          -maxDepth:指的是在一個stage中會有多個弱分類器,而在opencv中這個弱分類器使用決策樹實現的,這個參數就表示決策樹的最大深度,填1的話表示決策樹就只有一個節點,也只有一層深。一般填1就可以了。

         -maxWeakCount:指的是在訓練一個stage的過程中,如果弱分類器(也就是決策樹)的 數量大於了這個--maxFalseAlarmRate參數的但-minHitRate以及-maxFalseAlarmRate還沒有達到指標的話,這個stage也會停止訓練,進行下一個stage的訓練。

         -mode:這是選擇了HARR特徵之後所獨有的一個參數,BASIC、CORE、ALL分別含有不同的特徵,但三者是包含關係,也就是ALL包含了CORE中的特徵,CORE包含了BASIC中的特徵。具體內容可以參考博客,也可以看下圖:

        

       BASIC就橫豎的特徵,即1中的ab以及2中的abcd,CORE在BASIC的基礎上還包括了傾斜的橫豎特徵,即1,2所有的特徵,ALL包括了1,2,3中所有的特徵。因此可以根據自己想要檢測的物體的情況選擇這個參數。

        參數的介紹就到這裏啦,想要了解更多細節的話可以去閱讀源碼,我的博客也解析過部分adaboost的源碼,但都還比較淺,深的還寫不出來。

        在工作目錄打開終端輸入以下指令即可開始訓練:

        ./opencv_traincascade -data cascade -vec pos.vec  -bg neg.txt  -numPos 1200 -numNeg 5000 -featureType HARR -w 24 -h 24
        訓練時間的話,到後面訓練一個stage會比前面的stage訓練時間要長,我訓練1000個正樣本和5000個負樣本在i7的筆記本上花了將近20個小時,所以看到訓練程序沒有反應的時候不要擔心,其實是在訓練的,如果程序因爲某些原因比如負樣本不夠而停止訓練的話,程序會自己輸出提示信息的。我也沒有遇到過卡住了不繼續訓練的情況。另外,如果程序在訓練過程中被人爲終止了,可以再次輸入上面的指令,會接着上次訓練的結果繼續訓練的。比如上次訓練了6個stage,那麼這次再訓練的話會從第7個stage開始的,只要不去改變cascade目錄下的文件就行了。最後,祝大家都能訓練出效果好的檢測器吧。再上倆圖:

        

                                                                    

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