如何使用C++和OpenCV对齐人脸图像

18

我正在开发一款用于人脸认证的 C++ 应用程序。首先,我需要检测人脸并对图像进行预处理。

  1. 为了进行人脸检测,我使用了 HaarCascadeClassifier 工具。问题是这个工具或算法会给出一个稍微大一点的矩形来框选包括头发和一些背景在内的面部区域。有没有解决方案可以更改这个矩形的尺寸?我使用了 "frontalfacecascaadclassifier.xml"。
  2. 对于人脸预处理,我想要做到像这个技术所示的人脸对齐。我该如何实现?

为什么不能将PCA用于面部定向检测,就像这里所示的那样(https://robospace.wordpress.com/2013/10/09/object-orientation-principal-component-analysis-opencv/)? - Seanny123
我发现dlib似乎是一个非常强大的库,而且它快速、免费且开源。 - dashesy
9个回答

18
寻找给定图像中眼睛的准确位置远非易事。在OpenCV中查找眼睛的Haar-cascades会产生太多误报,无法使用。此外,这种方法对图像旋转不具有鲁棒性(尽管它可以补偿轻微旋转,但我不知道训练图像)。如果我是您,我会从http://scholar.google.com开始广泛搜索相关研究领域的论文。
您需要一个强大的头部姿势估计来对齐面部图像。我自己进行了一些研究,认为共享算法和代码在这里很有用。我看过的最有趣的方法有:

我想要执行类似于http://www.bytefish.de/blog这样的方法,并获得像http://www.bytefish.de/_detail/blog/arnie_20_20_200_200.jpg?id=blog这样的图像。有没有在C++中实现的想法? - OntoBLW

8

您可以使用另一个Haar分类器来查找每只眼睛(眼睛很容易找到),然后假设人有两只眼睛,我们定义“水平”脸为眼睛水平。

简单地测量两只眼睛之间的角度,并将图像旋转该角度。

angle = atan ( eye1.Y - eye2.Y ) / (eye1.X - eye2.X )

感谢您的回复,尤其是您的快速回复。是的,我同意您在检测第一道眼睛方面的观点。但我还没有明白如何“定义‘水平’脸部以表示眼睛是水平的”。这是否要归功于您定义的角度?实际上,我应该如何根据眼睛的位置来识别脸部? - OntoBLW
@louloulili - 你说你已经从Haar中找到了脸,只需要旋转它? - Martin Beckett
我想要一张像这样的图片 http://www.bytefish.de/_media/blog/arnie_20_20_200_200.jpg?cache=&w=200&h=200 但是我找到了一张像这样的图片 http://www.bytefish.de/_media/blog/arnie_30_30_200_200.jpg 并且haar检测脸部的矩形很大。之后我会将其旋转以对齐它。请帮帮我,提前感谢您的回复。 - OntoBLW
2
@MartinBeckett 是的,这就是 http://www.bytefish.de/blog/aligning_face_images 上的 Python 脚本所做的事情。我认为问题是关于找到眼睛位置的,这并不是一个简单的答案。 - bytefish
@/bytefish,我正在开发一个C++应用程序,能否检测眼睛位置,然后计算角度= ang = atan(eye1.Y - eye2.Y) / (eye1.X - eye2.X),然后使用这个角度进行仿射变换,以获得像Python脚本中所获得的结果,并且确切地获得像这样的图像http://www.bytefish.de/_media/blog/arnie_20_20_200_200.jpg?谢谢您的帮助。 - OntoBLW

6
我尝试了来自“野生标记脸部”项目页面的以下面部对齐代码。它非常好用,不需要检测面部特征点。可以从以下链接下载 C++ 代码:http://vis-www.cs.umass.edu/faceAlignment/ 如果你仍然希望找到面部关键点,我发现 Viola-Jones 检测器并不是非常稳健和准确。我个人推荐使用 Flandmark 面部关键点检测器:http://cmp.felk.cvut.cz/~uricamic/flandmark/,它更加稳健和准确。可以从以上链接下载 C 代码。

使用他们的people.train数据对我的一些样本图像进行训练,效果不如我所希望的那样好。它旋转了一些我的控制图像,并且没有像我想要的那样旋转我的测试图像。您能否分享一下您的测试集样本以及它给出的结果,这将使我更有信心做出这个建议? - Seanny123
1
我不熟悉你提到的people.train模型。我使用了凝聚代码来训练自己的模型,我称之为faces.train,用了大约1000张人脸。然后使用漏斗代码来对齐人脸。首先,你的训练和测试图像中的原始错位不能太“远”。如果它们的错位超过40度或者比例差异太大,它就行不通。阅读论文。不要把它当作黑匣子。 - lightalchemist
我尝试过的测试集之一是这个。请注意,如何裁剪脸部以及参数(尤其是内外窗口大小)非常重要。您需要一个仅捕捉从眉毛到嘴唇或下巴的内部窗口。 - lightalchemist
此外,不要期望它能在侧面朝向的脸上表现出奇迹。您可以尝试运行他们提供的汽车数据集以及该代码。这将让您了解需要设置的“窗口”的大小。 - lightalchemist
它基本上通过将对象(不仅仅是脸部)的图像堆叠在一起,并找到(通过非最优贪婪方法)对象的变换(缩放,平移和平面旋转),使得公共部分位于相同位置,即如果在相同位置穿过图像堆栈,则会得到相同部位的脸。因此,如果使用具有眉毛的面孔进行训练,则需要具有该特征的面孔来帮助其对齐面部。此外,您需要大约500个像样的训练图像才能很好地训练它。记住,垃圾进垃圾出。 - lightalchemist
显示剩余3条评论

4
现代人脸对齐方法的最先进方法必须是这样的:Supervised Descent Method and its Application to Face Alignment X. Xiong and F. De la Torre in CVPR 2013。它非常快速和有效。您可以查看他们的项目网站IntraFace。他们提供易于使用的软件。然而,核心部分代码即监督下降法(SDM)未发布,只有简单的线性回归可以轻松实现。这里展示了一个演示,可以处理倾斜的人脸(为保护隐私,添加模糊并注意左上角的轴):https://drive.google.com/file/d/0BztytuqPViMoTG9QaEpZWi1NMGc/edit?usp=sharing

虽然这是一个有用的链接,但在给你赏金之前,我想要更多的细节,例如证明它可以检测到倾斜的脸和/或倾斜的程度。 - Seanny123
上图展示了一个演示。对于代码,作者提供的是一个Matlab .p文件,可以在您的应用程序中使用,但源代码未知。然而,我强烈建议您查看论文,底层算法非常简单。 - rookiepig
1
请注意,该程序实际上非常容易编译和运行。然而,演示程序仅跟踪单个面部的特征。 - Seanny123
该项目的下载链接似乎已经丢失了(或者可能是您所说的未发布的部分?)。 - dashesy
1
我发现了一种真正的最先进的方法,它也是FOSS和无专利的dlib - dashesy
显示剩余2条评论

1
检测未对齐的面孔使人脸识别变得困难。有时您想要修复对齐,有时仅需要排除未正确对齐的面孔(例如在视频流中检测面孔)。我采取了后一种方法,并训练了一个特殊的Haar级联分类器,只检测正确对齐、光线充足的面孔。详细信息请参见:http://rwoodley.org/?p=417
如果您使用我的级联分类器,请告诉我它为您工作的情况。我很好奇其他人会得到什么结果。它满足了我的需求。

1

0

可以看一下CSIRO面部分析SDK(网站和演示, 源代码)软件,它可以进行面部对齐,并使用66个基准点进行跟踪。它速度快且非常精确。


我正在我的论文中使用它。我可以说这是我见过的最好的面部对齐软件之一。它可以实时跟踪66个关键点。更多细节请参阅此论文:“通过正则化平均漂移拟合可变形模型”。 - ivan_a
该程序无法处理带有侧倾人脸的图像。 - Seanny123
它使用OpenCV人脸检测器来检测人脸。您可以尝试使用其他能够处理倾斜面的人脸检测器来初始化CSIRO跟踪器。然而,通常为了解决认证问题,您需要将变量集合缩小到最小,使每个训练图像与测试图像尽可能相似。 - ivan_a

0
整天搜寻算法后,我在从 Google 切换到 DuckDuckGo 后找到了 Hemlata 等人的《通过查找面部特征和倾斜脸部的倾斜角来进行人脸检测》。它支持倾斜角大于45度的人脸。
至于如何在代码中实现,这是我目前正在努力解决的问题,但至少这是一个起点。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接