「圖像識別」訓練貓臉偵測器

OpenCV 使用的 Object detection 技術稱為 Cascade Classifier for Object Detection ,是一種屬於 boosted cascade of weak classifiers 的方法,也就是將數個弱分類器串聯起來再得出最佳的分類結果。其實最早整合到 OpenCV 並支持的分類特徵是哈爾特徵(Haar-like features),後來加入了 LBP ( Local Binary Pattern)以及 HOG( Histogram Of Gradient),不過可惜的是 HOG 在 3.x 後由於某些技術問題被取消了。

Boosting 的中心思想在於「三個臭皮匠勝過一個諸葛亮」,主要是將大量的弱分類器(分類效果僅比隨機好一點)逐步訓練成一個較強的分類器,透過對每個弱分類器分類錯誤的部份持續投入學習,最後形成一個超強的分類器。

舉例來說,我們熟知的 Spam mails 檢測,就是一種 Boosting 的概念,拆開,每一條 spam check rule 都是弱分類器,僅對一小部份的垃圾郵件有效,但是把數以百計的 rules 串連起來,便能打造一個滴水不漏的垃圾郵件防堵系統!

在機器學習中,有很多分類器便應用了 Boosting 的方法,例如 AdaBoost(Adaptive Boosting)、Gradient Tree Boosting、XGBoost 等, 而 OpenCV 內建的 Cascade Classifier for Object Detection,正是應用了AdaBoost。

新版 OpenCV 對於 Cascade Classifier 的支持

可惜的是,OpenCV 4.x 版後不再支持 Cascade Classifier 的訓練,因此目前在 4.x 版的 OpenCV 代碼中,無法看見諸如 opencv_createsamples、opencv_traincascade 等程序,官方的說法是近幾年流行的 ML、DL 效果更佳,鑑於使用者逐漸減少,決定不再包入相關的訓練程序在源碼中。

不過事實上目前還是有相當多的使用者對於 cascade classifier 有強烈的需求,因為它使用方便、偵測速度快,常讓人包容誤報率高和訓練複雜的缺點,因此有傳聞官方可能會在下一版本的 OpenCV 中再度支持。

訓練貓臉偵測器

特意編寫了一套工具程序可快速方便地進行 Cascade Classifier 的訓練,以下以貓臉偵測示範如何使用這個工具製作自己的 Cascade Classifier。

蒐集照片和標記

1. 先從網絡上下載一些貓的照片,本例中下載了 126 張。

「圖像識別」訓練貓臉偵測器

2. 使用 labelImg 進行標記:由於貓臉區域不像人臉那麼明確,因此在框選時選擇從兩眼外側(不包含耳朵)開始直到下巴的區域。

「圖像識別」訓練貓臉偵測器

準備 dataset

此步驟將產生訓練時需要的positives(正向圖片,即標記的貓臉)以及 negatives(負向圖片,即沒有貓臉的圖片)。

1. 所有相片及標記好的 label 分別置於 images 及 labels 的文件夾中。

2. 執行 1_labels_to_pos_neg_imgs.py:此程序的目的是將所有相片中的標記框取出,另外存到一個folder 下,這些圖片稱為 positives,圖片中不含標記框的其它區域則存到 neg_bg 資料夾中,這些與貓臉無關的圖片稱為 negatives。1_labels_to_pos_neg_imgs.py 的參數如下,您只要修改參數的內容即可:

<code>#標記檔的pathxmlFolder = “H:\\\\working\\\\cascade_cat_face\\\\voc_dataset\\\\labels”#圖片檔的pathimgFolder = “H:\\\\working\\\\cascade_cat_face\\\\voc_dataset\\\\images”#要取出的標記名稱(class name)labelName = “catface”#項目目錄,所有產生的檔案或目錄皆會存於此projFolder = “H:\\\\working\\\\cascade_cat_face\\\\cascade_training”#訓練的圖片大小(建議不要太大)outputSize = (54, 45)#產生的訓練圖片類型imageKeepType = “jpg”#去除標記區域的圖片,是否要作為negative圖片?generateNegativeSource = True/<code>

執行成功後,會產生以下兩個目錄:positives(正向圖片),含有貓臉標記的圖片;neg_bg(負向圖片),不含貓臉標記的圖片(我把有貓臉的區域以黑色色塊取代,就能作為負面圖片來使用)。

「圖像識別」訓練貓臉偵測器

positives


「圖像識別」訓練貓臉偵測器

negatives

3. 執行 2_generate-negatives.py:本程序使用 sliding window 的方式,將 neg_bg 文件夾下的相片切裁為指定大小的 negatives 圖片,併產生一個 negatives.info 文件。

<code>#項目目錄,所有產生的檔案或目錄皆會存於此projFolder = “H:\\\\working\\\\cascade_cat_face\\\\cascade_training”#sliding window移動距離movePixels = 80#sliding window時圖片依次的縮小比例resizeScale = 0.5#裁切出的圖片大小negSize = (54, 45)#載切後儲存的圖片格式imageKeepType = “jpg”#neg_bg folder下的圖片要不要先縮小為指定尺寸? 0–> keep the sameresize_org_w = 0#要產生多少負向的圖片?imagesCount = 8000/<code> 

negatives 資料夾內容:

「圖像識別」訓練貓臉偵測器

negatives.info文件內容:

H:\\working\\cascade_cat_face\\cascade_training\\negatives\\1580366317.81161742.jpg

H:\\working\\cascade_cat_face\\cascade_training\\negatives\\1580366317.81961253.jpg

H:\\working\\cascade_cat_face\\cascade_training\\negatives\\1580366317.83462724.jpg

H:\\working\\cascade_cat_face\\cascade_training\\negatives\\1580366317.84162245.jpg

H:\\working\\cascade_cat_face\\cascade_training\\negatives\\1580366317.8586116.jpg

H:\\working\\cascade_cat_face\\cascade_training\\negatives\\1580366317.86569797.jpg

4. 執行 3_augmentation.py:本程序使用 augmentation 強化資料的方式產生更多正向圖片,新增加的圖片將放置於 aug_positives 文件夾下。

<code>#項目目錄,所有產生的文檔或目錄皆會存於此projFolder = “H:\\\\working\\\\cascade_cat_face\\\\cascade_training”#產生的正向圖片大小outputSize = (54, 45)#產生的圖片格式imageKeepType = “jpg”#每一個正向圖片要產生出幾張新圖片?numAugment = 3#Augmentation的設定aug_whitening = Falseaug_rotation = 16aug_w_shift = 0.1aug_h_shift = 0.1aug_shear = 0.1aug_zoom = 0.05aug_h_flip = Trueaug_v_flip = Falseaug_fillmode = “nearest”/<code>

產生的圖片如下,原本僅有 243 張,但通過 augmentation 增加了 929 張。

「圖像識別」訓練貓臉偵測器

5. 執行 4_add_aug_positives_to_list.py:將前一步所產生的圖片放到 positives.info 文件,其內容截錄如下。

positives/aug__0_4419.jpg 1 0 0 54 45

positives/aug__0_584.jpg 1 0 0 54 45

positives/aug__0_5614.jpg 1 0 0 54 45

positives/aug__0_402.jpg 1 0 0 54 45

positives/aug__0_7285.jpg 1 0 0 54 45

positives/aug__0_710.jpg 1 0 0 54 45

positives/aug__0_4390.jpg 1 0 0 54 45

最終待訓練用的文件夾及其下文件如下:

「圖像識別」訓練貓臉偵測器

產生訓練用的 VEC 檔

由於 Cascade Classifier 不能直接讀取圖片,我們必須轉為 VEC 才能開始訓練。

1. 進入項目目錄:H:\\working\\cascade_cat_face\\cascade_training

cd H:\\working\\cascade_cat_face\\cascade_training

2. 執行 opencv_createsamples.exe

H:\\opencv\\build\\\\x64\\vc15\\bin\\opencv_createsamples.exe -info positives.info -vec samples.vec -w 54 -h 45 -num 1790

若出現如下方的 error message,表示某個圖文件有問題,建議直接從 positives.info 列表中刪除該圖,例如下方第 229 行的圖文件有問題,直接刪除該行。

「圖像識別」訓練貓臉偵測器

再執行一次 opencv_createsamples.exe 便可成功轉換,最後是如下畫面:

「圖像識別」訓練貓臉偵測器

開始訓練

1. 進入項目目錄:H:\\working\\cascade_cat_face\\cascade_training

cd H:\\working\\cascade_cat_face\\cascade_training

2. 執行下方的指令:

H:\\opencv\\build\\\\x64\\vc15\\bin\\opencv_traincascade.exe -data H:\\working\\cascade_cat_face\\cascade_training -vec samples.vec -bg negatives.info -numPos 1700 -numNeg 7000 -numStages 8 -minHitRate 0.995 -maxFalseAlarmRate 0.3 -w 54 -h 45 -featureType LBP

「圖像識別」訓練貓臉偵測器

3. 執行重點

(1)訓練 stange 的數目由 -numStages 指定。

(2)HR(Hit Rate,偵測到物件)、FA(False Alarm,錯誤偵測到物件,即誤判)此兩個值分別由 -minHitRate 和 -maxFalseAlarmRate 指定,訓練結果滿足這兩個值表示該 Stage 結束。

(3)-featureType可指定為HAAR 或 LBP,目前比較流行的是 LBP,訓練速度較快且偵測效果不亞於 HAAR。

「圖像識別」訓練貓臉偵測器


「圖像識別」訓練貓臉偵測器

「圖像識別」訓練貓臉偵測器

上圖中可看出訓練時間相當長,但如果將 -featureType 改為 HAAR,則訓練時間會比 LBP 要多出好幾倍!

訓練結果(LBP)

這次測試總共標記了 126 張相片(約有 241 張貓臉正樣本),另外通過資料強化擴增到 1,794 張,再搭配 7,059 張負樣本進行了 OpenCV Cascade Classifier 的 LBP 訓練,最後訓練了 7 個階段,總訓練時間為 5 小時 36 分 41 秒。

另外找了 11 張相片作為 test 圖片,使用訓練完成所產生的 cascade xml 測試其效果如下,若能繼續增加更多的貓臉正樣本,應該可提高識別的效果。

效果還不錯

「圖像識別」訓練貓臉偵測器


「圖像識別」訓練貓臉偵測器


「圖像識別」訓練貓臉偵測器

只偵測出部分


「圖像識別」訓練貓臉偵測器


「圖像識別」訓練貓臉偵測器

Bounding box 大小位置有待加強


「圖像識別」訓練貓臉偵測器


「圖像識別」訓練貓臉偵測器

False Alarm

「圖像識別」訓練貓臉偵測器


分享到:


相關文章: