face_recognition实现摄像头实时人脸识别

前言

face_recognition document

本篇博客使用 OpenCV + face_recognition 实现摄像头的实时人脸识别。有关环境配置请参考我的上一篇博客:Python人脸识别模块face_recognition之环境配置

face_recognition简介

face_recognition是世界上最简单的人脸识别库了。你可以通过Python引用或者命令行的形式使用它,来管理和识别人脸。该软件包使用dlib中最先进的人脸识别深度学习算法,使得识别准确率在《Labled Faces in the world》测试基准下达到了99.38%。它同时提供了一个叫face_recognition的命令行工具,以便你可以用命令行对一个文件夹中的图片进行识别操作。


一、face_recognition详解

(以下内容翻译自官方文档)

1.1 face_recognition.load_image_file(file,mode =’RGB’ )

解释:

  • 将图像文件(.jpg,.png等)加载到numpy数组中

参数:

  • file - 要加载的图像文件名或文件对象

  • mode - 将图像转换为的格式。仅支持“RGB”(8位RGB,3个通道)和“L”(黑色和白色)。

返回:

  • 图像内容为numpy数组
1.2 face_recognition.face_locations(img,number_of_times_to_upsample = 1,model =’hog’ )

解释:

  • 返回图像中人脸边界框的数组

参数:

  • img - 一个图像(作为一个numpy数组)
  • number_of_times_to_upsample - 对图像进行上采样以查找面部的次数。数字越大,面部越小。
  • model - 使用哪种人脸检测模型。“hog”不太准确,但在CPU上更快。“cnn”是一种更准确的深度学习模型,它是GPU / CUDA加速(如果可用)。默认为“hog”。

返回:

  • css(顶部,右侧,底部,左侧)顺序中找到的面部位置的元组列表
1.3 face_recognition.face_landmarks(face_image,face_locations = None,model =’large’ )

解释:

  • 给定图像,返回图像中每个面部的面部特征位置(眼睛,鼻子等)的字典

参数:

  • face_image - 要搜索的图像
  • face_locations - 可选择提供要检查的面部位置列表。
  • model - 可选 - 要使用的模型。“大”(默认)或 “小”(速度更快)。

返回:

  • 面部特征位置(眼睛,鼻子等)的序列表
1.4 face_recognition.face_encodings(face_image,known_face_locations = None,num_jitters = 1 )

解释:

  • 给定图像,返回图像中每个面的128维面部编码。

参数:

  • face_image - 包含一个或多个面的图像
  • known_face_locations - 可选 - 如果您已经知道它们,则每个面的边界框。
  • num_jitters - 计算编码时重新采样面的次数。更高更准确,但更慢(即100慢100倍)

返回:

  • 128维面部编码列表(图像中每个面部一个)
1.5 face_recognition.api.face_distance(face_encodings,face_to_compare )

解释:

  • 给定面部编码列表,将它们与已知面部编码进行比较,并获得每个比较面部的欧氏距离。距离告诉您脸部的相似程度。

参数:

  • faces - 要比较的面部编码列表
  • face_to_compare - 要与之进行比较的面部编码

返回:

  • 一个numpy ndarray,每个面的距离与’faces’数组的顺序相同
1.6 face_recognition.api.compare_faces(known_face_encodings,face_encoding_to_check,tolerance = 0.6 )

解释:

  • 将面部编码列表与候选编码进行比较,看它们是否匹配。

参数:

  • known_face_encodings - 已知面部编码的列表
  • face_encoding_to_check - 用于与列表进行比较的单面编码
  • tolerance - 面部之间的距离,将其视为匹配。越低越严格。0.6是典型的最佳性能。

返回:

  • True / False值的列表,指示哪个known_face_encodings与要检查的面部编码匹配

二、face_recognition代码阐述

2.1 在图片中识别人脸

1
2
3
import face_recognition
image=face_recognition.load_image_file("your_file.jpg")
face_locations=face_recognition.face_locations(image)

2.2 找到并操作图片中的脸部特征

获得图片中人类眼睛、鼻子、嘴、下巴的位置和轮廓:

1
2
3
import face_recognition
image = face_recognition.load_image_file("your_file.jpg")
face_landmarks_list = face_recognition.face_landmarks(image)

找到脸部特征有很多超级有用的应用场景,当然你也可以把它用在最显而易见的功能上:美颜功能,就像美图秀秀那样。

2.3 鉴定图片中的脸

1
2
3
4
5
6
import face_recognition
known_image=face_recognition.load_image_file("biden.jpg")
unknown_image=face_recognition.load_image_file("unknown.jpg")
biden_encoding=face_recognition.face_encodings(known_image)[0
]unknown_encoding=face_recognition.face_encodings(unknown_image)[0]
results=face_recognition.compare_faces([biden_encoding],unknown_encoding)

三、OpenCV+face_recognition 摄像头实时人脸识别

设计思路:

  • 读入目标图片并对已知人脸进行编码
  • 读取摄像头
  • 定位摄像头每一帧拍摄中的人脸位置坐标
  • 对摄像头每一帧进行编码并与已知图片的编码进行比较
  • 达到相似度的阈值则进行边框标记
  • 识别成功

注:过程中的函数的作用及参数的设置不懂的可以参考百度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 读入相关库
# cv2即 OpenCV(cv和cv2 有点类似 py2和py3),用来读取摄像头
# face_recognition 进行人脸识别

import face_recognition as fr
import cv2

# 保存在本地的待比较图片
# image是numpy三维数组
image = fr.load_image_file(r'C:\SecurityMonitor\FaceRecognition\img\face.jpg')
# 对已知图片进行编码,由于face_encodings是元组列表,并且我们已知的图片中只有一个人,所以获取索引0即目标编码
Admin_encoding = fr.face_encodings(image)[0]

# 调用OpenCV获取摄像头,VideoCapture(0)是后置摄像头,VideoCapture(1)是前置摄像头
cap = cv2.VideoCapture(1)

# 让摄像头一直进行拍摄
while True:
# 由于摄像头中会出现很多人脸,设置index为编码列表中识别成功的元素下标值
index = -1
# 进行摄像头的拍摄,read()是按帧拍摄
# 返回值1:ret是bool值,拍摄成功与否
# 返回值2:frame是该帧的numpy数组
ret,frame = cap.read()
# 对图像进行resize()缩小,提高速度
smallFrame = cv2.resize(frame,(0,0),fx=0.25,fy=0.25)
# 定位摄像头该帧中的人脸,face_locations(top,right,bottom,left)是元组列表,可能有多个人脸
face_locations = fr.face_locations(smallFrame)
# 在该帧图像中定位人脸位置,并进行人脸编码
face_encodings = fr.face_encodings(smallFrame,face_locations)

# 对每一个编码进行与已知编码进行比较,识别成功则记录下标并退出
for i,face_encoding in enumerate(face_encodings):
result = fr.compare_faces([Admin_encoding],face_encoding)
if result:
index = i
break
# 识别成功则进行矩形框标记,需要将该帧图像恢复原图,因为上面的比例因子为0.25,所以这里扩大四倍
if index != -1:
face_location = face_locations[index]
top = face_location[0] * 4
right = face_location[1] * 4
bottom = face_location[2] * 4
left = face_location[3] * 4
# 矩形框标记
cv2.rectangle(frame,(left,top),(right,bottom),(0,0,255),2)

# 显示摄像头图像
cv2.imshow('Identification',frame)
# 按 q 退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break

# 释放资源
cap.release()
cv2.destroyAllWindows()