標籤:
因為工作的原因,本人需要用到分類器來檢測目標,所以需要訓練自己的分類器
在這裡我就簡單的說下步驟和注意事項。
HaarTraining步驟1.正負樣本處理
正樣本處理需要對正樣本進行歸一化處理,一般情況下可以用Photoshop對映像進行尺寸統一處理,比如都是20*20或者24*24,其中其它尺寸比如240*15也可以做成樣本的,不要求是正方形,或者20*20,24*24,。這是取決於你的目標的形狀,不過正樣本的解析度不要太高,太高的話在訓練時會記憶體配置不足引起crash
錯誤如下: OpenCV Error :insufficient memory <failed to allocate 250343435bytes> in cv::\OutOfMemoryError
圖1.1 正樣本解析度太大時引起的記憶體配置不足的crash
不預先用Photoshop對正樣本進行處理時,還可以使用opencv_createSamples工具進行處理,其實就算用Photoshop對樣本進行過處理,在這裡還是會對樣本進行一次處理,Photoshop預先處理的好處就是樣本的位置都為0,0。那麼對正樣本描述檔案處理時就比較簡單,特別是正樣本數量足夠大時,可以減少正樣本描述檔案的出錯率,提高分類器的檢測率。
1.1正樣本描述檔案
正樣本描述檔案的建立如下:
一個.txt檔案或者.dat檔案裡麵包含正樣本的資訊,
結構:
包含正樣本圖片的相對路徑或者全路徑 正樣本中包含的正樣本數量 第一個正樣本的位置x y 第一個正樣本的寬和高w h 第二個正樣本的位置x y 第二個正樣本的寬和高w h …… 第n個正樣本的位置x y 第n個正樣本的寬和高w h
img01.jpg 1 0 0 20 20
img\\img02.jpg 1 0 0 24 24
e://img/img03.jpg 2 3 4 240 15 248 29 160 20
….
在這裡你就會明白為什麼要在之前用Photoshop對圖片進行處理,這樣的話,所有圖片都是只包含一個正樣本的統一尺寸的圖片,那麼正樣本描述檔案就像下面那樣:
img01.jpg 1 0 0 20 20
img02.jpg 1 0 0 20 20
img03.jpg 1 0 0 20 20
……
既然是是統一的話,就可以用批處理來完成:
在Windows下用命令: dir imgDir /b > imgDiscr.txt
(在linux下用: ls imgDir >imgDiscr.txt ,也可以儲存為.sh檔案,這樣不用每次輸入命令)
我是直接儲存為.bat檔案,這樣每次不用打命令,而是點擊就產生包含所有正樣本圖片名的檔案imgDiscr.txt :
img01.jpg
img02.jpg
img03.jpg
….
然後用編輯器開啟,把jpg替換成jpg 1 0 0 20 20
就可以快速產生正樣本描述檔案。
1.2負樣本描述檔案的產生
和正樣本一樣,不過不需要對負樣本圖片進行處理,只要負樣本圖片不比正樣本圖片的解析度小就行,負樣本描述檔案只需要包含圖片路徑名:
non-img01.jpg
non-img02.jpg
non-img03.jpg
….
2.opencv_createsamples產生正樣本.vec檔案
分類器在訓練時並不會直接處理正樣本描述檔案,而是包含正樣本的.vec檔案,這是一個用matlab函數產生的向量檔案。
參數的設定如下:
opencv_createsamples.exe -info imgDiscr.txt -vec samples.vec -num 68 -w 20-h 20
命令列參數:
- [-vec <vec_file_name>] 輸出檔案,內含用於訓練的正樣本
- [-img <image_file_name>] 輸入影像檔名(例如一個公司的標誌
- [-bg <background_file_name>] 背景映像的描述檔案,檔案中包含一系列的影像檔名,這些映像將被隨機選作物體的背景。
- [-mun <number_of_samples>]產生的正樣本的數目。
- [-maxxangle <max_x_rotation_angle>]X軸最大旋轉角度,必須以弧度為單位。
- [-maxyangle <max_y_rotation_angle>]Y軸最大旋轉角度,必須以弧度為單位。
- [-maxzangle <max_z_rotation_angle>]Z軸最大旋轉角度,必須以弧度為單位。
- [-w <sample_width >] 輸出樣本的寬度(以像素為單位)
- [-h <sample_height >]輸出樣本的高度(以像素為單位)。
其中-num的數值應該為總的正樣本數,也就是正樣本描述檔案中第二列數字總和
-w -h是輸出映像的寬和高,這裡也會對正樣本進行歸一化處理,其中我們之前用Photoshop對映像進行過歸一化處理,如果沒有,那麼在這裡createsample工具也會對正樣本進行歸一化處理,所有的正樣本大小都是一樣的。而且,之前Photoshop歸一化為20個像素後,在這裡設定為24個像素,那麼產生的.vec向量檔案裡面的映像是24個像素的。
3.haarTraining訓練分類器
opencv_haarTraining訓練器是一個被淘汰的訓練器,在2.4.9裡面還有,2.4.10後就沒有了,不過用opencv_traincascade訓練出來的分類器在樣本程式中無法使用,而且3.10的opencv_traincascade在使用時出現問題,所以迫不得已找回了以前的haarTraining來使用。其中opencv_traincascade出現的錯誤如下:
Train dataset for temp stage can not be filled. Branch training terminated
stackoverflow上的說是描述檔案是在Windows下產生的,結尾是/r/n,而linux下的描述檔案後面是/r沒有/n,所有導致讀取不到影像檔,但是在linux下訓練時還是會出現問題,所以,我覺得問題不在描述檔案上。訓練分類器用以下命令:
opencv_haartraining.exe -data block_xml/ -vec samples.vec -bg non-imgDiscr.txt -nstages 20 -nsplits 2 -minhitrate 0.999 -maxfalsealarm 0.5 -npos 200 -nneg 20 -w 240 -h 15 -mem 1024 -eqw 1 -mode ALL -bt GAB -minpos 32
這裡的正樣本數量為200,負樣本數量為20,樣本的寬為240,高為15
正樣本最小命中率為0.999,因為級聯-nstages為20,所以0.999^20 = 0.98 負樣本的最大錯誤率為0.5 經過20個級聯後錯誤率為0.5^20 = 0.0000009536
基本參數:
" -data <dir_name>\n" " -vec <vec_file_name>\n" " -bg <background_file_name>\n" " [-npos <number_of_positive_samples = %d>]\n" " [-nneg <number_of_negative_samples = %d>]\n" " [-nstages <number_of_stages = %d>]\n" " [-nsplits <number_of_splits = %d>]\n" " [-mem <memory_in_MB = %d>]\n" " [-sym (default)] [-nonsym]\n" " [-minhitrate <min_hit_rate = %f>]\n" " [-maxfalsealarm <max_false_alarm_rate = %f>]\n" " [-weighttrimming <weight_trimming = %f>]\n" " [-eqw]\n" " [-mode <BASIC (default) | CORE | ALL>]\n" " [-w <sample_width = %d>]\n" " [-h <sample_height = %d>]\n" " [-bt <DAB | RAB | LB | GAB (default)>]\n" " [-err <misclass (default) | gini | entropy>]\n" " [-maxtreesplits <max_number_of_splits_in_tree_cascade = %d>]\n" " [-minpos <min_number_of_positive_samples_per_cluster = %d>]\n",
要注意的是 –nneg 的參數 = 實際的負樣本數 * maxfalsealarm
因為第一次訓練完成後,第二個級聯的負樣本數其實並沒有百分百留下,其中有誤判的負樣本沒有載入,所以-nneg如果為實際的負樣本數,那麼程式很有可能進入死迴圈,如果樣本數不大,但是幾個小時後還沒有動靜,那麼就是進入死迴圈了,像上面的200個正樣本,20個負樣本基本上前10個級聯是一分鐘內完成,後面的級聯幾分鐘一個,如果超過十分鐘沒有動靜,那麼就是進入死迴圈了。在這裡,參數設定不正確,那麼就會訓練不成功,還有一個進入死迴圈的可能就是虛警率一直不能下來,就是maxfalsealarm的值一直居高不下,所以訓練器一直在跑,導致結果一直不能停,如果訓練一段時間,還在訓練,參數沒有問題的話,那麼就應該適當的設定級聯的數量,來停止訓練,得到分類器。
用opencv_traincascade來訓練的話可以結合TBB來多核處理,在
編譯opencv時加入TBB。
用opencv_haarTraining訓練出來的分類器會儲存在目前的目錄下用-data的參數命名的xml檔案裡。
訓練的過程可以隨時停止,重新訓練時,訓練器會讀取之前的參數,從停止的地方開始。
訓練結束:
opencv_haar分類器的訓練