概述
笔者接到一个技术需求,主要的业务场景如下:公司预先将员工的照片录入系统,此后员工访问系统时,可以由前端的照相设备采集面孔,使用人脸识别技术,找到员工对应的身份信息,实现 刷脸登录 的功能,此外,最好身份信息和照片都在系统内,尽量不使用互联网服务。
笔者从网上查找是否存在现成的解决方案,大部分的都是互联网厂商提供的云服务,没找到适合内网部署的现成项目。笔者则转变想法,查找是否有比较方便的人脸识别库,稍微写写代码,将它封装为服务。经过搜索,找到了 Face Recognition 这样一个 Python
库。
接下来笔者简述下 Face Recognition
库的使用。
Face Recognition 库简介
1. 原理
Face Recognition
库主要封装了dlib这一 C++
图形库,通过 Python
语言将它封装为一个非常简单就可以实现人脸识别的 API
库,屏蔽了人脸识别的算法细节,大大降低了人脸识别功能的开发难度。Face Recognition
库进行人脸识别主要经过如下步骤:
-
人脸检测:找出所有的面孔
找出所有的面孔 -
检测面部特征点: 使用特征点矫正姿态,将侧脸转为正脸
检测面部特征点 -
给脸部编码:根据面部特征点计算这个面孔的特征值(特征向量)
编码-计算特征值 - 从编码中找出人的名字:与已知面孔进行特征值比对,寻找匹配的面孔,得到人名
2. 接口
在 Face Recognition
库中对应的 API
接口如下:
- 人脸检测:
face_recognition.face_locations(img, number_of_times_to_upsample=1, model="hog")
- 检测面部特征点:
face_landmarks(face_image, face_locations=None, model="large")
- 给脸部编码:
face_encodings(face_image, known_face_locations=None, num_jitters=1)
- 从编码中找出人的名字:
compare_faces(known_face_encodings, face_encoding_to_check, tolerance=0.6)
值得说明的是,Face Recognition
中,第2步 face_landmarks
已经在第3步函数 face_encodings
的开头执行过了,所以如果要进行人脸识别,完全可以跳过第2步,只需要1、3、4步。此外Face Recognition
库还提供了如 load_image_file(file, mode='RGB')
这一加载面孔照片的函数等其他函数,此处不再多叙述。
3. 使用示例
示例是快速上手一个陌生库的主要手段,从Face Recognition
官方库下载 源码 ,打开其中的 examples
目录,可以看到里面有各种示例,下面以 face_distance.py
和 web_service_example.py
为例讲解 Face Recognition
库的使用。
face_distance.py
主要进行了人脸检测、脸部编码、两张脸编码相似度计算。分别读取obama.jpg
和biden.jpg
两个面孔作为已知面孔,用obama2.jpg
作为待判断面孔,通过计算编码,对编码进行计算相似度,判断obama2.jpg
应该属于那个已知面孔。
import face_recognition
# 加载2张已知面孔的图片
known_obama_image = face_recognition.load_image_file("obama.jpg")
known_biden_image = face_recognition.load_image_file("biden.jpg")
# 计算图片对应的编码
obama_face_encoding = face_recognition.face_encodings(known_obama_image)[0]
biden_face_encoding = face_recognition.face_encodings(known_biden_image)[0]
known_encodings = [
obama_face_encoding,
biden_face_encoding
]
# 加载一张未知面孔的图片
image_to_test = face_recognition.load_image_file("obama2.jpg")
# 计算图片对应的编码
image_to_test_encoding = face_recognition.face_encodings(image_to_test)[0]
# 计算未知图片与已知的2个面孔的距离
face_distances = face_recognition.face_distance(known_encodings, image_to_test_encoding)
for i, face_distance in enumerate(face_distances):
print("The test image has a distance of {:.2} from known image #{}".format(face_distance, i))
print("- With a normal cutoff of 0.6, would the test image match the known image? {}".format(face_distance < 0.6))
print("- With a very strict cutoff of 0.5, would the test image match the known image? {}".format(face_distance < 0.5))
print()
运行结果如下:
The test image has a distance of 0.35 from known image #0 (与#0面孔差异为0.35,在相似度阈值分别为 0.6和0.5的情形下,都可以认为与#0是同一人)
- With a normal cutoff of 0.6, would the test image match the known image? True
- With a very strict cutoff of 0.5, would the test image match the known image? True
The test image has a distance of 0.82 from known image #1(与#1面孔差异为0.82,在相似度阈值分别为 0.6和0.5的情形下,都不认为与#1是同一人)
- With a normal cutoff of 0.6, would the test image match the known image? False
- With a very strict cutoff of 0.5, would the test image match the known image? False