OpenCV 4.11.0
开源计算机视觉库
|
原作者 | Ana Huamán |
兼容性 | OpenCV >= 3.0 |
在本教程中,
使用基于 Haar 特征的级联分类器的目标检测是由 Paul Viola 和 Michael Jones 在他们 2001 年的论文“使用简单特征的增强级联进行快速目标检测”中提出的一种有效的目标检测方法。这是一种基于机器学习的方法,其中级联函数由大量的正样本图像和负样本图像训练得到。然后用于检测其他图像中的对象。
在这里,我们将进行人脸检测。最初,该算法需要大量的正样本图像(人脸图像)和负样本图像(无面部图像)来训练分类器。然后我们需要从中提取特征。为此,使用下图所示的 Haar 特征。它们就像我们的卷积核。每个特征都是通过从黑色矩形下像素的总和中减去白色矩形下像素的总和而获得的单个值。
现在,使用每个核的所有可能的尺寸和位置来计算大量的特征。(想象一下需要多少计算?即使是 24x24 的窗口也会产生超过 160000 个特征)。对于每个特征计算,我们需要找到白色和黑色矩形下像素的总和。为了解决这个问题,他们引入了积分图像。无论你的图像有多大,它都将给定像素的计算减少到只涉及四个像素的操作。不错,不是吗?它使事情变得超级快。
但是,在我们计算的所有这些特征中,大多数都是无关紧要的。例如,考虑下面的图像。顶行显示了两个良好的特征。选择的第一个特征似乎关注眼睛区域通常比鼻子和脸颊区域更暗的属性。选择的第二个特征依赖于眼睛比鼻梁更暗的属性。但是应用于脸颊或任何其他地方的相同窗口是无关紧要的。那么我们如何从 160000 多个特征中选择最佳特征呢?这是通过 **Adaboost** 实现的。
为此,我们将每个特征应用于所有训练图像。对于每个特征,它都会找到最佳阈值,该阈值将人脸分类为正样本和负样本。显然,会出现错误或误分类。我们选择误差率最小的特征,这意味着它们是最准确地对人脸和非人脸图像进行分类的特征。(该过程并不像这样简单。一开始每个图像都赋予相同的权重。每次分类后,误分类图像的权重都会增加。然后重复相同的过程。计算新的误差率。还有新的权重。该过程持续进行,直到达到所需的精度或误差率,或者找到所需的特征数量)。
最终分类器是这些弱分类器的加权和。它被称为弱分类器,因为它单独无法对图像进行分类,但与其他分类器一起形成强分类器。论文中说,即使是 200 个特征也能提供 95% 的检测精度。他们的最终设置大约有 6000 个特征。(想象一下从 160000 多个特征减少到 6000 个特征。这是一个很大的进步)。
所以现在你拿一张图片。取每个 24x24 的窗口。对其应用 6000 个特征。检查它是否是人脸。哇……是不是有点低效且费时?是的,是的。
在一幅图像中,大部分图像是非人脸区域。因此,最好有一个简单的方法来检查窗口是否不是人脸区域。如果不是,则一次性丢弃它,不要再次处理它。相反,关注可能存在人脸的区域。这样,我们就可以花更多的时间检查可能的人脸区域。
为此,他们引入了 **级联分类器** 的概念。不是将所有 6000 个特征应用于窗口,而是将特征分组到不同的分类器阶段并逐个应用。(通常,前几个阶段将包含非常少得多的特征)。如果窗口未能通过第一阶段,则将其丢弃。我们不考虑其上的剩余特征。如果通过,则应用第二阶段的特征并继续该过程。通过所有阶段的窗口为人脸区域。这个计划怎么样!
作者的检测器有 6000 多个特征,38 个阶段,前五个阶段分别有 1、10、25、25 和 50 个特征。(上图中的两个特征实际上是从 Adaboost 中获得的最佳两个特征)。根据作者的说法,平均每个子窗口评估 6000 多个特征中的 10 个特征。
因此,这是一个关于 Viola-Jones 人脸检测工作原理的简单直观解释。阅读论文以了解更多详细信息,或查看附加资源部分中的参考文献。
OpenCV 提供了一种训练方法(参见 级联分类器训练)或预训练模型,可以使用 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* 目录下。