目標檢測之訓練opencv自帶的分類器(opencv_haartraining 或 opencv_traincascade)
最權威的說明,參考官方使用手冊:
http://www.OpenCV.org.cn/opencvdoc/2.3.2/html/doc/user_guide/ug_traincascade.html
自帶的分類器是adaboost分類器演算法思想是通過迭代訓練弱分類器得到一個強分類器。每次迭代得到區域性最優的分類器,然後將區域性最優的分類器權值相加最後得到一個可用的強分類器。
演算法虛擬碼如下:
(1)初始化訓練資料的權值分佈,讓其服從均勻分佈。
(2)學習具有權值分佈的訓練資料集Dm (m= 1…M),得到基本的分類器 。計算 在訓練資料集上的分類誤差率。
也就是分類錯誤樣本的個數。(因為開始服從均勻分佈)。
(3)計算 的係數,也就是弱分類器的權值。 可以看出分類錯誤樣本的個數越多弱分類器的權值就越小,說明分類器的分類能力越差。
(4)更新訓練資料集的權值分佈。
由上述公式可以看出,可以增大分類錯誤樣本的權值,突出分類錯誤的樣本再進行分類。
(5)弱分類器的權值加權得到最終的分類器。
簡單的原理如上文所述,詳細原理可以檢視李航版的《統計機器學習方法》。下面詳細介紹如何才能訓練一個合適的opencv分類器。
整個訓練過程分為以下幾步:
建立樣本
樣本分為正、負兩類。其中正樣本就是我們要檢測目標樣本。因為我要檢測車輪所以,我的正樣本就是車輪。負樣本就是其他任意的圖片,經個人實驗發現負樣本跟正樣本相關訓練出的分類器分類效果比較好。(諸如,我的正樣本是車輪,負樣本是街道,道路,車身等)。
所有正樣本統一大小40*40放在相應的資料夾下。
負樣本的數量大於正樣本數量放在相應的資料夾下。
正樣本應該進行分割,使只包含有目標物。
一、所有的正樣本放在pos資料夾下,負樣本放在neg檔案加下。
檔案中的所有圖片,生成統一大小(40*40)儲存到檔案中:程式碼地址:Here。
圖片生成info.txt檔案的程式碼,地址:Here。
二、分別為正負樣本建立描述檔案。
A. 為正樣本建立描述檔案格式檔案info.txt,並且把這個檔案放在與樣本圖片同一目錄下,例如我的目錄為: E:\Adesk\Cpp-Primer\harr-like\pos\pos.txt
(檔名改為:pos.txt
B. 為負樣本建立集合檔案格式檔案neg.txt, 並且把這個檔案放在與樣本圖片同一目錄下,例如我的目錄為: E:\Adesk\Cpp-Primer\harr-like\neg\neg.txt。
三、建立正樣本。
Opencv2.4.8自帶的分類器在D:\opencv\build\x86\vc10\bin目錄下。
輸入opencv_createsamples.exe回車就可以得到訓練需要的引數列表。按照輸入即可,我建立600個正樣本。如下:
-info E:\Adesk\Cpp-Primer\harr-like\pos\pos.txt -vec E:\Adesk\Cpp-Primer\harr-like\pos\pos.vec -num 2000 -w 40 -h 40
正樣本建立完畢。開始訓練分類器。
四 訓練opencv自帶的分類器。
輸入opencv_haartraining.exe(回車)同樣可以得到訓練需要的引數列表。
本人輸入以下引數列表開始訓練。
-data E:\Adesk\Cpp-Primer\harr-like\dt -vec E:\Adesk\Cpp-Primer\harr-like\pos\pos.vec -bg E:\Adesk\Cpp-Primer\harr-like\neg\neg.txt -npos 1500
-nneg 4500 -nstages 2 -nsplits 5 -mem 4096 -nonsym -w 40 -h 40
經驗證正負樣本數目在1:3的時候訓練效果比較好。當然訓練層數越多越好,我這兒只是訓練了16層。如果訓練過程中出現卡在某一層。有以下原因和解決方案。
是負樣本有問題,解決方案(成功通過):
1。卡在某一層後,按ctrl+c結束
2。更新你的負樣本
3。不要刪除已經訓練出的cascade
4。繼續訓練,請注意是否要改動-nneg引數
-mem 是訓練時要求所佔記憶體的電腦記憶體是4G所以我這兒寫的是2048.具體看自己實現。
訓練完畢後會在資料夾下面發現一個dt.xml檔案說明你訓練成功。可以進入測試環節了。
當然opencv自帶的分類器作為入門的檢測器有很多缺點,檢測不是很準確,訓練過程耗時太長等等。因此下面將介紹一個更好的檢測器給大家。
在這兩天的實驗過程中發現的問題及解決方法
問題1:若生成正樣本是5000個時,訓練正樣本時全部都用完的話,會出現沒法提取正樣本的錯誤。
解決方法每次訓練樣本時都要比生成的正樣本少200~300個例如我實驗的時候就用4700個正樣本。
問題2,若在一個地方停止2,3個小時沒動靜
估計是負樣本不足造成的。利用ctrl+c指令中斷重新進行訓練增加負樣本的數目及多樣性。可以生成解析度不同的分類器這樣子分類器就會具有尺度不變性。
測試:
也可以用opencv的cvHaarDetectObjects函式進行檢測:
CvSeq* faces = cvHaarDetectObjects( img, cascade, storage,1.1, 2, CV_HAAR_DO_CANNY_PRUNING,cvSize(40, 40) );
訓練:
// opencv_haartraining
-data E:\Adesk\Cpp-Primer\harr-like\dt1 -vec E:\Adesk\Cpp-Primer\harr-like\pos\pos.vec -bg E:\Adesk\Cpp-Primer\harr-like\neg\neg.txt -npos 3000 -nneg 9000 -nstages 10 -nsplits 2 -mem 6144 -nonsym -w 40 -h 40
// opencv_traincascade
-data E:\Adesk\Cpp-Primer\harr-like\dt -vec E:\Adesk\Cpp-Primer\harr-like\pos\pos.vec -bg E:\Adesk\Cpp-Primer\harr-like\neg\neg.txt -numPos 5000 -numNeg 9000 -numStages 8 -minHitRate 0.999 -precalcValbufSize 2048 -precalcdxBufSize 2048 -w 40 -h 40
opencv_traincascade測試:
CascadeClassifier *face_cascade;
vector<Rect> faces;
face_cascade->detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
測試程式碼:地址:Here。
如果幫到你了,請讚賞支援: