Python人脸识别库DeepFace使用教程及源码解析
目录
一、DeepFace介绍
1、人脸库设计
2、DeepFace.find
3、DeepFace.verify
4、DeepFace.analyze
5、DeepFace.extract_faces
6、DeepFace.represent
7、DeepFace.stream
二、DeepFace二次开发
1、开发活体检测API
2、模型权重持久化
三、总结
一、DeepFace介绍
DeepFace是一个用于人脸识别和面部属性分析的 Python 库。它是建立在深度学习模型之上,提供了简单易用的接口,用于处理各种面部相关的任务,如验证两张脸是否属于同一人、识别面部表情、检测年龄和性别等。
安装方式:
pip install deepface
DeepFace提供了以下几种人脸识别相关的API:
DeepFace.find:用于人脸库检索
DeepFace.verify:用于两张人脸比较
DeepFace.analyze:用于人脸属性分析
DeepFace.extract_faces:用于人脸目标检测
DeepFace.represent:用于人脸特征提取
DeepFace.stream:用于人脸实时分析
1、人脸库设计
以下是本人设计的人脸库存储结构,在face_database目录下,每个子目录代表某一个人的人脸图片,可以存放正脸、侧脸等不同角度照片,其中info.json存储了该人物的所有信息,比如姓名、手机号、出生年月等等信息,子目录名称是基于唯一标识(例如手机号)通过md5生成的散列值。
work_space
├── face_database
│ ├──682f1d4d333c228f02199c86dd385528
│ │ ├──0000.jpg
│ │ ├──0001.jpg│ │ ├──info.json
│ ├──992bd729860ab5603d3133bc7108991e
│ │ ├──0000.jpg│ │ ├──info.json
…
2、DeepFace.find
DeepFace.find主要用于在一组人脸图像(可以是一个图像数据库)中查找与给定的一张人脸图像相似的人脸。例如,在一个拥有大量员工照片的公司数据库中,使用一张未知身份员工的近照通过DeepFace.find来找到该员工在数据库中的其他照片,进而确定该员工的身份。
DeepFace.find返回一个包含查找结果的list(List[pd.DataFrame]),其中每个元素是Pandas DataFrame类型,DataFrame的每一行都对应着一张在数据库中找到的相似人脸,包含人脸图像的相关信息(如图像路径等)以及和输入人脸的距离,该距离用于衡量找到的人脸与输入人脸的相似程度,距离越近表示越相似。
from deepface import DeepFace
# 数据库图像路径列表
database_path = 'face_database'
query_image_path = "query_image.jpg"
results = DeepFace.find(image_path,
database_path,
enforce_detection=False,
)[0]
for _, row in results.iterrows():
print(f"找到的相似人脸路径:{row['identity']},距离:{row['distance']}")
DeepFace.find函数的代码逻辑在DeepFace包的路径下的“modules\recognition.py”文件中,首先对人脸库路径下缓存的pkl文件提取所有人脸图片的特征向量,这些特征包含了面部的轮廓、五官的形状和位置、皮肤纹理等细节信息:
然后通过representation.represent函数对输入图像query_image_path提取特征向量,与人脸库的所有特征向量逐一计算距离,通过阈值target_threshold筛选所有距离小于阈值的人脸库图片,注意最后输出结果是按照距离从小到大升序的,如果只想获取距离最近的结果则提取DataFrame的第一行即可。
3、DeepFace.verify
DeepFace.verify是DeepFace库中的一个函数,主要用于验证两张人脸图像是否属于同一个人。
DeepFace.verify的代码逻辑在“modules\verification.py”文件中,与DeepFace.find类似,也是通过representation.represent函数分别对输入的两张图片提取特征向量,然后通过相应的距离计算函数生成两张图片的距离,距离小于预设阈值,则判定为同一个人。
from deepface import DeepFace
# 两张人脸图像的路径,这里假设是本地的图像文件
img1_path = "path/to/image1.jpg"
img2_path = "path/to/image2.jpg"
result = deepface.verify(img1_path, img2_path, enforce_detection=False)
if result["verified"]:
print("这两张脸属于同一个人。")
else:
print("这两张脸不属于同一个人。")
print("距离:", result.get("distance"))
返回的结果示例如下:
{'verified': True, 'distance': 0.5409709948424768, 'threshold': 0.68, 'model': 'VGG-Face', 'detector_backend': 'opencv', 'similarity_metric': 'cosine', 'facial_areas': {'img1': {'x': 0, 'y': 5, 'w': 182, 'h': 221, 'left_eye': (127, 82), 'right_eye': (40, 90)}, 'img2': {'x': 0, 'y': 0, 'w': 683, 'h': 755, 'left_eye': (493, 244), 'right_eye': (170, 266)} }, 'time': 1.49 }verified表明输入的两张人脸是否被判定为属于同一个人。
distance表示两张人脸特征向量之间的距离度量值。
threshold是判定两张人脸是否属于同一人的阈值。
model代表用于提取人脸特征的深度学习模型名称,可选:VGG-Face, Facenet, Facenet512, OpenFace, DeepFace, DeepID, Dlib, ArcFace, SFace and GhostFaceNet。
detector_backend表示用于检测图像中人脸位置的方法,可选:Options: 'opencv', 'retinaface', 'mtcnn', 'ssd', 'dlib', 'mediapipe', 'yolov8', 'centerface' or 'skip'。
similarity_metric指定用于计算两张人脸特征向量之间相似度的度量方法。
facial_areas包含了输入的两张人脸图像(分别标记为img1和img2)中人脸的位置信息以及眼睛的位置信息。
time表示整个过程所花费的时间。
4、DeepFace.analyze
DeepFace.analyze能够对输入的人脸图像进行多维度的分析,包括表情识别、年龄估计、性别识别、种族识别等。这在很多领域都有广泛的应用,例如在市场调研中,通过分析消费者的表情来判断对产品的喜好程度;在安防监控中,对人员的年龄、性别等信息进行初步判断。
表情、性别、种族的识别实际上是二分类或多分类任务,年龄识别则是一个回归任务。
from deepface import DeepFace
img_path = "path/to/face_image.jpg"
analysis_result = DeepFace.analyze(img_path, enforce_detection=False)
print("表情:", analysis_result.get("dominant_emotion"))
print("年龄:", analysis_result.get("age"))
print("性别:", analysis_result.get("dominant_gender"))
print("种族:", analysis_result.get("dominant_race"))
返回的结果示例如下:
[{'emotion': {'angry': 0.7418791274356322, 'disgust': 5.340072880214408e-05, 'fear': 89.25175602744555, 'happy': 0.01589643601781866, 'sad': 0.0007775448929871182, 'surprise': 9.989639967062471, 'neutral': 1.7639903034977293e-06 }, 'dominant_emotion': 'fear', 'region': {'x': 0, 'y': 5, 'w': 182, 'h': 221, 'left_eye': (127, 82), 'right_eye': (40, 90) }, 'face_confidence': 0.94, 'age': 28, 'gender': {'Woman': 0.02528490440454334, 'Man': 99.9747097492218 }, 'dominant_gender': 'Man', 'race': {'asian': 79.76993322372437, 'indian': 2.4958742782473564, 'black': 0.7977190427482128, 'white': 7.959078252315521, 'middle eastern': 1.5946529805660248, 'latino hispanic': 7.382745295763016 }, 'dominant_race': 'asian' }]
DeepFace.analyze的代码逻辑在“modules\demography.py”文件中,通过加载action对应的模型,再由predict方法对输入的np.ndarray类型图像进行推理。例如,表情识别的模型加载及推理代码在“modules\demography\Emotion.py”文件中,基于tensorflow或keras构建一个3层卷积+3层全连接层的模型,通过softmax函数进行7分类。
5、DeepFace.extract_faces
DeepFace.extract_faces主要用于在给定的图像中检测人脸的位置和提取人脸区域,能够帮助后续的人脸分析(如表情分析、身份验证等)准确地定位到人脸所在的区域。例如,在一张包含多个人的合影中,该函数可以找出每个人脸的具体位置和边界。
from deepface import DeepFace
img_path = "path/to/face_image.jpg"
result = DeepFace.extract_faces(img_path)
print(result)
返回的结果示例如下:
[{'face': array([[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
...,
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]]]),'facial_area': {'x': 0, 'y': 5, 'w': 182, 'h': 221, 'left_eye': (127, 82), 'right_eye': (40, 90)},
'confidence': 0.94}]
face为图像中人脸部分的np.ndarray。
facial_area为图像中人脸的矩形框位置及左右眼位置。
confidence为人脸目标检测的置信度。
DeepFace.extract_faces的代码逻辑在“modules\detection.py”文件中,包含图像预处理、人脸目标检测与处理等逻辑。
6、DeepFace.represent
DeepFace.represent主要用于提取人脸图像的特征表示,通过使用预训练的深度学习模型将人脸图像转换为一个高维的特征向量。这个特征向量可以表示人脸的独特特征,例如面部的轮廓、眼睛、鼻子、嘴巴等的位置和形状信息,以及更细微的面部纹理和结构信息。对于不同的深度学习模型,提取的特征向量维度和表达能力会有所不同。
from deepface import DeepFace
img_path = "path/to/face_image.jpg"
result = DeepFace.represent(img_path)
print(result)
返回的结果示例如下:
[{'embedding': [0.0, 0.0, …… , 0.0],
'facial_area': {'x': 0, 'y': 5, 'w': 182, 'h': 221, 'left_eye': (127, 82), 'right_eye': (40, 90)},
'face_confidence': 0.94}]
embedding为4096维的向量。
7、DeepFace.stream
DeepFace.stream主要用于实现实时的人脸识别功能,该函数可以处理视频流(例如来自电脑自带摄像头)中的人脸信息,并进行实时的人脸识别操作。能够持续地从视频源中读取帧,检测帧中的人脸,并将其与已知的人脸数据库进行比对。
from deepface import DeepFace
# 使用 DeepFace.stream 进行实时人脸识别,使用笔记本自带摄像头
DeepFace.stream(db_path="face_database")
该函数不返回任何结果,但是运行该函数会打开一个窗口,显示笔记本摄像头的拍摄画面并进行实时分析,例如在人脸库中进行检索,分析年龄(25)、性别(Man)、表情识别(fear):
二、DeepFace二次开发
1、开发活体检测API
在DeepFace中,可以在verify、analyze、find、represent、stream、extract_faces设置anti_spoofing为True,即可对输入图像进行活体检测,使用的算法是MiniFASNet:
但有个问题是,DeepFace源码在anti_spoofing设为True、并且检测为假时,会抛出异常:
但我想在实际使用中不抛异常而是获得活体检测的分类结果和类别对应分数,再进行下一步的业务逻辑处理。
于是,我在DeepFace.py文件中新增了一个detect_spoofing函数:
在“modules\demography.py”文件中新增detect_spoofing函数:
然后调用DeepFace.detect_spoofing方法即可返回活体检测二分类的类别(True or False)以及分数。
2、模型权重持久化
由于DeepFace并未提供模型权重输入方式,而是通过输入的model_name每次运行时加载对应模型的权重,一个是会略微拖慢代码运行速度,另一个是如果我想加载自己训练的模型就只能去修改代码底层的模型路径了,有点不方便。
例如,DeepFace提供的目标检测模型有yolov8,但我想用我自己训练的yolov11。
于是我把加载模型的代码放到了外部逻辑里:
在DeepFace底层代码中逐层修改,添加model参数,并在对应的加载模型处进行修改,例如人脸分析DeepFace.analyze:
修改后,测得DeepFace.find、DeepFace.analyze等API运行速度平均加快6%,算是小幅增速。
三、总结
DeepFace是基于TensorFlow、Keras的人脸识别库,集成了多种人脸目标检测、人脸识别、人脸分析等算法,可通过修改model_name轻松切换不同模型,也可以使用自己训练的模型集成到DeepFace框架中,快速地搭建起一个小型的、具有一定准确率的人脸识别与分析应用。
DeepFace优化方向:可以从集成更多的图像预处理方法、提升神经网络提取人脸特征的能力、提升推理速度以便用于实时检测视频流。