Python deepface:让你的代码轻松地实现人脸识别功能

news/2024/11/13 10:50:41/文章来源:https://www.cnblogs.com/wan-ming-zhu/p/18354858

楔子

在 GitHub 上面发现了一个非常有趣的库,叫 deepface,简直是人间宝藏。这个库主要是做人脸识别和面部属性分析的,它集合了目前全球最顶尖的开源人脸识别算法,使用卷积神经网络(CNN)对图像进行特征提取,以实现高精度的人脸识别。实验表明,人类在面部识别任务上的准确率为 97.53%,而这些模型已经达到并超过了该准确率水平。

而该库提供非常丰富的功能,比如:

  • 人脸检测:deepface 可以在图像中检测出人脸的位置,为后续的人脸识别任务提供基础。
  • 人脸对齐:为了提高识别准确性,deepface 会将检测到的人脸进行对齐操作,消除姿态、光照和表情等因素对识别结果的影响。
  • 特征提取:deepface 使用卷积神经网络(CNN)对齐后的人脸图像进行特征提取,将人脸转换为高维特征向量。
  • 人脸识别:通过比较特征向量之间的相似度,deepface 可以识别出图像中的人脸是否属于同一个人。
  • 人脸验证:deepface 可以用于人脸验证任务,即判断给定的两张人脸图像是否属于同一个人。
  • 人脸搜索:deepface 可以在大型人脸数据库中搜索特定人物,通过比较特征向量找到与目标人物最相似的人脸。
  • 人脸聚类:deepface 可以对人脸进行聚类分析,将相似的人脸分组在一起,以便进行进一步的分析和处理。
  • 人脸属性识别:deepface 还可以识别人脸的一些属性,如性别、年龄、表情等。年龄模型得到 ±4.65 MAE;性别模型可达 97.44% 的准确率、96.29% 的准确率和 95.05% 的召回率。
  • 人脸跟踪:deepface 可以在视频序列中跟踪人脸,实现实时的人脸识别和分析。
  • 人脸年龄分析:deepface 可以估计图像中的人脸年纪。
  • 人脸表情识别:deepface 可以估计图像中的人脸表情。
  • 人种识别:deepface 可以识别出图像中的人脸属于什么人种。
  • 性别分析:deepface 可以识别出图像中的人脸是什么性别。

下面我们就来实际测试一个该库,看看它的效果如何?不过使用之前需要安装,直接 pip install deepface 即可。在安装的时候,会安装一些依赖,比如 OpenCV-Python、Tensorflow 等等,这些库比较大,所以要保证网络通畅,否则耗时会比较长。

对比两张图片上的人脸是否是同一个人

假设我们有两张图片,想判断两张图片上人是否为同一人,要怎么做呢?

当前有两个文件,分别是 yui1.png 和 yui2.png,来验证一下它们是否为同一个人。

from pprint import pprint
# deep 库的所有功能都在 deep.DeepFace 子模块下面
from deepface import DeepFace# 传入两张图片即可进行对比
result = DeepFace.verify("yui1.png", "yui2.png")
pprint(result)

现代人脸识别流程包括 5 个常见阶段:检测、对齐、归一化、表示和验证。deepface 会在后台处理好一切,我们不需要深入了解其背后的所有过程,只需要用一行代码即可调用它的验证、查找或分析函数。

然后是 DeepFace.verify 函数,它负责对两张图片上的人进行比对,判断是否为同一个人。该函数接收如下参数:

img1_path 和 img2_path:就是两张图片的路径,当然除了路径,还可以是 numpy 数组或 base64 字符串。verify 函数会将图像上的人脸部分表示为向量,然后计算相似度。如果其中一张图片出现了多张脸,比如 img1_path 里面有一张脸,但 img2_path 里面有三张脸,那么每一张脸都会进行比对,找到最相似的那一个。

model_name:deepface 已经集成了大量顶尖的人脸模型用于训练,比如:

"VGG-Face"、"OpenFace"、"Facenet"、"Facenet512"、"DeepFace"、"DeepID"
"Dlib"、"ArcFace"、"SFace"、"Emotion"、"Age"、"Gender"、"Race"

喜欢哪个就用哪个,但是模型需要下载,如果 deepface 检测到当前机器上没有指定的模型,那么会自动下载。所以当前第一次执行上面代码的时候,会下载 VGG-Face 模型(大小有好几百 M)。关于这些模型的区别,有兴趣可以自己了解一下,我们直接使用默认的即可。

detector_backend:检测器后端,负责提供人脸识别算法,因为 deepface 所使用的算法是由其它模块提供的,默认是 opencv。但除了 opencv 之外,还有其它选择。

"opencv", "retinaface", "mtcnn", "ssd", "dlib", "mediapipe"

这些人脸检测器之间的区别,还是很重要的,我们来解释一下。

  • "opencv":最轻量级的人脸检测器,使用不基于深度学习技术的 haar-cascade 算法,因此速度很快,但准确率较低。而为了使 OpenCV 正常工作,需要正面图像,如果脸侧了一下或者局部发生遮挡,准确率就会受到影响。此外也不擅长对眼睛的检测,容易导致对齐问题。目前 DeepFace 使用的默认检测器就是 OpenCV。
  • "dlib":该检测器在后台使用 hog 算法,与 OpenCV 类似,它也不是基于深度学习的,但它的检测和对齐分数相对较高。
  • "ssd":单次检测器,它是一种流行的基于深度学习的检测器,但性能可与 OpenCV 相媲美。只是 SSD 不支持面部特征点,并且依赖于 OpenCV 的眼睛检测模块来对齐,因此尽管其检测性能很高,但对准分数仅为平均水平。
  • "mtcnn":基于深度学习的人脸检测器,并带有面部特征点,所以它的检测和对齐得分都很高但是,但速度比 OpenCV,SSD 和 Dlib 慢。另外 MTCNN 是一种多任务级联卷积神经网络的人脸检测算法,能够同时实现人脸检测、关键点定位和人脸对齐等功能。其对于大尺寸人脸的检测效果较好,并且模型规模相对于 RetinaFace 的较小。
  • "retinaface":一种基于卷积神经网络的人脸检测算法,具有高精度的特点,被公认为是最先进的人脸检测算法,但需要很高的计算能力。相比 MTCNN,检测小尺寸人脸的效果更好。

因此如果你希望结果更加精确,那么使用 RetinaFace 或 MTCNN;如果希望检测速度更快,比如清洗一部分没有人脸的照片,那么可以使用 OpenCV 或 SSD。

distance_metric:距离(面部嵌入)度量方法,可以是 cosine、euclidean 或 euclidean_l2。

enforce_detection:如果没有检测到人脸时,是否引发异常,可以将其设置为 False。

align:是否执行面部对齐。

normalization:用于预处理图像的归一化技术。

from pprint import pprint
from deepface import DeepFaceresult = DeepFace.verify("yui1.png", "yui2.png")
pprint(result)
"""
{'detector_backend': 'opencv','distance': 0.2437701450344817,'facial_areas': {'img1': {'h': 115, 'w': 115, 'x': 73, 'y': 408},'img2': {'h': 327, 'w': 327, 'x': 159, 'y': 38}},'model': 'VGG-Face','similarity_metric': 'cosine','threshold': 0.4,'time': 1.25,'verified': True}
"""

返回的是一个字典,里面有两个重要字段:

  • verified:表示比对结果,即两张图片上的人是否为同一人。
  • facial_areas:由矩形表示的面部区域,x、y 表示矩形的左上顶点的坐标,w 和 h 分别表示矩形的宽度和高度。

我们修改一下代码,将人脸所在的矩形描绘出来。

from deepface import DeepFace
import cv2result = DeepFace.verify("yui1.png", "yui2.png",detector_backend="mtcnn")if not result["verified"]:print("人脸不一致")exit(0)# 获取人脸位置坐标
rect_img1 = result["facial_areas"]["img1"]
rect_img2 = result["facial_areas"]["img2"]# cv2 将图片读取进来之后,会得到一个三维数组
# 第一个维度表示图片的每一行,第二个维度表示图片的每一列,第三个维度就是图片的像素点
im1 = cv2.imread("yui1.png")
im2 = cv2.imread("yui2.png")
# 将人脸所在的矩形绘制出来,调用 cv2.rectangle 函数,该函数接收 5 个参数
# 分别是:原始图像、矩形的左上顶点、矩形的右下顶点、线条颜色、线条粗细
cv2.rectangle(im1, (rect_img1["x"], rect_img1["y"]),(rect_img1["x"] + rect_img1["w"], rect_img1["y"] + rect_img1["h"]),(0, 255, 0),  3
)
cv2.rectangle(im2, (rect_img2["x"], rect_img2["y"]),(rect_img2["x"] + rect_img2["w"], rect_img2["y"] + rect_img2["h"]),(255, 0, 0),  3
)
cv2.imshow("yui1.png", im1)
cv2.imshow("yui2.png", im2)
cv2.waitKey(0)

看一下结果:

你也可以将 detector_backend 换成别的,看看效果。首先换成 retinaface,结果也是正常的,但如果换成 opencv 结果就有问题了。换成 opencv 的话,也是提示人物是同一人,但第一张图片在返回面部所在矩形位置的时候出现了很大的问题,它返回的位置是人物手中的饮料所在的矩形区域。

这就有点离谱了,当然这只是我当前的结果是这样的,总之建议在识别的时候使用 MTCNN 和 Retinaface。

补充:图片的路径不能包含中文,或者说图片的路径必须是 ASCII 字符。

查找一张图片上的人脸所在的位置

现在有一张图片,如果让你绘制出人脸所在的矩形区域,要怎么做呢?

from deepface import DeepFace
import cv2im = cv2.imread(r"nigehaji.png")# 除了传递路径,也可以传一个 Numpy 数组
# 因为一张图片可能包含多张人脸,所以返回的是一个列表,列表的每个元素是字典
results = DeepFace.extract_faces(im,detector_backend="retinaface",enforce_detection=False)# 每个字典里面有如下字段:
# face: 一个 Numpy 数组,对应人脸的部分,大小可以通过 extract_faces 里面的 target_size 指定
#       此外 extract_faces 里面还有一个 grayscale 参数,表示 face 对应的图像是否为灰度图(默认 False)
# facial_area: 脸部所在的矩形区域
# confidence: 准确率,有多大把握确定该位置是人脸
for result in results:facial_area = result["facial_area"]cv2.rectangle(im, (facial_area["x"], facial_area["y"]),(facial_area["x"] + facial_area["w"], facial_area["y"] + facial_area["h"]),(0, 255, 0),  1)cv2.imshow("nigehaji.png", im)
cv2.waitKey(0)

图片上的人脸能否全部找出来呢?看一下结果。

功能还是比较强的,然后注意第一张图片,里面其实有 3 个人脸,我一开始都没看出来。

判断图片上的人脸是否在现有的数据集中

这也是一个比较常用的功能,比如你是一个公司老总,手下员工无数,但信息、照片都存储在你的系统中。但某天有个在逃犯人被摄像头排到了脸,警察问你这个人是不是你公司的员工,你要怎么做呢?很简单,直接拿这个犯人的照片和手下的员工的照片挨个进行比对即可。针对这个需求,你可以依次读取每个员工的图像,然后调用 DeepFace.verify 函数,但 deepface 提供了一个更简单的函数。

可以调用 DeepFace.find 函数,第一个参数就是图片,第二个参数是目录,里面包含了一系列的图片,会依次进行比对。然后里面的 silent 参数表示是否禁用一些日志记录和进度条,至于其它参数我们都说过了。

然后返回值是一个列表,列表元素是 pandas.DataFrame,里面包含如下字段:VGG-Face_cosine、identity(图片路径)、source_h、source_w、source_x、source_y。

需要注意的是,该函数执行完后,会在图片目录里面生成一个 pkl 文件。如果后续目录里面的图片发生了变化,那么需要先将 pkl 文件删除,然后才能执行,否则报错。

判断图片上人物的年龄、情绪等

deepface 还有一个很强的功能,就是它可以推测出人物的年龄、情绪以及人种等等。

from deepface import DeepFace
import cv2im = cv2.imread(r"C:\Users\86185\Desktop\moon\nigehaji.png")results = DeepFace.analyze(im,detector_backend="mtcnn",enforce_detection=False)

返回值是一个列表,列表里面是字典,每个字典对应一个人物的相关属性。

{ 'age': 28,  # 年龄'dominant_emotion': 'surprise',  # 表示人脸的主要情绪'dominant_gender': 'Woman',  # 人脸的主要性别'dominant_race': 'asian',  # 人脸的主要种族# 情绪有多种可能,所以 emotion 表示每种情绪的概率,而概率最高的会用 dominant_emotion 单独保存'emotion': {'angry': 0.005373688327381387,'disgust': 3.8977976402065906e-08,'fear': 20.51267772912979,'happy': 0.006043683970347047,'neutral': 4.0025247471930925e-05,'sad': 8.856896016595783e-06,'surprise': 79.47585582733154},# 每种性别的概率,概率最高会用 dominant_gender 单独保存'gender': {'Man': 2.714412286877632, 'Woman': 97.2855806350708},# 每个人种的概念,概率最高的会用 dominant_race 单独保存'race': {'asian': 63.200453710583076,'black': 0.10846455762324081,'indian': 0.21811715695960265,'latino hispanic': 3.3837137898036116,'middle eastern': 2.7975549726220947,'white': 30.291696208220493},# 位置'region': {'h': 47, 'w': 37, 'x': 143, 'y': 262}}

然后我们测试一下:

from deepface import DeepFace
import cv2im = cv2.imread(r"nigehaji.png")
# 图片有点小,为了有显示文字的空间,这里放大两倍
# 从这里也能看出,即便图片放大了,对识别依旧没有什么影响
im = cv2.resize(im, (1280, 960))results = DeepFace.analyze(im,detector_backend="mtcnn",enforce_detection=False)for result in results:age = result["age"]emotion = result["dominant_emotion"]gender = result["dominant_gender"]race = result["dominant_race"]region = result["region"]# 绘制人脸矩形cv2.rectangle(im, (region["x"], region["y"]),(region["x"] + region["w"], region["y"] + region["h"]),(255, 0, 0), 1)# 绘制文字,该函数接收 9 个参数# 参数一: 原始图像;参数二: 绘制的文字内容;参数三: 在什么位置开始绘制# 参数四: 字体;参数五: 文字大小,等于字体的基础大小乘上传入的值,比如传入 1.5 表示放大 1.5 倍# 参数六: 文字颜色;参数七: 文字的线条粗细;# 参数八: 线条类型,可取值为 cv2.LINE_4、cv2.LINE_8 分别表示 8 邻接连接线、4 邻接连接线#        但是更推荐使用 cv2.LINE_AA,它是反锯齿连接线,背后采用了高斯滤波cv2.putText(im,f"age: {age}, emotion: {emotion}, gender: {gender}, race: {race}",(region["x"] - 135, region["y"]),cv2.FONT_HERSHEY_SIMPLEX,0.6,(161, 16, 203),1,cv2.LINE_AA)cv2.imshow("...", im)
cv2.waitKey(0)

总的来说,识别效果还是不错的。然后 analyze 函数默认会分析年龄、性别、情绪、人种,如果你不想分析这么多,也可以通过参数指定。

def analyze(img_path,actions=("emotion", "age", "gender", "race"),enforce_detection=True,detector_backend="opencv",align=True,silent=False,
):

比如你只想分析年龄和情绪,那么就指定 actions 为 ("age", "emotion") 即可。

小结

以上就是该模块的用法,还是很有趣的。如果你对背后的原理感兴趣,那么可以尝试去了解一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/781749.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

翔云PHP身份证识别接口集成示例-护照识别-港澳台通行证识别

证件识别接口简介: 证件识别接口一般是指针对各类证件进行识别,其中包含但不限于身份证识别、护照识别、港澳台通行证识别、户口页识别、驾驶证识别、行驶证识别、台湾健保卡等,其​多应用于需要进行实名认证与证件信息登记的场景。 证件身份证识别接口返回结果示例如下:证…

雅思考试官方指南(第2版)配套资源 All In One

雅思考试官方指南(第2版)配套资源 All In One 听力 (音频) / 口语 (视频) International English Language Testing System (IELTS)雅思考试官方指南(第2版)配套资源 All In One听力 (音频) / 口语 (视频)https://mp.pxwhqr.cn/book.htm?id=236649&sign=1a6d5b&au…

Vue + ElementUI表格内实现图片点击放大效果的两种方式

方式一:使用el-popover弹出框 trigger属性用于设置何时触发Popover(弹出框)属性值有:hover、click、focus 和 manual style="cursor:pointer":当鼠标放上去时让img标签出现小手状态<el-table-column label="物品图片" header-align="center&quo…

2024纷享销客逆势再获7500万美元投资

8月12日,纷享销客宣布完成新一轮7500万美元的战略投资,由钟鼎资本领投,启明创投与建发新兴投资跟投,这是继2023年7月在IPO资本协助下获贵阳创投3000万美元投资后,纷享销客在一年间再获投资,这也是其连续第四年获得新的投资。 本轮融资后,纷享销客将一如既往地持续完善产…

wpf 如何7步写一个badge控件

首先看一下效果: 任意控件可以附加一个文字在控件的右上角,并带有红色背景 第一步,新建一个空的wpf项目: 第二步,创建一个类,取名为badge: 第三步,将badge的父类设置成 System.Windows.Documents.Adornerpublic class Badge : Adorner{public Badge(UIElement adornedEle…

CSS 绘制扇面

参考资料:https://juejin.cn/post/7266641059282927650效果:源码:<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0&…

咪咕视频m3u8地址解析及ddCalcu参数加密逆向

本文主要讲述咪咕视频m3u8地址的解析以及使用Wasm对视频的m3u8地址进行加密得到ddCalcu参数的方法。咪咕视频m3u8地址解析及ddCalcu参数加密逆向 概述 本文主要讲述咪咕视频m3u8地址的解析以及使用Wasm对视频的m3u8地址进行加密得到ddCalcu参数的方法。 使用视频ID获取未加密的…

Vs+Qt添加ui子页面

在Qt项目中,如果要实现一个弹出子界面并包含返回按钮的功能,最合适的选择是使用 Qt Dialog Form File 来创建子界面。 Qt Dialog Form File 与 Qt Widget Form File 的区别 Qt Dialog Form File (Button Bottom) 和 Qt Dialog Form File (Button Right): 这两种文件类型用于创…

ubuntu 22.04 安装 docker(服务器从毛胚到精装)

1、用户操作 阿里云默认是 root 用户,我们一般要自己创建一个用户,然后给该用户 sudo 权限 添加用户 sudo adduser newUserName赋予sudo权限 sudo usermod -aG sudo newUserName删除用户 sudo deluser --remove-home --remove-all-files newUserName切换用户 sudo su - newUs…

Mac os的防火墙导致开的热点手机连不上

在工位上用Mac给手机开热点用,结果今天手机一直连不上Mac开的热点,最后把Mac的防火墙关了就能让手机连上了,连上了再把防火墙打开也不影响连接。

k8s技术总结(一)

在学习完docker之后,也很有必要再学习k8s的一些理论和技术。 一、基础概念 kubernetes(k8s)和docker在容器管理领域具有不同的侧重点和优势。当前docker主要关注单个容器的构建、运行和管理,而k8s则专注于大规模的容器编排和管理。k8s在以下几个特性中,更具有优势。 特性1…

TIM-定时器

TIM简介定时器类型