级联分类器
在本教程中,
- 我们将学习 Haar 级联目标检测的工作原理。
- 我们将看到使用基于 Haar 特征的级联分类器进行人脸检测和眼睛检测的基础。
- 我们将使用 cv::CascadeClassifier 类来检测视频流中的目标。具体而言,我们将使用以下函数:
- cv::CascadeClassifier::load 来加载 .xml 分类器文件。它可以是 Haar 或 LBP 分类器。
- cv::CascadeClassifier::detectMultiScale 来执行检测。
基于 Haar 特征的级联分类器的目标检测是一种有效的目标检测方法,由 Paul Viola 和 Michael Jones 在他们 2001 年的论文 “Rapid Object Detection using a Boosted Cascade of Simple Features” 中提出。它是一种基于机器学习的方法,其中级联函数是从大量正样本和负样本图像中训练出来的。然后将其用于检测其他图像中的目标。
这里我们将处理人脸检测。最初,算法需要大量的正样本图像(人脸图像)和负样本图像(无人脸的图像)来训练分类器。然后我们需要从中提取特征。为此,使用下图所示的 Haar 特征。它们就像我们的卷积核。每个特征是一个单一值,通过从黑色矩形下像素之和减去白色矩形下像素之和得到。
现在,使用每个核的所有可能尺寸和位置来计算大量特征。(想象一下这需要多少计算量?即使是 24x24 的窗口也会产生超过 160000 个特征)。对于每次特征计算,我们需要找到白色和黑色矩形下的像素之和。为了解决这个问题,他们引入了积分图像。无论你的图像多大,它都将给定像素的计算简化为仅涉及四个像素的操作。不错,不是吗?它让事情变得超级快。
但在我们计算的所有这些特征中,大多数是无关的。例如,考虑下面的图像。第一行显示了两个好的特征。选择的第一个特征似乎关注于这样一个属性:眼睛区域通常比鼻子和脸颊区域更暗。选择的第二个特征依赖于眼睛比鼻梁更暗的属性。但将同样的窗口应用于脸颊或任何其他地方则是无关的。那么我们如何从 160000+ 个特征中选择最佳特征呢?这是通过 Adaboost 实现的。
为此,我们将每个特征应用于所有训练图像。对于每个特征,它找到将人脸分类为正样本和负样本的最佳阈值。显然,会存在错误或误分类。我们选择错误率最低的特征,这意味着它们是最准确地对人脸和非人脸图像进行分类的特征。(该过程并非如此简单。开始时每张图像被赋予相等的权重。每次分类之后,误分类图像的权重会增加。然后执行相同的过程。计算新的错误率。以及新的权重。该过程持续进行,直到达到所需的精度或错误率,或者找到所需数量的特征)。
最终的分类器是这些弱分类器的加权和。之所以称为弱分类器,是因为它单独无法对图像进行分类,但与其他分类器一起构成了一个强分类器。论文说,即使是 200 个特征也能提供 95% 精度的检测。他们最终的设置有大约 6000 个特征。(想象一下从 160000+ 个特征减少到 6000 个特征。这是一个巨大的收获)。
所以现在你取一张图像。取每个 24x24 的窗口。对其应用 6000 个特征。检查它是否是人脸。哇……这不是有点低效和耗时吗?是的。作者对此有一个很好的解决方案。
在一张图像中,图像的大部分是非人脸区域。因此,最好有一个简单的方法来检查一个窗口是否不是人脸区域。如果不是,就一次性丢弃它,不再处理它。相反,把注意力集中在可能有人脸的区域上。这样,我们花更多时间检查可能的人脸区域。
为此,他们引入了分类器级联的概念。特征不是一次性应用于一个窗口,而是被分组到分类器的不同阶段,并一个接一个地应用。(通常前几个阶段将包含非常少的特征)。如果一个窗口未通过第一阶段,就丢弃它。我们不再考虑它上面的其余特征。如果它通过了,就应用第二阶段的特征并继续该过程。通过所有阶段的窗口是人脸区域。这个计划怎么样!
作者的检测器有 6000+ 个特征,分为 38 个阶段,前五个阶段分别有 1、10、25、25 和 50 个特征。(上图中的两个特征实际上是 Adaboost 得到的最佳两个特征)。据作者称,每个子窗口平均评估 6000+ 个特征中的 10 个。
所以这是对 Viola-Jones 人脸检测如何工作的一个简单直观的解释。更多细节请阅读论文或查看”附加资源”一节中的参考文献。
OpenCV 中的 Haar 级联检测
Section titled “OpenCV 中的 Haar 级联检测”OpenCV 提供了训练方法(参见 tutorial_traincascade)或预训练模型,可以使用 cv::CascadeClassifier::load 方法读取。预训练模型位于 OpenCV 安装目录的 data 文件夹中,也可以在这里找到。
以下代码示例将使用预训练的 Haar 级联模型来检测图像中的人脸和眼睛。 首先,创建一个 cv::CascadeClassifier,并使用 cv::CascadeClassifier::load 方法加载必要的 XML 文件。 然后,使用 cv::CascadeClassifier::detectMultiScale 方法执行检测,该方法返回检测到的人脸或眼睛的边界矩形。
本教程的代码如下所示。你也可以从这里下载 代码见下方示例 本教程的代码如下所示。你也可以从这里下载 代码见下方示例 本教程的代码如下所示。你也可以从这里下载 代码见下方示例

-
以下是运行上述代码并使用内置网络摄像头的视频流作为输入的结果:
确保程序能找到 haarcascade_frontalface_alt.xml 和 haarcascade_eye_tree_eyeglasses.xml 文件的路径。它们位于 opencv/data/haarcascades 中。
-
这是使用 lbpcascade_frontalface.xml(LBP 训练)文件进行人脸检测的结果。对于眼睛,我们继续使用教程中使用的文件。
-
Paul Viola and Michael J. Jones. Robust real-time face detection. International Journal of Computer Vision, 57(2):137–154, 2004. [Viola04]
-
Rainer Lienhart and Jochen Maydt. An extended set of haar-like features for rapid object detection. In Image Processing. 2002. Proceedings. 2002 International Conference on, volume 1, pages I–900. IEEE, 2002. [Lienhart02]
-
关于人脸检测与跟踪的视频讲座
-
Adam Harvey 关于人脸检测的一个有趣采访
-
Adam Harvey 在 Vimeo 上的 OpenCV 人脸检测:可视化
