对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的,是人的逃避方式,是对大众理想的懦弱回归,是随波逐流,是对内心的恐惧 ——赫尔曼·黑塞《德米安》
人脸识别基本原理:
人脸检测
:人脸检测是指在图像或视频中自动检测出人脸的位置,并将其框出来的过程。该技术通常使用分类器或神经网络模型来检测面部特征、形状、颜色等,从而确定人脸的位置。
人脸识别
:人脸识别是指在已经检测到人脸的基础上,通过对其特征进行比较和匹配,将其与先前存储的一组人脸数据集中的个体进行识别和辨认的过程。这种技术通常使用各种算法(如 PCA、LBP、CNN 等)来提取人脸特征,并使用相似性计算方法来比较和匹配人脸。
DeepFace 是 Python 上最轻量级的人脸识别和面部属性分析库。开源的 DeepFace 库包括所有用于人脸识别的前沿 AI 模型,并自动处理后台面部识别的所有程序。
安装很方便,更过内容小伙伴可以参考项目文档,https://github.com/serengil/deepface
# pip install deepface==0.0.79
在识别时,需要下载对应模型的权重文件,有些是特征点获取的模型,需要科学上网,如果无法下载,可以到有网的机器下载,项目中的 单元测试中有一些测试脚本,执行的时候会下载,
rst = DeepFace.extract_faces(
img_path=image,
target_size=(224, 224),
detector_backend="mtcnn",
enforce_detection=True,
align=True,
grayscale=False)
verification = DeepFace.verify(img1_path = "img1.jpg", img2_path = "img2.jpg")
recognition = DeepFace.find(img_path = "img.jpg", db_path = “C:/facial_db")
analysis = DeepFace.analyze(img_path = "img.jpg", actions = ["age", "gender", "emotion", "race"]) print(analysis)
DeepFace.stream(db_path = “C:/facial_db”)
人脸检测和对齐
是面部识别管道非常重要的阶段。谷歌表示,仅面部对齐就可以将面部识别准确率提高0.76%
。这里的检测即指这图片中找到人脸的位置,对齐即把人脸通过类似透视变换的操作一样。 deepface
支持的检测器如下:
OpenCV
: 与其他人脸检测器相比,OpenCV 是最轻量级的人脸检测器。流行的图像处理工具使用不基于深度学习技术的 haar-cascade 算法。这就是为什么它很快,但它的性能相对较低。为了使 OpenCV 正常工作,需要正面图像。此外,它的眼睛检测性能一般。这会导致对齐问题。请注意,DeepFace 中的默认检测器是 OpenCV。 使用 OpenCV 进行人脸检测Dlib
: 该检测器在后台使用 hog
算法。因此,与 OpenCV 类似,它不是基于深度学习的。尽管如此,它的检测和对齐分数相对较高。SSD
: SSD 代表 单次检测器;它是一种流行的基于深度学习的检测器。SSD 的性能可与 OpenCV 相媲美。但是,SSD 不支持面部特征点,并且依赖于 OpenCV 的眼睛检测模块来对齐。尽管其检测性能很高,但对准分数仅为平均水平。MTCNN
: MTCNN 这是一个基于深度学习的人脸检测器,它带有面部特征点。这就是为什么 MTCNN 的检测和对齐得分都很高的原因。但是,它比 OpenCV,SSD 和 Dlib 慢。 MTCNN 是一种多任务级联卷积神经网络的人脸检测算法,能够同时实现人脸检测、关键点定位和人脸对齐
等功能。其对于大尺寸人脸的检测效果较好
,并且相对于 RetinaFace 的模型规模较小。RetinaFace
: RetinaFace 被公认为最先进的基于深度学习的人脸检测模型。它在野外的表现具有挑战性。但是,它需要很高的计算能力。这就是为什么与其他人脸检测器相比,RetinaFace 是速度最慢的人脸检测器
。RetinaFace 是一种基于卷积神经网络的人脸检测算法,具有高精度的特点。其在 WIDER FACE 和 COCO 数据集上的表现比 MTCNN 更好,尤其是对于小尺寸人脸的检测效果更佳
。detectors = ["opencv", "ssd", "mtcnn", "dlib", "retinaface"]
应该使用哪种人脸检测器? 需要根据实际情况分析
高置信度
,考虑使用 RetinaFace 或 MTCNN
高速
,清洗一部分没有人脸的照片,那么,可以使用 OpenCV 或 SSD
人脸识别模型,即通过对人脸库的数据进行特征提取,然后提取需要识别的图片的特征,两者通过计算生成一个相似度值,这个值的指定阈值内,即确定为同一个人。
VGG-Face
: VGG 代表 视觉几何组。VGG 神经网络(VGGNet)是基于深度卷积神经网络最常用的图像识别模型类型之一。VGG 人脸识别模型在流行的野外标记人脸 (LFW) 数据集上实现了 97.78%
的准确率。Facenet
: 该模型由谷歌的研究人员开发。FaceNet 被认为是通过深度学习进行人脸检测和识别的最先进的模型。 FaceNet 的主要优点是其高效率和高性能,据报道,它在 LFW 数据集上达到了99.63%
的准确率。OpenFace
:这个人脸识别模型是由卡内基梅隆大学的研究人员建立的。因此,OpenFace 在很大程度上受到 FaceNet 项目的启发,但这更轻量级,其许可证类型更灵活,OpenFace 在 LFW 数据集上实现了93.80%
的准确率。DeepFace
: 这种人脸识别模型是由 Facebook 的研究人员开发的。Facebook DeepFace 算法是在属于 4000 万张面孔的标记数据集上进行训练的,这是发布时最大的面部数据集。该方法基于具有九层
的深度神经网络。 Facebook 模型在 LFW 数据集基准测试上实现了97.35%(+/- 0.25%)
的准确率。DeepID
: DeepID 人脸验证算法基于深度学习进行人脸识别。它是首批使用卷积神经网络
并在人脸识别任务上实现优于人类性能的模型之一。Deep-ID 是由香港中文大学的研究人员引入的。 基于 DeepID 人脸识别的系统是第一批在这项任务中超越人类表现的系统。例如,DeepID2 在野外标记面孔(LFW)数据集上实现了99.15%
。Dlib
: Dlib 人脸识别模型将自己命名为“世界上最简单的 python 面部识别 API”。 Dlib 的人脸识别工具将人脸图像映射到 128 维矢量空间,其中同一个人的图像彼此靠近,而不同人的图像相距甚远。因此,dlib 通过将人脸映射到 128d 空间,然后检查它们的欧几里得距离是否足够小来执行人脸识别。 dlib 模型的距离阈值为 0.6,在标准 LFW 人脸识别基准上实现了 99.38%
的准确率。ArcFace
: 这是模型组合中的最新型号。它的联合设计师是伦敦帝国理工学院和 InsightFace 的研究人员。ArcFace 模型在 LFW 数据集上的准确度达到 99.40%
。SFace
: 是一种人脸识别的预训练模型,它是基于深度神经网络的人脸识别模型。SFace 模型是由中国科学院自动化研究所的研究人员开发的,它在多个人脸识别竞赛中表现出色。SFace 模型采用了一种名为“中心损失”的训练方法,可以使得模型在人脸识别任务中更加准确。models=["VGG-Face", "Facenet", "Facenet512", "OpenFace", "DeepFace", "DeepID", "ArcFace", "Dlib","SFace"]
经过测试发现,Deepface 中,使用默认阈值,ArcFace
,和 SFace
的识别度要好于其他的模型。当然,对应的阈值可以通过修改源码的方式调整,这里我们已 cosine
为例
对应的文件位置为:Python\Python310\site-packages\deepface\commons\distance.py
,注释代码为默认的原来阈值
......
def findThreshold(model_name, distance_metric):
base_threshold = {"cosine": 0.40, "euclidean": 0.55, "euclidean_l2": 0.75}
thresholds = {
"VGG-Face": {"cosine": 0.40, "euclidean": 0.60, "euclidean_l2": 0.86},
"Facenet": {"cosine": 0.40, "euclidean": 10, "euclidean_l2": 0.80},
"Facenet512": {"cosine": 0.30, "euclidean": 23.56, "euclidean_l2": 1.04},
# "ArcFace": {"cosine": 0.68, "euclidean": 4.15, "euclidean_l2": 1.13},
"ArcFace": {"cosine": 0.45, "euclidean": 4.15, "euclidean_l2": 1.13},
"Dlib": {"cosine": 0.07, "euclidean": 0.6, "euclidean_l2": 0.4},
# "SFace": {"cosine": 0.593, "euclidean": 10.734, "euclidean_l2": 1.055},
"SFace": {"cosine": 0.60, "euclidean": 10.734, "euclidean_l2": 1.055},
"OpenFace": {"cosine": 0.10, "euclidean": 0.55, "euclidean_l2": 0.55},
"DeepFace": {"cosine": 0.23, "euclidean": 64, "euclidean_l2": 0.64},
"DeepID": {"cosine": 0.015, "euclidean": 45, "euclidean_l2": 0.17},
}
threshold = thresholds.get(model_name, base_threshold).get(distance_metric, 0.4)
return threshold
.......
在实际测试中发现,deepface 对 GPU 的利用很低,只是使用了显存,在同等情况下,还不如 CPU 并行跑的快。
实际使用中,如果采集的照片质量太低,考虑对识别数据进行清洗,然后在和人脸库比对,比如,检测人脸大小过滤,头部姿态过滤,置信度过滤等方式,同时可以调整阈值,这里需要说明的是,deepface 的 余弦相似度,和其他的人脸识别模型相反的,在取值时,用 1 减了,所以 deepface 的余弦值时越小越好,而且其他的人脸识别是越大越好。
可以做源码的这个位置看到
.......
def findCosineDistance(source_representation, test_representation):
a = np.matmul(np.transpose(source_representation), test_representation)
b = np.sum(np.multiply(source_representation, source_representation))
c = np.sum(np.multiply(test_representation, test_representation))
return 1 - (a / (np.sqrt(b) * np.sqrt(c)))
........
简单调用
from deepface import DeepFace
# 人脸识别
models=["VGG-Face", "Facenet", "Facenet512", "OpenFace", "DeepFace", "DeepID", "ArcFace", "Dlib"]
# 人脸检测
detectors = ["opencv", "ssd", "mtcnn", "dlib", "retinaface"]
# 教室人脸识别
verification = DeepFace.verify(img1_path = "hg1.png", img2_path = "hg2.png",model_name=models[6],detector_backend = detectors[4] )
print(verification)
这里之前测试,所以做了一个,deepface 环境镜像 ,涉及 deepface API 环境, deepface 部分 models(*.h5) 权重文件和检测器,环境有问题小伙伴可以直接用
docker pull liruilong/deepface_and_deepface_models
verify 方法
"""
@Time : 2023/06/13 00:34:17
@Author : [email protected]
@Version : 1.0
@Desc : 人脸验证:用于验证图像对是否为同一人或不同人,验证函数将面部图像表示为向量,然后计算这些向量之间的相似度。
同一人图像的向量应具有更高的相似度(或更小的距离)比不同人的向量。
Args:
+ img1_path (str): 第一张图像的路径
+ img2_path (str): 第二张图像的路径
+ model_name (str): 要使用的人脸识别模型的名称(默认为“VGG-Face”)
+ detector_backend (str): 要使用的人脸检测后端(默认为“opencv”)
+ distance_metric (str): 用于比较面部嵌入的距离度量(默认为“cosine”)
+ enforce_detection (bool): 是否在图像中未检测到人脸时引发异常(默认为True)
+ align (bool): 是否在生成嵌入之前执行面部对齐(默认为True)
+ normalization (str): 用于预处理图像的归一化技术(默认为“base”)
Returns:
+ verified(核实):True
+ distance(距离):0.4439834803806296
+ threshold(阈值):0.593
+ model:SFace
+ detector_backend:mtcnn
+ similarity_metric(相似性指标):cosine
+ facial_areas(人脸位置):{'img1': {'x': 0, 'y': 0, 'w': 200, 'h': 255}, 'img2': {'x': 2, 'y': 13, 'w': 194, 'h': 231}}
+ time:1.95
void
"""
dfs = DeepFace.verify(
img1_path="W:\\python_code\\deepface\\temp\\cf\\cf_6dd3a0638cf4f4006aa1f455cac65577d.jpg.png",
img2_path ="W:\\python_code\\deepface\\temp\\cf\\cf_8a96787835b5d4677a56ad6db0c610958.jpg.png",
model_name="SFace",
detector_backend="mtcnn",
enforce_detection=False)
find 方法
"""
@Time : 2023/05/21 02:35:51
@Author : [email protected]
@Version : 1.0
@Desc : DeepFace.find方法是DeepFace库中的一个方法,用于在人脸数据库中查找与给定人脸最相似的人脸。
Args:
- img_path:要查找的人脸图像路径、numpy数组(BGR)或base64编码的图像。
- db_path:人脸数据库路径。您应该在此文件夹中存储一些.jpg文件。
- model_name:人脸识别模型的名称,例如VGG-Face、Facenet、Facenet512、OpenFace、DeepFace、DeepID、Dlib、ArcFace、SFace。
- distance_metric:距离度量方法可以是cosine、euclidean或euclideanl2。
- enforce_detection 参数是一个布尔值,指定如果无法检测到人脸,则该函数是否应引发异常。如果不想得到异常并仍要运行该函数,则将其设置为False。这对于低分辨率图像可能很方便。
- detector_backend 参数指定要使用的人脸检测器后端,可以是opencv、retinaface、mtcnn、ssd、dlib或mediapipe。
- align 参数是一个布尔值,指定是否应对人脸进行对齐。
- normalization 参数指定要使用的归一化方法,可以是base VGGFace Facenet raw 等
- silent参数是一个布尔值,用于禁用一些日志记录和进度条。
Returns:
df: 返回一个满足指定阈值的 的一个 pandas 对象
"""
dfs = DeepFace.find(
img_path="huge_1.jpg",
db_path="W:\python_code\db",
model_name="DeepID",
distance_metric="cosine",
enforce_detection=True,
detector_backend="retinaface",
align=False,
normalization="ArcFace",
silent=False,
)
extract_faces 方法
"""
@Time : 2023/05/20 03:50:07
@Author : [email protected]
@Version : 1.0
@Desc : extract_faces 用于对图像进行特征分析,提取头像坐标,
在实际使用中,如果对精度有要求,可以通过 `confidence` 来对提取的人脸进行过滤,
Args:
extract_faces方法接受以下参数:
- img_path:要从中提取人脸的图像路径、numpy数组(BGR)或base64编码的图像。
- target_size:人脸图像的最终形状。将添加黑色像素以调整图像大小。
- detector_backend:人脸检测后端可以是 retinaface、mtcnn、opencv、ssd或dlib。
- enforce_detection:如果在提供的图像中无法检测到人脸,则该函数会引发异常。如果不想得到异常并仍要运行该函数,则将其设置为False。
- align:根据眼睛位置对齐。
- grayscale:以RGB或灰度提取人脸。
Returns:
返回一个包含人脸图像、人脸区域和置信度的字典列表。其中,
- face 键对应的值是提取的人脸图像
- facial_area 键对应的值是人脸在原始图像中的位置和大小
- confidence 键对应的值是人脸检测的置信度
"""
rst = DeepFace.extract_faces(
img_path=image,
target_size=(224, 224),
detector_backend="mtcnn",
enforce_detection=True,
align=True,
grayscale=False)
analyze 方法
"""
@Time : 2023/05/31 01:44:27
@Author : [email protected]
@Version : 1.0
@Desc : analyze 方法是 DeepFace 库中的一个函数,用于分析人脸属性,包括年龄、性别、情绪和种族。
在后台,分析函数构建卷积神经网络模型,以对输入图像中的人脸进行年龄、性别、情绪和种族分类。
Args:
- img_path:图像路径、numpy 数组(BGR)或 base64 编码的图像。如果源图像中有多个人脸,则结果将是出现在图像中的人脸数量大小的列表。
- actions: 参数是一个元组,其中默认值为 ('age', 'gender', 'emotion', 'race'),您可以删除其中的一些属性。
- enforce_detection :参数默认为 True,如果未检测到人脸,则函数会抛出异常。如果您不想得到异常,则可以将其设置为 False。这对于低分辨率图像可能很方便。
- detector_backend: 参数指定要使用的人脸检测器的后端,例如 OpenCV、RetinaFace、MTCNN 等。
- align: 参数是一个布尔值,表示是否根据眼睛位置进行对齐。
- silent :参数是一个布尔值,表示是否禁用(某些)日志消息。
Returns:
- "region":表示人脸在图像中的位置和大小。
- "age":表示人脸的年龄。
- "dominant_gender":表示人脸的主要性别。
- "gender":表示人脸的性别及其置信度。
- "dominant_emotion":表示人脸的主要情绪。
- "emotion":表示人脸的情绪及其置信度。
- "dominant_race":表示人脸的主要种族。
- "race":表示人脸的种族及其置信度。
"""
dfs = DeepFace.analyze("database\yz_W.jpg",detector_backend="retinaface")
不同识别模型测试的简单统计:
识别流程:
相同人脸库数据,相同识别数据集,不同识别模型统计:
模型名称 | 识别结果数 | 识别陌生人 | 识别总人数 | 识别错误 | 识别成功 | 识别成功率 |
---|---|---|---|---|---|---|
VGG-Face | ||||||
Facenet | 430 | 267 | 163 | 118 | 45 | 27% |
Facenet512 | 432 | 311 | 121 | 57 | 64 | 52% |
OpenFace | 434 | 3 | 431 | 3 | 0 | 0% |
DeepFace | 430 | 267 | 163 | 125 | 38 | 23% |
Dlib | 428 | 173 | 255 | 174 | 81 | 31% |
ArcFace | 430 | 255 | 175 | 62 | 113 | 65% |
SFace | 432 | 346 | 86 | 7 | 79 | 91% |
测试发现,当前的数据集,SFace
相对来说要好一点,整体上还是达不到期望。 主要是图片质量问题,当前检测识别属于小目标检测识别,如果是打卡或者门禁其他的大目标正脸识别,是OK的。
© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知,这是一个开源项目,如果你认可它,不要吝啬星星哦
https://viso.ai/computer-vision/deepface/
https://github.com/serengil/deepface
© 2018-2023 [email protected], All rights reserved. 保持署名-非商用-相同方式共享(CC BY-NC-SA 4.0)