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
(待续)