face_recognition 是一个基于 dlib 库的人脸识别工具包。主要包括:
- 标注人脸位置
- 计算人脸特征
- 人脸信息编码
- 人脸信息匹配
该 Python 工具包使用起来也比较简单,我们就通过几个例子来了解下使用方法。也可以直接参考文档,下联链接已经给出:
Document: https://face-recognition.readthedocs.io/en/latest/readme.html
- Face Recognition 安装 {#title-0} =================================
安装要求:
- Python 3.3+ or Python 2.7
- macOS or Linux (Windows not officially supported, but might work)
pip install face_recognition
详细按照文档:https://face-recognition.readthedocs.io/en/latest/readme.html#requirements
- 标注人脸位置 {#title-1} ====================
人脸识别使用的接口为:
face_locations(img, number_of_times_to_upsample=1, model="hog")
- img 为要进行人脸检测的输入图像
- number_of_times_to_upsample 在进行人脸检测时,
face_locations
函数使用了一个基于 HOG 特征的人脸检测算法。这种算法对于输入的图像分辨率有一定的要求,因为低分辨率的图像往往难以检测出人脸。为了解决这个问题face_locations
函数会先对输入图像进行上采样,提高其分辨率,然后再进行人脸检测。具体来说,它表示对输入图像进行几次上采样。每次上采样都会使图像的分辨率翻倍,因此上采样的次数越多,图像的分辨率就越高,人脸检测的精度也会相应提高。但是,上采样次数越多,计算时间也会相应增加。因此,在设置这个参数时需要根据实际需求进行平衡。 - model 使用何种人脸检测模型,可选的值有:hog 和 cnn,hog 的准确率低一些,但是更快。cnn 是深度模型,有着更好的准确率,但是检测速度要慢一些,使用时,可能需要 GPU 加速模型计算以便能够获得更好的实时性能
- 返回值:该函数将会返回一个列表,列表中的每个元素都是一个包含了 4 个位置值 (top, right, bottom, left) 的元组,用于表示人脸的位置
接下来,我们使用该 API 检测下面输入图像中的人脸位置,下面是示例代码(test03 为 cv2 中的检测器示例):
import face_recognition
import matplotlib.pyplot as plt
import cv2
import time
# 获得人脸坐标
def test01():
# 1. 读取要识别的图像
image = face_recognition.load_image_file('1.jpg', mode='RGB')
print('图片尺寸:', image.shape)
# 2. 使用 hog 检测人脸位置
start = time.time()
face_locations = face_recognition.face_locations(image, model='hog')
print('HOG 检测时间:', time.time() - start)
# 3. 绘制人脸位置
for top, right, bottom, left in face_locations:
cv2.rectangle(image, (left, top), (right, bottom), color=(255, 0, 255), thickness=2)
plt.title('HOG')
plt.imshow(image)
plt.show()
def test02():
# 1. 读取要识别的图像
image = face_recognition.load_image_file('1.jpg', mode='RGB')
print('图片尺寸:', image.shape)
# 2. 使用 cnn 检测人脸位置
start = time.time()
face_locations = face_recognition.face_locations(image, model='cnn')
print('CNN 检测时间:', time.time() - start)
# 3. 绘制人脸位置
for top, right, bottom, left in face_locations:
cv2.rectangle(image, (left, top), (right, bottom), color=(255, 0, 255), thickness=2)
plt.title('CNN')
plt.imshow(image)
plt.show()
def test03():
# 1. 读取要识别的图像
image = cv2.imread('1.jpg', cv2.IMREAD_COLOR)
print('图片尺寸:', image.shape)
# 2. 使用 cv2 检测人脸位置
model = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml')
# 检测之前先将图像转换为灰度图
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
start = time.time()
# 返回: x, y, width, height
face_locations = model.detectMultiScale(gray_image)
print('CV2 检测时间:', time.time() - start)
# 3. 绘制人脸位置
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
for x, y, width, height in face_locations:
cv2.rectangle(image, (x, y), (x + width, y + height), color=(255, 0, 255), thickness=2)
plt.title('CV2')
plt.imshow(image)
plt.show()
if __name__ == '__main__':
test01()
test02()
test03()
程序输出结果:
图片尺寸: (432, 658, 3)
HOG 检测时间: 0.11088299751281738
图片尺寸: (432, 658, 3)
CNN 检测时间: 2.421550750732422
图片尺寸: (432, 658, 3)
CV2 检测时间: 0.06716680526733398
上述输出的检测时间都是在 CPU 上的计算结果。
- 计算人脸特征 {#title-2} ====================
人脸特征即提取下巴(chin)、左眉(left_eyebrow)、右眉(right_eyebrow)、鼻梁(nose_bridge)、鼻尖(nose_tip)、左眼(left_eye)、右眼(right_eye)、上唇(top_lip)、下唇(bottom_lip)共计 72 个关键位置特征。
如果将 face_landmarks 函数的 model 参数设置为 small,则只输出鼻尖(nose_tip)、左眼(left_eye)、右眼(right_eye)这三个部位共计 5 位置特征
import face_recognition
import matplotlib.pyplot as plt
def test():
image = face_recognition.load_image_file('1.jpg', mode='RGB')
# [(51, 365, 149, 267)] => top, right, bottom, left
face_locations = face_recognition.face_locations(image, model='hog')
# 获得人脸特征
facial_features = face_recognition.face_landmarks(image, face_locations, model='large')
print(facial_features)
# 绘制人脸特征
for facial_feature in facial_features:
for key, features in facial_feature.items():
for feature in features:
cv2.circle(image, feature, radius=2, color=(0, 255, 12))
plt.imshow(image)
plt.show()
if __name__ == '__main__':
test()
程序输出结果:
[{'chin': [(278, 92), (278, 104), (279, 117), (281, 130), (284, 142), (290, 154), (298, 164), (306, 173), (318, 175), (332, 173), (344, 165), (355, 156), (365, 146), (371, 133), (374, 119), (375, 105), (376, 91)], 'left_eyebrow': [(283, 85), (289, 79), (297, 79), (305, 81), (313, 84)], 'right_eyebrow': [(323, 83), (332, 80), (342, 78), (352, 80), (359, 86)], 'nose_bridge': [(318, 91), (318, 99), (317, 108), (316, 117)], 'nose_tip': [(309, 122), (313, 124), (317, 125), (322, 124), (327, 123)], 'left_eye': [(292, 90), (296, 87), (302, 87), (307, 91), (302, 92), (296, 92)], 'right_eye': [(333, 91), (338, 88), (344, 88), (349, 91), (344, 93), (338, 93)], 'top_lip': [(306, 143), (309, 138), (313, 135), (317, 137), (322, 136), (328, 139), (333, 144), (330, 144), (322, 141), (317, 141), (314, 141), (309, 143)], 'bottom_lip': [(333, 144), (328, 151), (322, 154), (318, 154), (313, 153), (309, 149), (306, 143), (309, 143), (313, 144), (317, 145), (322, 144), (330, 144)]}]
- 人脸信息编码 {#title-3} ====================
我们在做人脸匹配时,比较的就是两个人脸的编码距离。face_encodings 函数如下:
face_encodings(face_image, known_face_locations=None, num_jitters=1, model="small")
- face_image 输入的检测图像
- known_face_locations 为 face_locations 函数检测到的多个人脸位置
- model 可选的值为 large、small,表示用多少个人脸特征来构造人脸编码,small 更快
- num_jitters 它指定了在提取人脸特征时进行多少次随机扰动(jitter),随机扰动指的是将输入的人脸图像进行随机的微小变换,例如旋转、裁剪、亮度变换等,从而生成多个略微不同的人脸图像。在进行人脸特征提取时,将这些略微不同的图像进行特征提取,并将得到的特征向量进行平均或取中位数,可以提高人脸识别的精度,但计算时间也会相应增加。
示例代码:
import face_recognition
import matplotlib.pyplot as plt
def test():
# 读取输入图像
image = face_recognition.load_image_file('1.jpg', mode='RGB')
# 计算人脸位置
face_locations = face_recognition.face_locations(image, model='hog')
# 人脸信息编码
face_encodings = face_recognition.face_encodings(image, known_face_locations=face_locations, model='large')
print('人脸编码维度:', face_encodings[0].shape)
print(face_encodings)
if __name__ == '__main__':
test()
程序输出结果:
人脸编码维度: (128,)
[array([-0.10339236, 0.14851965, 0.01029977, 0.00930228, -0.15734453,
0.03904981, 0.01654922, -0.17565952, 0.05527157, -0.12608829,
0.18594478, -0.07738445, -0.31720433, -0.09317419, 0.0242323 ,
0.17734227, -0.1299797 , -0.1051617 , -0.21656519, -0.10200764,
0.00980881, 0.06125376, -0.03489925, -0.02904189, -0.12794323,
-0.25462753, -0.08247674, -0.03054573, 0.02245354, -0.04793654,
0.04205053, 0.01841517, -0.23550904, -0.06501944, -0.02505583,
0.02860026, -0.05353981, -0.06184244, 0.13586399, 0.03928199,
-0.13611943, 0.04089652, 0.01368326, 0.23697728, 0.18460381,
-0.00639988, 0.02225903, -0.09905794, 0.11359482, -0.24700806,
-0.0144341 , 0.12040581, 0.11725815, 0.08271284, 0.03133506,
-0.08889135, 0.04660001, 0.13280977, -0.147306 , 0.07945663,
0.09690579, -0.18537416, -0.06320523, -0.06023312, 0.12699956,
0.0395139 , -0.02118635, -0.13156748, 0.19904432, -0.14599995,
-0.11009898, 0.00675882, -0.07475307, -0.13796815, -0.39703727,
0.03987332, 0.40932226, 0.17702992, -0.2292663 , -0.04161827,
-0.04523409, 0.02514784, 0.1070801 , 0.06148657, -0.04007861,
-0.12225512, -0.12017394, 0.07339939, 0.25885367, -0.10757827,
-0.00895133, 0.28658509, 0.07006181, -0.04103569, 0.03035998,
0.00265448, -0.0738667 , -0.06689832, -0.03737948, -0.01301235,
0.1173306 , -0.16319954, 0.03531633, 0.11514346, -0.14696895,
0.20176159, -0.02319317, 0.00985028, 0.01496939, -0.05379927,
-0.08210421, 0.02171123, 0.19380003, -0.15109025, 0.20256151,
0.20543517, -0.08692768, 0.09492791, 0.07402149, 0.1480388 ,
-0.07978582, 0.00954351, -0.15085556, -0.18490645, 0.05490613,
0.00381539, 0.02888954, 0.05953676])]
- 人脸信息匹配 {#title-4} ====================
人脸信息匹配其实就是将两个人脸的编码计算欧式距离,距离越大则越不相似,我们实际在比较两个人脸相似度时,就需要设置一个判断阈值。
我们接下来从下面两张图片中提取人脸编码信息,并比较是否是同一个人。
示例代码:
import face_recognition
import matplotlib.pyplot as plt
def test():
# 读取输入图像
trump = face_recognition.load_image_file('1.jpg', mode='RGB')
biden = face_recognition.load_image_file('2.jpeg', mode='RGB')
# 识别人脸位置
trump_locations = face_recognition.face_locations(trump, model='hog')
biden_locations = face_recognition.face_locations(biden, model='hog')
# 绘制提取人脸
top, right, bottom, left = trump_locations[0]
plt.subplot(121)
plt.title('Trump')
plt.imshow(trump[top: bottom, left: right])
top, right, bottom, left = biden_locations[0]
plt.subplot(122)
plt.title('Biden')
plt.imshow(biden[top: bottom, left: right])
plt.show()
# 人脸信息编码
trump_encodings = face_recognition.face_encodings(trump, trump_locations)
biden_encodings = face_recognition.face_encodings(biden, biden_locations)
# 计算人脸相似度
similarity = face_recognition.face_distance(trump_encodings, biden_encodings[0])
print('人脸相似度:', similarity) # 值越大越不相似
# 比较人脸编码
# tolerance 为阈值,两个人脸编码的欧式距离小于该值认为相似,默认为 0.6, 值越大越严格
# 第一个参数为一个人脸编码列表
# 第二个参数为单个人脸编码数值
result = face_recognition.compare_faces(trump_encodings, biden_encodings[0], tolerance=0.3)
print(result)
if __name__ == '__main__':
test()
程序执行结果:
人脸相似度: [0.62457377]
[False]
提取到人脸图像