OpenCV/JavaCV人脸识别 - 非常相似的置信度值

12

我将解释一下我的尝试,因为这似乎是理解我的问题所必需的。

我目前正在尝试人脸识别,即基于数据库中已知图片识别站在摄像头前的人员。

这些已知图片是从身份证明智能卡(仅包含单张正面照片)或社交网络上的正面面部剖面照片中收集的。根据我目前的阅读,好的人脸识别需要一定数量的训练图像(50+)。因此,由于我收集到的图片太少,无法创建可靠的训练集,我尝试将我的实时相机帧捕获(当前使用150个)作为训练集,以前收集的已识别图片作为测试集。我不确定我现在的做法是否正确,请告诉我如果我搞错了。

因此,问题是,在我有了5张从智能卡得到的已识别图片之后,我尝试使用相机拍摄的150帧作为训练集进行人脸识别。但是在识别时,每个测试面孔的置信度非常相似,使整个程序毫无用处,因为我无法准确识别任何人。经常使用不同的相机拍摄作为训练,我从随机人员的照片中获得了比我的照片更高的置信度值。

因为我很困惑,所以非常感谢您能给我任何帮助。

谢谢。

注意:我正在使用JavaCV包装器进行OpenCV编程,并使用包中随附的haarcascades。Eigenfaces是所用的算法。


你正在使用哪些模型来训练什么数据还不清楚吗? - Louis Wasserman
如果我正确理解了你的问题,那么我的做法是在训练集中使用灰度、均衡化、裁剪后的人脸图像。测试集中也使用相同类型的图像。 - Fábio Constantino
2个回答

27

人脸识别

简介

我想补充一点内容。libfacerec 已经被包含在官方的 OpenCV 2.4.2 中,详情请参见:

这意味着如果您使用的是OpenCV 2.4.2,则在contrib模块中有新的cv::FaceRecognizer。我知道最近添加了Python封装(感谢!),可能在编写本文时也已经包装了Java。 cv::FaceRecognizer附带了详细的文档,将向您展示如何使用许多完整源代码示例进行人脸识别: 如果您想了解可用的人脸识别算法(Eigenfaces、Fisherfaces、局部二进制模式直方图),那么特别是要阅读OpenCV人脸识别指南。在那里,我将解释这些算法的工作原理并提及它们的缺点。

使用少量图像进行人脸识别

现在来解决你的问题,即当你的训练数据集很小时如何识别人脸。我会给你写一篇详细的答案,这可能会帮助从谷歌搜索而来的人们。

实际上,在数据集中每个人只有非常少的样本时,不应该使用特征脸或费舍尔脸。这些模型需要数据才能发挥作用,我再次强调这点。数据越多越好。这些方法是基于估计数据中的方差,因此请提供一些数据以估算模型!不久前,我在AT&T人脸数据库上运行了一个小测试(使用facerec framework),显示了这些方法在每个人的图像数量不同的情况下的性能:

enter image description here

我在这里不写一篇出版物,也不会用详细的数学分析来支持这些数字。这已经做过了,所以我建议每个怀疑这些数字的人去参考(2),以便看到PCA(Eigenfaces)和LDA(Fisherfaces)在小训练数据集上的非常详细的分析。
因此,我建议在小样本场景中使用局部二进制模式直方图(3)进行面部识别。这些也包含在OpenCV FaceRecognizer中,并且已被证明在小训练数据集上表现非常好。如果将其与TanTriggs预处理(4)结合使用,您应该拥有一个非常强大的面部识别模型。 TanTriggs预处理是Python中的8行代码(左右),请参见https://github.com/bytefish/facerec/blob/master/py/facerec/preprocessing.py#L41以获取实现。这应该很容易适应Java(或者如果需要,我可以使用OpenCV实现它)。
(1) Belhumeur, P. N., Hespanha, J., and Kriegman, D.《利用类别特定线性投影的特征脸与Fisherfaces进行识别》。IEEE模式分析与机器智能交易,19卷7期(1997年),711-720页。 (2) Martinez, A和Kak, A.《PCA与LDA对比》。IEEE模式分析与机器智能交易,第23卷,第2期,第228-233页,2001年。 (3) Ahonen, T.,Hadid, A.,和Pietikainen, M.《使用局部二进制模式进行人脸识别》。计算机视觉-ECCV 2004(2004年),469-481页。 (4) Tan, X.和Triggs, B.《增强的本地纹理特征集用于在困难照明条件下进行人脸识别》。IEEE图像处理交易,19(2010年),1635-650页。

非常感谢您的回答,先生。我一直对此感到有些绝望,因为我以前的方法无法产生任何像样的结果,即使在lukaskrieger的帮助下也是如此(尽管我仍然感激您的帮助!)。我将不得不尝试一下这个方法,并在这里发布我所能够取得的成果。再次感谢您的洞察力,非常感谢:) - Fábio Constantino
你好,我一直在尝试寻找一些Java的示例代码/教程,因为似乎已经有人将其包装起来了 - http://code.google.com/p/javacv/source/browse/src/main/java/com/googlecode/javacv/cpp/opencv_contrib.java#841。然而,我没有成功地找到教程,也无法自己完成...几次挫败后,我尝试着使用C++代码,因为它有创建的示例,但我似乎无法运行它,总是返回:“‘imread’ was not declared in this scope”,在编译facerec_lbph.cpp时。 - Fábio Constantino
显然,那里包装的接口不是OpenCV 2.4.2。Javacv可能需要一些时间来适应。局部二进制模式直方图在OpenCV中可用,并且我昨天刚编译了演示程序用于回答这个问题,并且可以正常工作:http://stackoverflow.com/a/11399099/513875。请确保阅读此答案,如果问题仍然存在,则可能要在http://answers.opencv.org/questions上提问或提交错误报告。错误不会在http://stackoverflow.com上提交,而是在http://code.opencv.org的错误跟踪器上提交。 - bytefish
1
你好,我的之前的问题通过将我的openCV从2.4.1升级到2.4.2得以解决。我曾经认为在2.4之后的任何版本都可以工作。现在,我可以使用我的测试csv文件编译和测试您的示例代码facerec_lbph.cpp,但结果仍然很糟糕。我认为这是因为我用于训练的图像是灰度直方图均衡化图像,而不是TanTriggs处理过的图像。即使阅读并尝试了Python示例,我仍然无法将此预处理方法应用于我的图像。请问您能否给出任何提示来指导我正确的方向? - Fábio Constantino

6
您想知道如何只使用一张训练图像进行人脸识别。这是可能的,但也取决于您要分类的不同人数。基本的人脸识别需要约50张面孔来计算面部空间(特征脸)。您可以从任何喜欢的面部数据库中获取这些面部数据。http://www.face-rec.org/列出了几个数据库并解释了不同的算法。在计算面部空间后,使用您拥有的所有面孔进行训练。如果您得到太多错误分类,建议尝试混合方法。混合方法将模板匹配算法(特征脸、Fisherfaces)与基于特征的算法相结合。在这种情况下,您可以使用第一个算法的输出,并将眼睛、鼻子、眉毛、下巴形状等与测试面部匹配。简而言之:
  1. 使用Haarcascades从每个图像中提取人脸
  2. 计算您的人脸空间
  3. 为每张人脸进行训练
  4. 请求人脸分类
  5. 选择最可能的分类并检查人脸特征

如果您还没有找到它,OpenCV还有一个人脸识别库: https://github.com/bytefish/libfacerec

编辑: 我不会使用超过10-15个组件(特征脸)。


你好,谢谢回复 :) 我也尝试过这种方式,使用了Cambridge_FaceDB,其中我的训练图像是这个人脸数据库中的所有图像加上我从智能卡收集到的自己识别的图片。我正在测试将3张收集到的图片插入训练集中,测试集包含3张属于这些人的不同图片。即使如此,我仍然得到大约95%的置信度,判定为完全不同的人。 PS:我目前没有使用混合方法,但即使没有这种方法,我也期望得到非常不同的结果。 还有什么其他可能会导致这种情况呢? - Fábio Constantino
在我看来,您似乎将面部空间生成与训练自己的面孔混淆了。您不需要将3个收集到的面孔添加到训练集中。只需使用数据库图像生成面部空间即可。这为您提供了一种将面孔投影到坐标系中的转换方式。基本上,您将此转换应用于以后要识别的主体的面孔(训练)。如果您将变换应用于要识别的面孔,则将其投影到相同的坐标系中并与最近邻匹配(匹配)。现在先不考虑置信区间。 - lukaskrieger
好的,我明显在这里搞砸了..所以,我只会使用一个已下载的人脸数据库作为训练集,这将生成平均图像和特征脸,对吧?接下来的部分是我不太理解的。我正在从相机中收集图像,并且我想知道这个人是否是已知的人(他的面部图片已经从他的智能卡中检索出来)。我之前做的是,简单地加载保存的训练数据,然后将测试图像投影到PCA子空间中,以便找到最近的邻居,但结果总是错误的。 - Fábio Constantino
现在你明白了。在子空间中,你需要预分类的人脸。这些是你的训练人脸。当你将一个未知的人脸投影到空间中并找到最近的邻居时,你就得到了你的分类结果。 - lukaskrieger
这对我来说没有意义,许多使用opencv和javacv的人脸识别指南都要求创建一个文本文件,指定训练图像的位置(即要识别的人的训练图像)。如果我只使用剑桥图像作为训练图像,如何能够期望在其中识别自己?目前正在尝试匹配并确定不符合测试脸的最近邻居... 如果你熟悉它,我一直在遵循javaCV包中提供的示例代码“FaceRecognition.java”。 - Fábio Constantino
剑桥图像用于计算转换以投影到子空间中。相机图像用于训练。然后进行测试。 - lukaskrieger

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