python-计算机视觉-OpenCV-人脸特征提取

Goal

我们将看到使用基于Haar特征的级联分类器进行人脸检测的基础。

我们将扩展眼睛检测和笑容特征提取等。

Haar基础 

使用基于Haar特征的级联分类器进行目标检测是Paul Viola和Michael Jones在2001年的论文《使用简单特征的增强级联快速目标检测》中提出的一种有效的目标检测方法。它是一种基于机器学习的方法,从大量的正面和负面图像中训练级联函数。然后,它被用来检测其他图像中的对象。

这里我们将研究人脸检测。该算法首先需要大量的正面图像(人脸图像)和负面图像(没有人脸的图像)来训练分类器。然后我们需要从中提取特征。为此,使用如下图所示的haar特性。它们就像卷积核。每个特征都是一个单一的值,由白色矩形下的像素和减去黑色矩形下的像素和得到。

python-计算机视觉-OpenCV-人脸特征提取_第1张图片

 现在,每个内核的所有可能大小和位置都被用来计算大量的特性。(想象一下它需要多少计算量?即使是一个24x24的窗口也有超过16万个功能)。对于每一个特征的计算,我们都需要找到白色和黑色矩形下的像素之和。为了解决这个问题,他们引入了积分图像。它简化了对像素和的计算,即像素的数量可能有多大,只涉及四个像素的操作。不错,不是吗?它使事情变得超级快。

但在我们计算的所有这些特征中,大多数都是无关紧要的。例如,考虑下图。第一行显示了两个很好的特性。选择的第一个特征似乎集中在眼睛的区域通常比鼻子和脸颊的区域暗。选择的第二个特征依赖于眼睛比鼻梁颜色深的属性。但是同样的窗户在脸颊或其他任何地方都是无关紧要的。那么我们如何从16万多个特性中选择最好的特性呢?它是由Adaboost实现的。

python-计算机视觉-OpenCV-人脸特征提取_第2张图片

为此,我们在所有的训练图像上应用每一个特性。对于每个特征,它会找到最佳阈值,将人脸分为正面和负面。但很明显,会有错误或分类错误。我们选择错误率最小的特征,这意味着它们是对人脸和非人脸图像进行最佳分类的特征。(这个过程没有这么简单。每幅图像在开始时都被赋予相同的权重。每次分类后,错误分类的图像的权重都会增加。同样的过程。计算新的错误率。同时新的权重。这个过程将继续进行,直到达到所需的准确度或错误率,或找到所需的特征数为止)。

最终分类器是这些弱分类器的加权和。它之所以被称为弱分类器,是因为它单独不能对图像进行分类,但与其他分类器一起形成了一个强分类器。论文称,即使是200个特征也能提供95%的准确率。他们最后的设置大约有6000个功能。(想象一下从160000多个特性减少到6000个特性。这是一个巨大的收获)。

现在你拍一张照片。取每个24x24窗口。应用6000个功能到它。检查一下是不是正面。哇. .哇. .这不是有点低效和费时吗?是的,它是。作者对此有一个很好的解决方案。

在图像中,大部分图像区域是非人脸区域。因此,最好有一个简单的方法来检查窗口是否不是一个面区域。如果不是,就一次性扔掉。不要再处理它了。相反,要把注意力集中在有人脸的区域。这样,我们可以找到更多的时间来检查一个可能的面部区域。

为此,他们引入了级联分类器的概念。不是在一个窗口中应用所有的6000个特性,而是将这些特性分组到分类器的不同阶段,然后逐一应用。(通常最初的几个阶段包含的特性非常少)。如果一个窗口在第一阶段失败,则丢弃它。我们不考虑它的其他特性。如果通过,则应用特性的第二阶段并继续此过程。通过所有阶段的窗口是一个面区域。计划如何!!

作者的检测器有6000多个特征,共38个阶段,前5个阶段有1、10、25、25和50个特征。(上图中的两个特征实际上是Adaboost中最好的两个特征)。根据作者的说法,平均来说,6000多个特性中有10个是针对每个子窗口进行评估的。

这是对 Viola-Jones 人脸检测原理的一个简单直观的解释。要了解更多细节,请阅读论文或查看附加参考资料部分的参考资料。 

OpenCV人脸检测实现 

OpenCV配备了训练器和检测器。如果您想为任何对象(例如汽车、飞机等)训练自己的分类器,可以使用OpenCV创建一个。可以参考:https://docs.opencv.org/2.4/doc/user_guide/ug_traincascade.html

这里我们将讨论检测。OpenCV已经包含了许多预先训练好的脸部、眼睛、微笑等分类器。这些XML文件存储在opencv/data/haarcascades/文件夹中(pip安装的时候会自动下载)。如下目录有:

python-计算机视觉-OpenCV-人脸特征提取_第3张图片

让我们用OpenCV创建人脸,眼睛和微笑检测器。 

首先,我们需要加载所需的XML分类器。然后以灰度模式加载我们的输入图像(或视频)。

import numpy as np
import cv2

face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
face_smile = cv2.CascadeClassifier('haarcascade_smile.xml')

img = cv2.imread('timg.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 将图片转化成灰度

现在我们找到图像中的人脸。如果找到了人脸,它将返回检测到的人脸的位置为Rect(x,y,w,h)。一旦我们得到了这些位置,我们就可以为脸部创建一个ROI,并对这个ROI应用眼睛检测(因为眼睛总是在脸上!!)

faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
    img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
    roi_gray = gray[y:y+h, x:x+w]
    roi_color = img[y:y+h, x:x+w]
    eyes = eye_cascade.detectMultiScale(roi_gray)
    smiles = face_smile.detectMultiScale(roi_gray)
    for (ex,ey,ew,eh) in eyes:
        cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
    for (ex,ey,ew,eh) in smiles:
        cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(211,53,114),2)

cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果如下,蓝色方框内是人脸,绿色方框内是眼睛,紫色方框内是笑容特征:

你可能感兴趣的:(Python,OpenCV)