Prerequisites:
python2.7、openCV3.0
代碼及註釋
def detectface(filename):
files = []
print('Using face detector %s' % FLAGS.face_detection_model)
face_detect = FaceDetector('haarcascade_frontalface_default.xml')
face_files, rectangles = face_detect.run(filename)
files += face_files
if (len(files)>0) :
return 1
else:
return 0
主要是FaceDetector類的run函數實現了人臉檢測,run函數會返回人臉的文件、以及矩形區域
我們把FaceDetector類的實現代碼貼出來
class FaceDetector(object):
def __init__(self, model_name, basename = 'frontal-face', tgtdir = '.'):
self.tgtdir = tgtdir
self.basename = basename
self.face_cascade = cv2.CascadeClassifier(model_name)
def run(self, image_file, min_height_dec = 20, min_width_dec = 20, min_height_thresh=50, min_width_thresh=50):
print(image_file)
img = cv2.imread(image_file)
min_h = int(max(img.shape[0] / min_height_dec, min_height_thresh))
min_w = int(max(img.shape[1] / min_width_dec, min_width_thresh))
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = self.face_cascade.detectMultiScale(gray, 1.3, minNeighbors=5, minSize=(min_h,min_w))
images = []
for i, (x,y,w,h) in enumerate(faces):
images.append(self.sub_image('%s/%s-%d.jpg' % (self.tgtdir, self.basename, i+1), img, x, y, w, h))
print('%d faces detected' % len(images))
for (x,y,w,h) in faces:
self.draw_rect(img, x, y, w, h)
# Fix in case nothing found in the image
outfile = '%s/%s.jpg' % (self.tgtdir, self.basename)
cv2.imwrite(outfile, img)
return images, outfile
def sub_image(self, name, img, x, y, w, h):
upper_cut = [min(img.shape[0], y+h+FACE_PAD), min(img.shape[1], x+w+FACE_PAD)]
lower_cut = [max(y-FACE_PAD, 0), max(x-FACE_PAD, 0)]
roi_color = img[lower_cut[0]:upper_cut[0], lower_cut[1]:upper_cut[1]]
cv2.imwrite(name, roi_color)
return name
def draw_rect(self, img, x, y, w, h):
upper_cut = [min(img.shape[0], y+h+FACE_PAD), min(img.shape[1], x+w+FACE_PAD)]
lower_cut = [max(y-FACE_PAD, 0), max(x-FACE_PAD, 0)]
cv2.rectangle(img, (lower_cut[1],lower_cut[0]),(upper_cut[1],upper_cut[0]), (255,0,0), 2)
FaceDetector類有init初始化函數來初始化顯式變量,是可變長參數
我們第一段代碼中只是傳了模型參數
more haarcascade_frontalface_default.xml
打開模型配置文件,發現是一堆xml配置參數
<stages>
<_>
<maxWeakCount>9</maxWeakCount>
<stageThreshold>-5.0425500869750977e+00</stageThreshold>
<weakClassifiers>
<_>
<internalNodes>
0 -1 0 -3.1511999666690826e-02</internalNodes>
<leafValues>
2.0875380039215088e+00 -2.2172100543975830e+00</leafValues></_>
<_>
<internalNodes>
0 -1 1 1.2396000325679779e-02</internalNodes>
<leafValues>
-1.8633940219879150e+00 1.3272049427032471e+00</leafValues></_>
<_>
<internalNodes>
0 -1 2 2.1927999332547188e-02</internalNodes>
<leafValues>
-1.5105249881744385e+00 1.0625729560852051e+00</leafValues></_>
<_>
<internalNodes>
0 -1 3 5.7529998011887074e-03</internalNodes>
<leafValues>
-8.7463897466659546e-01 1.1760339736938477e+00</leafValues></_>
<_>
<internalNodes>
0 -1 4 1.5014000236988068e-02</internalNodes>
<leafValues>
-7.7945697307586670e-01 1.2608419656753540e+00</leafValues></_>
<_>
<internalNodes>
這是從openCV源碼那邊拷貝過來的,是別人訓練好的haar分類器模型,可以看到起到主要作用的函數是
detectMultiScale
人臉檢測主要用到的是CascadeClassifier這個類,以及該類下的detectMultiScale函數。
函數原型是:
void CascadeClassifier::detectMultiScale(InputArray image, vector<Rect>& objects, double scaleFactor=1.1, int minNeighbors=3, int flags=0, Size minSize=Size(), Size maxSize=Size())
總共有7個參數,分別是
第一個參數image: 要檢測的圖片,一般爲灰度圖
第二個參數objects: Rect型的容器,存放所有檢測出的人臉,每個人臉是一個矩形
第三個參數scaleFactor: 縮放因子,對圖片進行縮放,默認爲1.1
第四個參數minNeighbors: 最小鄰居數,默認爲3
第五個參數flags: 兼容老版本的一個參數,在3.0版本中沒用處。默認爲0
第六個參數minSize: 最小尺寸,檢測出的人臉最小尺寸
第七個參數maxSize: 最大尺寸,檢測出的人臉最大尺寸
這裏關注第六和第七個參數,由之前的代碼看出
min_h = int(max(img.shape[0] / min_height_dec, min_height_thresh))
min_w = int(max(img.shape[1] / min_width_dec, min_width_thresh))
img.shape[0]和img.shape[1]分別是圖片的高、寬,然後除以20的整數,和預設的min_height_thresh、min_width_thresh作比較後,取最大值的整數。
也就是理論上說可以最小檢測到圖片1/20的人臉
可以看到這裏沒有傳遞最大的值。
具體的參數配置可參考這篇csdn博友的文章http://blog.csdn.net/delltdk/article/details/9186875
(待續)