【问题标题】:How to store multiple features for face and find distance?如何存储多个面部特征并查找距离?
【发布时间】:2020-04-24 05:36:24
【问题描述】:

我正在做一个基于面部识别和验证的项目。我正在使用连体网络来获取人脸的 128 向量(嵌入)。

我将人脸的编码/嵌入存储在数据库中,然后检查或说将传入人脸的编码与先前存储的编码进行匹配以识别该人。

为了构建一个健壮的系统,我必须存储同一个人的多个编码。当我只使用一个编码向量,并匹配:

来自face_recognition库(获取距离):

face_recognition.compare_faces( stored_list_of_encodings, checking_image_encodings )

这并不总是有效,因为我只与单一编码进行了比较。为了使系统能够满足大多数情况,我想存储同一个人的至少 3 个编码,然后与新数据进行比较。

现在的问题是:如何存储同一个人的多个嵌入然后比较距离?

我使用 face_recognition 作为库和 Siamese Network 进行特征提取。

【问题讨论】:

    标签: python opencv computer-vision artificial-intelligence face-recognition


    【解决方案1】:

    有多种方法可以解决这个问题,我在人脸识别方面进行了广泛的研究,并且我尝试了一些方法。您可以执行以下一些操作。

    创建 KNN 分类器

    这样做的方法是创建一个数据库,其中每个特征都有一个与之关联的人名(在这种情况下,一个特征代表一个人的一张面部图像)。然后在比较时,您计算查询特征与每个表示的距离。您与 N 个最小距离进行比较。然后,您可以遍历 N 个距离并查看每个距离属于哪些类别,然后您可以使用出现次数最多的标签,这将是您的目标类别。根据我的经验,虽然这不是非常可靠(尽管这完全取决于您的测试数据的类型,但我的数据与很多野外图像有关,所以这还不够稳健)

    平均表现

    我使用的另一种方法是平均每个人的表示。如果我有 5 张图像,我会取从这些表示中提取的 5 个表示的平均值或中位数。根据我的经验,中位数比平均值效果更好。您现在将有一个与每个人相关的平均表示,您可以只计算每个平均表示的距离,距离最小的将是您的目标类。

    集群表示

    另一种方法是使用 DBScan 将表示聚类到聚类中,然后在运行时将查询表示分类到一个聚类中,并将该聚类中的多数类作为标签

    根据我的经验,平均表示是最好的,但你最终需要多张图片,我认为至少 5 张。但在我的情况下,我需要至少 5 个,因为我要迎合多个角度,什么不是。

    注意 :: SVM 是一种糟糕的方法,您会限制数据库大小,并且每次需要向数据库添加新人时,您都需要训练一个新的 SVM刚刚弹出的类

    此外,出于存储目的,您始终可以将其存储在 JSON 中

    【讨论】:

    • 如果你对距离/相似度算法进行矢量化,它们也非常快。此外,如果您使用像 cupy 这样的东西在 gpu 上执行这些距离/相似性,那么这也非常快,而这方面的好处是您使用阈值,因此根据您的问题,您可以获得非常安全的(高阈值) 或松散(低阈值)系统
    • 糟糕的是,我对 SVM 的看法是有缺陷的
    • SVM 不是已知人脸的数据库。因此,您需要为数据集中的每个人脸创建一个标签类。相反,您要做的是创建一个算法,该算法可以判断两个输入的面孔是否来自同一个人。因此,您可以将未知面孔与数据库中的每张面孔进行比较。因为使用 svm 进行分类相对较快,所以我想这将在可接受的时间内起作用,即使您有一百万张面孔要测试。您还可以根据性别、种族等对数据集进行预过滤以提高速度。但是 +1 是因为您所说的关于接受的答案是真实的。
    • 这与速度无关,knn 可能会比 svm 解决方案更快。我只是感觉两张脸之间的比较对于图片角度或其他外部影响的差异更加稳健。因此,如果您所有的照片都是从相同的角度和相同的质量拍摄的,那么肯定是要走的路。但是如果你不确定你的图片来自哪里以及你将拥有什么样的角度/质量/光线条件,那么比较应该比识别更可靠。
    • 当 SVM 限制数据库大小时,您能否详细说明您所说的内容? SVM 有许多优点,其中包括 1) 它是一种比 KNN 更健壮的算法 2) 在推理期间,您不必从数据库中加载训练数据。想象一个场景,您的数据库总是增加以识别 200 个面孔,推理时间将与 db 的 I/O 速度成正比,而 SVM,您只是存储边界(及其快速)。3)是的必须重新训练 SVM,但拟合 SVM 很快。但是一旦你安装了它,那么使用它就毫不费力
    【解决方案2】:

    您可以将所有面部嵌入存储在支持最近邻查询的数据库/数据结构中,然后对于任何给定的面部,您应该找到匹配项,在数据库中获取它的最近邻嵌入。通过 k 个最近邻居及其与查询项目的距离,您可以确定这张新面孔属于哪个人(如果它完全属于已知人)。

    您可以查看Approximate Nearest Neighbor Benchmark 以获取可用选项。

    请记住,它们被称为近似值,因此您不会得到准确的结果,但如果您要处理大量实体,这是最好的选择。如果您不是这种情况,您可以使用 sklearn 中已经提供的蛮力最近邻解决方案来获得精确匹配。

    【讨论】:

      【解决方案3】:

      您是否考虑过使用 SVM 分类器对人脸进行分类?因此,SVM 分类器的输入将是大小为 128 的向量。然后,您可以编译一些属于单个人(在您的情况下为 3 个)面部的向量,并将其作为一个类拟合到 SVM。然后,您可以对不同的面孔(类)执行相同的操作。

      然后,在预测人脸时,只需输入新向量并运行

      svm.predict([..])
      

      我的项目有一个类似的用例,但我使用 Facenet 作为特征提取器。完美运行。

      【讨论】:

      • 你能分享一个关于如何做到这一点的教程......我的意思是步骤?因为我不了解 SVM。任何帮助将不胜感激!
      • 请查看此详细指南以供参考:machinelearningmastery.com/…
      猜你喜欢
      • 2021-03-09
      • 2020-04-24
      • 2013-12-08
      • 2020-12-16
      • 1970-01-01
      • 2019-11-20
      • 2019-10-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多