本文為作者原創,未經允許不得轉載;原文由作者發表在博客園: http://www.cnblogs.com/panxiaochun/p/5345412.html
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文件里。
訓練的過程可以隨時停止,重新訓練時,訓練器會讀取之前的參數,從停止的地方開始。
訓練結束: