用python、opencv快速实现人脸检测

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章