opencv利用Cascade Classifier訓練人臉檢測器

opencv默認提供了haar特徵和lbp特徵訓練的人臉分類器,可是效果不太好,因此咱們能夠用opencv提供的跑opencv_traincascade函數來訓練一個LBP特徵的分類器。(因爲opencv3中hog與hog文章定義的不一樣,所以在opencv3 的opencv_traincascade函數中被刪掉了詳情html

LBP特徵

按照官方文檔的訓練流程:python

1. 準備訓練數據

首先把正例和負例樣本按下面的結構存放:git

train
-pos
-- info.dat
-- img
---- 1.jpg
---- 2.jpg
---- ...

-neg
-- info.dat
-- img
---- 1.jpg
---- 2.jpg
---- ...

其中正例的info.dat格式以下:其中路徑爲必須爲相對路徑,1爲圖片中目標的個數,x,y爲bounding box左上角的座標;w,h爲bounding box的長和寬github

img/1.jpg 1 x y w h
img/2.jpg 1 x y w h
# img/3.jpg  2  100 200 50 50   50 30 25 25  # 若是同一圖片有多個目標

而負例的格式只是文件名,但*必須爲全路徑**(opencv坑1):bash

/path/to/img/1.jpg
/path/to/img/2.jpg

通常來講樣本須要覆蓋多種大小才能使模型比較魯棒,對於負例樣原本說,須要保證圖片尺寸比訓練時候的window size大,而從一張負例圖片中能夠截出許多個負例的window進行訓練,所以負例的圖片數量與正例差很少的時候能夠在訓練的時候設定比正例超過10倍的數目。ide

2. 利用opencv_createsamples生成訓練數據集

opencv_createsamples -vec face.vec \   # 輸出的數據集vec文件
                    -info /startdt_data/face_datasets/opencv_face_dataset/train/pos/info.dat \  # 正例的annotation文件,這裏須要用全路徑,避免報錯
                    -w 112 -h 112 -num 5000 \  # 正例的圖片大小和數量
                    -maxxangle 20 \                  # 數據加強:容許的最大的x方向的偏轉角
                    -maxyangle 20 \                  # 容許的最大的y方向的偏轉角

3. 利用opencv_traincascade訓練檢測器(以xml文件保存)

opencv_traincascade -data data \  # 模型xml文件保存的目錄
                    -vec face.vec \   # 數據集文件
                    -bg /startdt_data/face_datasets/opencv_face_dataset/train/neg/info.dat \
                    -numPos 4200 \  # 這裏的數量須要比實際寫入的正例圖片要小,否則可能會報錯
                    -numNeg 32000 \  # 負例圖片數
                    -numStages 5 \   # stage數越多,訓練效果越好,可是耗時也越長
                    -numThreads 6 \
                    -featureType LBP \  # 官方文檔裏面沒有說支持HOG,可是在opencv3.4中,經過命令行能夠看到有這個參數 ,雖然能夠訓練,可是已經不支持
                    -w 112 \
                    -h 112 \
                    -precalcValBufSize 4096 \  # (in Mb) Size of buffer for precalculated feature values; size larger, training faster
                    -precalcIdxBufSize 4096

4. 測試

import cv2

face_detector = cv2.CascadeClassifier("cascade.xml")

img = "test.jpg"
frame = cv2.imread(img)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

faces = face_detector.detectMultiScale(frame, 1.3, 3)
for face in faces:
    cv2.rectangle(frame, (face[0], face[1]), (face[0]+face[2],face[1]+face[3]), (0, 0, 255), 2)
cv2.imshow("test", frame)
cv2.waitKey(0)

HOG特徵

雖然cascade classifier的HOG特徵在3.x版本是不能用了(2.4版本仍是能夠的),可是能夠用opencv samples/cpp/train_HOG.cpp(或者是這個庫)
首先須要編譯.cpp文件得到.o文件(編譯opencv的sample文件能夠看這裏):函數

g++ `pkg-config --cflags --libs opencv` -o train_HOG opencv/samples/cpp/train_HOG.cpp

訓練:測試

train_HOG --dw=112 \      # 圖像的檢測窗口高度
                  --dh=112 \       # 圖像的檢測窗口高度(與圖像有關,可是必須爲8的整數倍--腳本內劃窗方式決定)
                  -d \                  # 訓練2次(提升精度)
                  --fn=hog_face_detector.xml \                        # 輸出訓練模型文件
                  -f \
                  --nd=opencv_face_dataset/train_hog/neg \  # 負例文件目錄
                  --pd=opencv_face_dataset/train_hog/pos \  # 正例文件目錄
                  --td=opencv_face_dataset/train_hog/val \    # 測試文件目錄
                  --tv=test.mp4  # 測試視頻文件

測試:命令行

import cv2

hog_face_file = "hog_face_detector.xml"
hog_model = cv2.HOGDescriptor()
hog_model.load(hog_face_file)

win_stride = (8, 8)
padding = (16, 16)
scale = 1.05

cam = cv2.VideoCapture(0)
while cam.isOpened():
    ret, frame = cam.read()
    if ret:
        detect_region = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = hog_model.detectMultiScale(detect_region, winStride=win_stride, padding=padding, scale=scale)  # 返回tuple(array of bounding box, array of bounding box confidence)
        faces = list(faces[0])    
        if len(faces):
            face = faces[0]  # 只取機率最高的一我的臉
            cv2.rectangle(frame, (face[0], face[1]), (face[0]+face[2], face[1]+face[3]), (0, 0, 255), 2)
        cv2.imshow("test", frame)
        if cv2.waitKey(1) == ord("q"):
            break
cv2.destroyAllWindows()

具體參數意義能夠參考這裏code

參考:

cascade classifier:

train_HOG

相關文章
相關標籤/搜索