利用face locations包实现刷脸签到小应用

前言

前段时间看了一篇帖子老板来了:人脸识别+手机推送,老板来了你立刻知道。作者利用face_recognition+jpush-api-python-client的方式完成了办公室摄像头识别BOSS脸型,自动手机推送同时切换电脑屏幕的功能。点子不错,也启发了我也许可以做个自动人脸识别签到的小应用,可以用在上课,晚宴,会展等需要签到的场景。


效果展示

img

img

环境

  • Python 3.6.1
  • Windows 7 64位
  • PyCharm 2017.1.4

策略

需要用到的库

  • face_recognition(基于dlib的人脸检测,识别率高达99.38%,比OpenCV更好用)

    ageitgey/face_recognition

    安装:

    1
    pip install face_recognition

    如果安装过程中出现问题,99%都是安装依赖的库时出现了问题,这货安装依赖较多:boost(boost_python),cmake,dlib这几个依赖和库,中间出现任何问题都可以通过Google解决(回头我写篇帖子吧这个坑填上)。

  • cv2 (用来获取对网络摄像头的引用)

  • csv(用来创建并写入签到表)

  • time(获取签到时间)

思路

1.将所有宾客人员的头像照片放在同一个文件夹下,并将文件名设置为人员姓名(由于CV2不能识别中文,这里只能用英文表示)。

2.利用face_recognition识别宾客人员集(学习集),并将人脸姓名人脸参数形成一个dict等待调用。

3.用CV2调用摄像头,抓取单帧视频 ,用face_recognition在视频框架中查找所有的人脸,对比学习集中每张脸,查看是否与已知面孔匹配,识别匹配后在视频中标记姓名,并将姓名签到时间写入签到名单.csv

4.用CV2检测指定按键,当点击键盘上的 “f”时, 显示当前签到状态(名册总人数、目前已签到人数、未签到名单)。

建立学习集

将所有宾客人员的头像照片放在同一个文件夹下并改好文件名后

img

在项目根目录下建立一个guests_collections.py写入代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import os
import face_recognition

# 建立学习集人脸识别对比库
path = '*************\刷脸签到\宾客人员集' # 宾客人员集文件夹位置
Learning = {} # 人脸姓名与参数 Dict
for rt, dirs, face_names in os.walk(path):
for name in face_names:
# 人脸姓名
face_name = name[:-4]
# 人脸参数
dirpath = rt + "\\" + name
face_image = face_recognition.load_image_file(dirpath)
face_encoding = face_recognition.face_encodings(face_image)[0]
# 将人脸姓名、人脸参数加入Learning字典
Learning [face_name] = face_encoding
all_num = len(Learning) # 计算宾客人员总人数
all_mames = Learning.keys() # 宾客人员姓名表

这里的Learning , all_num , all_mames都是等待下一步主程序调用的

代码

在项目根目录下建立主程序,并写入代码:

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# -*- coding:utf-8 -*-
# hahajoker-2017-11-02

import face_recognition
import cv2
import csv
import sys
sys.path.append(" *********\刷脸签到") # 设置你的项目文件夹路径
# 调用上一步学习集的Learning , all_num , all_mame参数
from guests_collections import Learning , all_num , all_mames
import time

# 这是一个运行在现场从摄像头获取的人脸识别签到项目。

# 获取对网络摄像头 #0 的引用 (默认值)
video_capture = cv2.VideoCapture(0)

# 建立签到名单.csv 模式为写入模式
with open('签到名单.csv', 'w', newline='') as f:
csv_writer = csv.writer(f)

target_names = []
while True:
# 记录当前时间
now = time.strftime("%H:%M:%S")

# 抓取单帧视频
ret, frame = video_capture.read()

# 在视频框架中查找所有的面孔和面孔 enqcodings
face_locations = face_recognition.face_locations(frame)
face_encodings = face_recognition.face_encodings(frame, face_locations)

# 遍历视频帧中的每个脸
for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):
name = "Unknown"
# 对于学习集中每张脸
for face_name, guests_face_encoding in Learning.items():
# 查看是否与已知面孔匹配
match = face_recognition.compare_faces([guests_face_encoding], face_encoding, tolerance=0.4)

# 为识别出来的脸命名,并将姓名添加到签到名单中
if match[0]:
name = face_name
if name not in target_names:
target_names.append(face_name)
csv_writer.writerow([face_name]) # 将姓名添加到签到名单.csv中
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print("您好", name, ",系统已经帮您签到 ",now)
target_num = len(target_names) # 签到人数
Remaining_names = all_mames - target_names # 当前未到人员列表

break

# 在脸上画一个框
cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)

# 在脸下面画一个名字的标签
cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
font = cv2.FONT_HERSHEY_DUPLEX
cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)

# 显示生成的图像
cv2.imshow('Video', frame)

# 点击键盘上的 "f" 显示当前签到状态!
if cv2.waitKey(1) & 0xFF == ord('f'):
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print(now,"——— 名册总人数为",all_num,"人,目前已签到",target_num,"人。")
print("未签到名单:")
for ever_name in Remaining_names:
print(ever_name)

# 点击键盘上的 "q" 退出!
if cv2.waitKey(1) & 0xFF == ord('q'):
break


# 网络摄像头的释放手柄
video_capture.release()
cv2.destroyAllWindows()

每一步我都做了注释,应该不难理解。

用钱砸我,不要停!