人脸匹配(face matching)

2023-05-16

以下是人脸匹配(face matching)的实验报告,实验中采用ldlib,facenet,arcface三种算法,简单对比了三种算法的效果,源代码见文章末尾

一.问题分析

1.问题描述

人脸识别是基于人的脸部特征信息进行身份识别的一种生物识别技术。人脸匹配就是给定任意两张人脸图像,判断这两张人脸图像中的人脸是否属于同一个人。

在人脸匹配中存在着诸多难点,比如,人脸表情复杂;人脸随年龄而改变;人脸有易变化的附加物;人脸特征遮掩;人脸图像畸变。

 

2.数据集分析

实验中给出的数据集是收集全班人的人脸照片,每个人两张照片,一共有80张照片。对这80张照片进行随机分配为40组图片,每组图片包含任意两个人的人脸照片。

用实验中设计的人脸匹配算法来判断这40组图片对是否属于同一张人脸。以此来判断算法的优劣性。

3.现有方法

现有的进行人脸匹配的方式有很多种,大概都可以分为三个步骤,首先就是识别出每张图像中的人脸,找到人脸所在的位置,接着对人脸提取特征,最后对比不同人脸的特征之间的距离,如果距离小于某个阈值则认为是同一张人脸,否则就认为是不同的人脸。

实验中我们尝试了dlib,facenet,arcface三种方式,经过测试发现arcface的效果最好,所以实验中最后选择了arcface作为人脸匹配的算法。

 

 

二.方法总结

2.1 dlib

Dlib是一个机器学习库,里面集成了许多优质的算法,其中就包括人脸识别,特征提取等算法。利用dlib进行人脸匹配的算法流程图如下图2.1所示。

                                                                       图2.1 dlib人脸匹配流程图

从图2.1可以看出整个步骤也是分为三步:

(1)识别人脸,主要原理就是提取图片的HOG特征,SVM用于对特征进行分类找到最后的人脸位置。

                                                                                      图2.2 dlib检测人脸图

(2)提取人脸特征点。在检测出人脸之后,在人脸的区域中提取68个关键点作为特征点。

                                                                               图2.3 dlib提取人脸关键点图

(3)提取特征向量。在得到每张人脸的特征点之后提取相应的特征向量,这里得到的一个128维的特征向量。

(4)计算特征向量之间的距离。在得到了每张图片人脸的特征向量之后,计算特征向量之间的欧式距离,如果该距离小于指定的阈值则认为是同一张人脸,否则就认为是不同的人脸。经过测试实验中设置的阈值为0.42。

 

2.2 facenet

Facenet的基本思想就是利用相同人脸在不同角度等姿态的照片下有高内聚性,不同人脸有低耦合性,提出使用 cnn + triplet mining 方法。

利用facenet进行人脸匹配的步骤如下:

(1)用MTCCN进行人脸检测。MTCNN利用三个CNN级联的方式对人脸识别任务实现了从粗到细的处理。主要结构图如下图2.4所示。

                                                                                  图2.4 MTCNN结构图

主要是先通过P-Net来生成若干候选框,接着用bounding box regression来矫正,用NMS来抑制重叠框。用R-Net进一步筛选掉那些错误的box。O-Net用来输出最终的人脸框还有特征点的位置。

(2)利用facenet输出人脸的特征向量。Facenet通过将人脸映射到一个多维空间,然后用triplets的loss做到将相同人脸的距离拉到尽可能小,不同人脸之间的空间距离尽可能的大。主要流程图如下图2.5所示。

                                                                            图2.5 facenet算法流程图

图2.5中的Batch是MTCNN检测出来的人脸图片。接着经过facenet的网络结构,一般采用Googlenet,将网络输出用L2进行归一化,得到人脸的特征表示,最后用三元组即Triplet Loss计算损失函数。

                                                                                    图2.6 Triplet原理图

如图2.6所示,facenet就是将人脸先embedding到一个d维度的欧几里得空间 ,在该向量空间中,希望将单个图像的和该个体的其他图像距离近,和其他个体的图像的距离远。即最小化如下公式的损失函数

  

(3)计算特征向量之间的距离。在用facenet得到人脸的特征向量之后,用欧式距离计算出特征向量之间的距离,如果距离小于阈值则认为值属于同一张人脸,否则就不是。

2.3 arcface

Arcface的主要思想就是使用角边距最大化类间距离、最小化类内距离。使用arc-cosine函数计算特征与目标权重间的角度,然后,为目标角度添加一个角余量惩罚m,通过cosine函数重新获得目标logit最后,使用固定的特征范数重新确定所有的逻辑,随后完全按照softmax loss处理。主要流程如图2.7所示。

 

                                                                                图2.7 archface原理图

Arcface主要是提出一种新的用于人脸识别的损失函数:additive angular margin loss,直接在角度空间(angular space)中最大化分类界限。

L1为基于softmax的损失函数。

 

进行权重归一化后,使L1 loss只跟特征向量和权重之间的角度有关。


最后添加角余量惩罚m,获得ArcFace损失。

 


Arcface用来做人脸匹配的步骤基本和上述的facenet类似,步骤如下:

 

(1)利用MTCNN检测出人脸

(2)利用Arcface输出人脸特征向量

(3)比较特征向量之间的距离,小于指定阈值则认为是同一张人脸。否则就不是。

 

 

三.实验

由于在做实验的时候,测试图片没有公开,我们仅仅收集了本小组的图片,小组一共六个人,每个人两张图片,一共12张图片。

我们将这12张图片两两进行人脸匹配,从而分析算法的效果。下图是使用三种算法得到的实验结果图。其中dlib,facenet,arcface设置的距离阈值分别是0.4,0.75,1.1,阈值的设置为经验值。

                                                                                     图3.1 实验结果图

图3.1的每个矩阵是12*12,第i行j列的值表示第i张图像与第j张图片进行人俩匹配的结果,如果值为1表示算法认为是同一张人脸,值为0表示不是同一张人脸。从图3.1可以看出在dlib算法检测结果中用红圈框处的区域位置,即(11,12),(12,11)应该是同一张人脸,但是dlib却误检测为不同的人脸。在facenet的实验结果中,同样可以看到在红圈框处的位置(1,5),(1,6),(2,5),(5,1),(5,2),(6,1)处,误将不同的人脸认为是同一张人脸。只有arcface做到了100%的准确率,证明了arcface的优越性。

 

 

四.总结

在这次人脸匹配的实验中,我们一共尝试了三种不同的人脸匹配的算法,进一步对比了不同算法的效果,从而选出效果最好的算法用于最终的人脸匹配。实验中也发现对于最后人脸相似性的阈值设置十分依赖于经验,在不同的数据集上面的阈值都不尽相同。

在计算人脸特征向量之间的距离的时候,实验中都是采用的欧式距离,没有深究其他距离的计算方式,可能其他的方式会带来更好的效果。另外实验中采用的测试数据集非常少,这样导致最后得到的实验结果可能不具有很强的说服力,后续需要进一步进行测试。

 

源代码

dlib:

要求的文件结构

#dlib人脸匹配源码
import sys
import dlib
import numpy as np
import cv2
import os
import glob

def compare_feature(a, b):
    diff = 0
    for i in range(len(a)):
        diff += (a[i] - b[i])**2
    diff = np.sqrt(diff)
   # print(diff)
    # return float(diff)
    if (diff < 0.42): #阈值设置为0.42
        return True
    else:
        return False
    #     print("It's the same person")
    # else:
    #     print("It's not the same person")

def extract_feature(img_path):
    img = cv2.imread(img_path, cv2.IMREAD_COLOR)
    b, g, r = cv2.split(img)
    img2 = cv2.merge([r, g, b])
    dets = detector(img, 1)  # 人脸标定
    for index, face in enumerate(dets): #一张图片出现多张人脸?
        # face = face.rect
        # print('face {}; left {}; top {}; right {}; bottom {}'.format(index, face.left(), face.top(), face.right(), face.bottom()))
        cv2.rectangle(img, (face.left(), face.top()), (face.right(), face.bottom()), (0, 255, 0), 3)
        shape = shape_predictor(img2, face)   # 提取68个特征点
        for i, pt in enumerate(shape.parts()):
            pt_pos = (pt.x, pt.y)
            cv2.circle(img, pt_pos, 5, (255, 0, 0), 1)

        # cv2.imwrite(img_path+str(index)+'.jpg', img)
        # save_path = os.path.join(img_path[:img_path.rfind('/')], 'result/')
        save_path = os.path.join('./result/', img_path[2:img_path.rfind('/')])
        if not os.path.exists(save_path):
           os.makedirs(save_path)
        cv2.imwrite(os.path.join(save_path,img_path[img_path.rfind('/')+1:]), img)
        face_descriptor = face_rec_model.compute_face_descriptor(img2, shape)   # 计算人脸的128维的向量

    return face_descriptor

predictor_path = "shape_predictor_68_face_landmarks.dat"
face_rec_model_path = "dlib_face_recognition_resnet_model_v1.dat"
detector = dlib.get_frontal_face_detector() #检测人脸
# detector = dlib.cnn_face_detection_model_v1('mmod_human_face_detector.dat') #CNN方式,用的时候需要加face = face.rect
shape_predictor = dlib.shape_predictor(predictor_path) #提取关键点
face_rec_model = dlib.face_recognition_model_v1(face_rec_model_path) #根据关键点输出人脸特征向量

root_path = './6th'
root_path_dir = sorted(list(map(int, os.listdir(root_path))))
root_path_dir = list(map(str, root_path_dir))
i = 1
result = open('result.txt', 'w')
for imgs_path in root_path_dir:
    img_pair_path = sorted(glob.glob(os.path.join(root_path,imgs_path, "*")))
    img1_vector = extract_feature(img_pair_path[0])
    img2_vector = extract_feature(img_pair_path[1])
    print(imgs_path, end=':')
    r = compare_feature(img1_vector,img2_vector)
    print(r)
    if r:
        result.write(str(1)+'\n') #将结果输入到文件中
    else:
        result.write('0'+'\n')

facenet:https://github.com/davidsandberg/facenet 直接运行其中的https://github.com/davidsandberg/facenet/blob/master/src/compare.py即可

arcface:https://github.com/deepinsight/insightface

 

参考:

https://blog.csdn.net/tinyzhao/article/details/53236191

https://zhuanlan.zhihu.com/p/76541084

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

人脸匹配(face matching) 的相关文章

  • Horspool (String Matching)

    Description of Horspool Assumation text string the string where we want to locate the pattern string n the length of the
  • INSTALL_FAILED_NO_MATCHING_ABIS 的解决办法

    在Android模拟器上安装apk的时候出现 xfeff xfeff INSTALL FAILED NO MATCHING ABIS 这个错误提示的解决办法 是由于使用了native libraries 该native libraries
  • H264码流RTP封装方式详解:rfc3984

    264码流RTP封装方式详解 文章目录 H264码流RTP封装方式详解 1 H264基本概念 2 NALU Header介绍 3 RTP封装H264码流 3 1 单一NALU模式 3 2 组合帧封装模式 3 3 分片封装模式 4 代码解析
  • face++人脸识别初探

    依然是实训第一周 由于选定了face 作为api 我摸索了一下face 的人脸识别api的情况 下面我来为大家分析一下face api的情况 face 人脸识别有 1 人脸检测 2 人脸别对 3 人脸搜索 4 人脸关键点 5 人脸属性 6
  • 关于求职及面试的一些小技巧

    关于面试的一些小窍门 内容仅代表我个人观点 欢迎批评指正 之前已经分享过怎么样做一份看起来还算不错的简历了 老司机的分享 写简历的过程中 都有哪些坑 点开即可查看 1 关于面试时机 对相当一部分的部门需求者而言 如果求职者不是绝对的让部门需
  • R 返回行名称的部分匹配

    我遇到了以下问题 vec lt c a11 b21 c31 df lt data frame a c 0 0 0 b c 1 1 1 row names vec df a returns df a a b a11 0 1 However a
  • Microsoft Face API 中“解码错误,图像格式不受支持”

    我正在尝试使用 Microsoft Face API 为此 我有 Microsoft 提供的以下代码作为示例 在本页末尾 https dev projectoxford ai docs services 563879b61984550e40
  • PowerShell 字符串匹配和管道字符

    我在 PowerShell 中匹配包含管道字符的字符串时遇到困难 在以下情况下 Match 不应该返回 true gt Debug x86 match Debug x128 True 我尝试转义匹配参数管道字符 但这不会改变意外结果 例如
  • 通过 OpenCV 将 MTCNN 与网络摄像头结合使用

    我希望能够使用网络摄像头并利用 MTCNN 作为主要面部检测器 正如可以使用 Haar Cascades 一样 我想使用 MTCNN 在我的网络摄像头上查找人脸 该视频是关于打破 MTCNN 的 但仍然提供了我的目标的见解 https ww
  • 没有匹配的函数用于调用构造函数(c ++)[重复]

    这个问题在这里已经有答案了 EDIT 好吧 我又花了几个小时阅读了一些内容 我想我终于更好地理解了 C OOP 至少是基础知识 我决定一次重写整个程序和代码并进行更多测试 我想这次我缩小了错误的范围 命名风暴 h include
  • Java:匹配字符串中的短语

    我在数据库和输入字符串中有一个短语列表 短语可能由一个或多个单词组成 我需要找出哪些短语出现在输入字符串中 在Java中是否有一种有效的方法来执行这种匹配 一个快速的破解方法是 基于组合短语构建正则表达式 构造一个集合 列出迄今为止尚未匹配
  • 具有重叠时隙的会议调度算法

    我想做类似的事情预约调度算法 N个人 N个忙闲时段 约束满足 https stackoverflow com questions 11143439 appointment scheduling algorithm n people with
  • 允许共享起始/结束顶点的定向最大加权二分匹配

    令 G U u V E 为加权有向二分图 即 U 和 V 是二分图的两组节点 E 包含从 U 到 V 或从 V 到 U 的有向加权边 这是一个例子 在这种情况下 U A B C V D E F E A gt E 7 B gt D 1 C g
  • 我想在列之间匹配相似的单词

    1 0 2 0 3 0 loud complaint problems pain stress confused dull pain stress 这是我的数据集 我想重新组织行 以便如果每列中出现一个单词 它就会转移到相应的行 例如 1
  • Lucene 通配符匹配在化学符号上失败(?)

    使用 Hibernate 搜索注释 大部分只是 Field index Index TOKENIZED 我已经索引了一些与我的名为 Compound 的持久类相关的字段 我已经使用以下命令对所有索引字段设置了文本搜索MultiFieldQu
  • 匹配完全限定类名的正则表达式

    在文本中匹配完全限定的 Java 类名的最佳方式是什么 例子 java lang Reflect java util ArrayList org hibernate Hibernate Java 完全限定类名 假设为 N 具有以下结构 N
  • 模糊匹配两个数据框

    我想合并两个数据框 df1 和 df2 df1 lt tibble x c FIDELITY FREEDOM 2015 FUND VANGUARD WELLESLEY INCOME FUND y c 1 2 df2 lt tibble x
  • 匹配两个数据集中的 ID

    我有两组数据 包括前数据和后数据 受访者拥有唯一的 ID 我想创建一个子集 其中仅包含对两项调查做出回应的受访者 数据集示例 pre data lt data frame ID c 1 10 Y sample c yes no 10 rep
  • 如何为 r 中两个数据帧之间的匹配观察值分配相同的唯一 ID?

    当我有两个 或更多 数据框并希望为每个数据集中和跨两个数据集的每个匹配观察分配唯一的 ID 时 我有一个实际问题 例如 1 Create dataframe df1 a1 lt c 1 1 1 1 2 2 2 2 1 1 b1 lt c 1
  • 在 R 中匹配多个日期值

    我有以下数据框 DF 描述在特定日期从事项目的人员 ID ProjectName StartDate 1 Health 3 1 06 18 20 2 Education 2 1 07 15 30 1 Education 5 3 09 9 0

随机推荐

  • 配置yum源遇到的问题

    yun配置文件 ambari name 61 local iso baseurl 61 file home redhat iso 填写挂载镜像的位置 enable 61 1 gpgcheck 61 1 gpg签名校验 默认关闭 gpgkey
  • 【Android安全】Android settings命令

    Android 中有一个可执行文件settings xff0c 可以使得调试变得方便 settings用法 xff1a device span class token operator span name span class token
  • PyCharm,Terminal 常用快捷键

    转自 xff1a https blog csdn net sinat 41668302 article details 106211007 PyCharm xff0c Terminal 常用快捷键 enter Terminal 快捷键 功能
  • 1175 最大半连通子图(强连通分量)

    1 问题描述 xff1a 一个有向图 G 61 V xff0c E 称为半连通的 Semi Connected xff0c 如果满足 xff1a u xff0c v V xff0c 满足 u v 或 v u xff0c 即对于图中任意两点
  • 呆呆和你谈谈入职CVTE一个月的感受

    呆呆和你谈谈入职CVTE一个月的感受 你盼世界 xff0c 我盼望你无bug Hello 大家好 xff01 我是霖呆呆 xff01 啊啊啊啊啊 至6 18日入职新公司CVTE已经一个多月了 xff0c 在 你盼世界 xff0c 我盼望你无
  • fastboot刷boot命令

    fastboot flash boot b rooted boot路径 fastboot flash boot a rooted boot路径
  • 剑指 Offer 03. 数组中重复的数字--详解

    找出数组中重复的数字 在一个长度为 n 的数组 nums 里的所有数字都在 0 xff5e n 1 的范围内 数组中某些数字是重复的 xff0c 但不知道有几个数字重复了 xff0c 也不知道每个数字重复了几次 请找出数组中任意一个重复的数
  • 虚拟机和win主机不能互相ping通,不能ping通外网,全方位解析

    1 确认虚拟机处于桥接状态 xff1a xff08 虚拟机 gt 设置 gt 网络适配器 xff09 2 桥接是虚拟机的虚拟网卡与主机的网卡通过虚拟网桥进行连接 xff0c 因此 主机 虚拟机的子网掩码 网关 dns必须保持一直 ubunt
  • Android Cordova 正常安卓项目封装成插件的流程记录

    Android Cordova 正常安卓项目封装成插件的流程记录 背景 xff1a 混合式开发cordova使用Android原生插件 封装流程 xff1a 1 gradle的封装 xff1a a xff1a 需要在插件中先创建一个 gra
  • Ubuntu18.04配置ssh服务以实现远程连接

    1 连接环境 虚拟机 xff1a Ubuntu18 04 连接工具 xff1a SecureCRT 2 配置虚拟机的SSH服务 sudo apt get update sudo apt get install openssh client
  • RxJava2(五)线程调度器Scheduler

    线程调度器Scheduler RxJava是一个为异步编程而实现的库 xff0c 但异步也存在线程安全问题 xff0c 比如 xff0c 那些操作需要在前台线程 xff0c 那些操作又需要在后台线程等等 而Scheduler就是这样一个线程
  • 按键消抖的三种方案

    首先 xff0c 做两个假定 xff0c 以方便后面的描述 xff1a 假定按键的默认状态为0 xff0c 被按下后为1假定按键抖动时长小于20ms xff0c 也即使用20ms的消抖时间 方案1 xff1a 在按键电平稳定的情况下 xff
  • D1_1-10的阶乘求和:1!+2!+3!+......+9!+10!

    首先我们要清楚10 xff01 是什么 阶乘 xff0c 符号为n 是指从1开始依次相乘直到n eg xff1a 10 xff01 61 1 2 3 4 5 6 7 8 9 10 话不多说 xff0c 先放代码为敬 xff1a span c
  • ASK、FSK、PSK信号及其频谱

    代码 xff1a https github com LHesperus signal processing tree master Modulated 20signal 2ASK信号及其频谱 4ASK信号及其频谱 FSK信号及其频谱 4FS
  • 2022-9-20----Android----User版 打开串口抓开机日志

    分析设备无法开机或开机出现异常 xff0c 得用串口抓取开机log xff0c 但是user版默认是关闭串口的 xff0c 所以你得去 lk 把串口打开 Android 5 6的修改方法 xff1a diff span class toke
  • C# RabbitMQ(一)介绍

    什么是消息队列 顾名思义 xff0c 这是一个消息按顺序排列的集合 xff0c 遵循的是先进先出原则 xff0c 队列中存放的是Message 消息队列中间件是分布式系统中重要的组件 xff0c 主要解决应用耦合 异步消息 流量削锋等问题
  • IDEI打开主动引入功能,并排除一些包的自动引入

    欧尅了
  • dubbo

    dubbo通过官网学习 http dubbo apache org en us 一 陌生的名词解释 xff1a SPI xff1a service provider interface 服务提供机制 Hessian 是一个轻量级的RPC框架
  • 2020-09-04

    构造器 private SystemStatus try this sysStatus 61 0 transManager 61 new TransactionManager try DBTableSQL dbTable 61 new DB
  • 人脸匹配(face matching)

    以下是人脸匹配 xff08 face matching xff09 的实验报告 xff0c 实验中采用ldlib xff0c facenet xff0c arcface三种算法 xff0c 简单对比了三种算法的效果 xff0c 源代码见文章