人脸考勤机分为两个模块,人脸识别与人脸检测
人脸识别
常用的人脸识别算法有Haar、Hog、CNN、SSD、MTCNN。
下面来分别阐述一下在Python中如何利用OpenCv快速实现使用。
我们通用的步骤是
# 步骤
# 1、读取包含人脸的图片
# 2.使用模型识别人脸
# 3.将识别结果用矩形框画出来
Haar
import cv2
import numpy as np
img = cv2.imread('./images/faces1.jpg')
# 转为灰度图
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 构造haar检测器 https://github.com/opencv/opencv/tree/master/data/haarcascades
face_detector = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml')
detections = face_detector.detectMultiscale(img_gray)
# 解析检测结果
for (x,y,w,h) in detections:
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),5)
detections = face_detector.detectMultiScale(img_gray,scaleFactor=1.3)
通过调整参数实现更优效果
Hog
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 安装dlib
# conda install -c conda-forge dlib
import dlib
plt.rcParams['figure.dpi'] = 200
img = cv2.imread('./images/faces2.jpg')
# 构造人脸解析器
hog_face_detector = dlib.get_frontal_face_detector()
# 检测人脸
detections = hog_face_detector(img,1)
# 解析矩形结果
for face in detections:
x = face.left()
y = face.top()
r = face.right()
b = face.bottom()
cv2.rectangle(img,(x,y),(r,b),(0,255,0),3)
CNN
# %%
# 导入相关包
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取照片
img = cv2.imread('./images/faces2.jpg')
# 安装DLIB
import dlib
# %%
# 构造CNN人脸检测器
cnn_face_detector = dlib.cnn_face_detection_model_v1('./weights/mmod_human_face_detector.dat')
# 检测人脸
detections = cnn_face_detector(img,1)
# 解析矩形结果
for face in detections:
x = face.rect.left()
y = face.rect.top()
r = face.rect.right()
b = face.rect.bottom()
#置信度
c = face.confidence
print(c)
cv2.rectangle(img,(x,y),(r,b),(0,255,0),5)
SSD与MTCNN我不经常使用就不多做介绍,下面进行人脸检测介绍
人脸检测
这里只对resnet的使用进行介绍。
resnet
文件夹架构如下:
- 1、图片数据预处理
- 2、加载模型
- 3、提取图片的68个关键点
- 4、预测图片:找到欧氏距离最近的特征描述符
- 5、评估测试数据集
# 导入包
import cv2
import numpy as np
import matplotlib.pyplot as plt
import dlib
# 人脸检测模型
hog_face_detector = dlib.get_frontal_face_detector()
# 关键点 检测模型
shape_detector = dlib.shape_predictor('./weights/shape_predictor_68_face_landmarks.dat')
# resnet模型
face_descriptor_extractor = dlib.face_recognition_model_v1('./weights/dlib_face_recognition_resnet_model_v1.dat')
# 提取单张图片的特征描述符,label
def getFaceFeatLabel(fileName):
# 获取人脸labelid
label_id = int(fileName.split('/')[-1].split('.')[0].split('subject')[-1])
# 读取图片
cap = cv2.VideoCapture(fileName)
ret,img = cap.read()
# 转为RGB
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#人脸检测
detections = hog_face_detector(img,1)
face_descriptor = None
for face in detections:
# 获取关键点
points = shape_detector(img,face)
# 获取特征描述符
face_descriptor = face_descriptor_extractor.compute_face_descriptor(img,points)
# 转为numpy 格式的数组
face_descriptor = [f for f in face_descriptor]
face_descriptor = np.asarray(face_descriptor,dtype=np.float64)
face_descriptor = np.reshape(face_descriptor,(1,-1))
return label_id,face_descriptor
# 对train文件夹进行处理
import glob
file_list =glob.glob('./yalefaces/train/*')
# 构造两个空列表
label_list = []
feature_list = None
name_list = {}
index= 0
for train_file in file_list:
# 获取每一张图片的对应信息
label,feat = getFaceFeatLabel(train_file)
#过滤数据
if feat is not None:
#文件名列表
name_list[index] = train_file
#label列表
label_list.append(label)
if feature_list is None:
feature_list = feat
else:
# 特征列表
feature_list = np.concatenate((feature_list,feat),axis=0)
index +=1
# 评估测试数据集
file_list =glob.glob('./yalefaces/test/*')
# 构造两个空列表
predict_list = []
label_list= []
# 距离阈值
threshold = 0.5
for test_file in file_list:
# 获取每一张图片的对应信息
label,feat = getFaceFeatLabel(test_file)
# 读取图片
cap = cv2.VideoCapture(test_file)
ret,img = cap.read()
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#过滤数据
if feat is not None:
# 计算距离
distances = np.linalg.norm((feat-feature_list),axis=1)
min_index = np.argmin(distances)
min_distance = distances[min_index]
if min_distance < threshold:
# 同一人
predict_id = int(name_list[min_index].split('/')[-1].split('.')[0].split('subject')[-1])
else:
predict_id = -1
predict_list.append(predict_id)
label_list.append(label)
cv2.putText(img,'True:'+str(label),(10,30),cv2.FONT_HERSHEY_COMPLEX_SMALL,1,(0,255,0))
cv2.putText(img,'Pred:'+str(predict_id),(10,50),cv2.FONT_HERSHEY_COMPLEX_SMALL,1,(0,255,0))
cv2.putText(img,'Dist:'+str(min_distance),(10,70),cv2.FONT_HERSHEY_COMPLEX_SMALL,1,(0,255,0))
# 显示
plt.figure()
plt.imshow(img)
人脸考勤机
'''
人脸注册:将人脸特征存进csv
人脸识别:将检测的人脸特征与csv中的人脸特征作比较,如果存在,则将考勤记录写入另一个csv
'''
import cv2
import numpy as np
import dlib
import time
import csv
# 人脸注册
def face_Register(label_id = 1,name='xiuye',count=3,interval=3):
'''
label_id 人脸ID
name 人脸姓名
count 采集数量
interval 采集间隔时间
'''
# 检测人脸
cap = cv2.VideoCapture(1)
# 获取长宽
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 构造人脸检测器
hog_face_detector = dlib.get_frontal_face_detector()
# 关键点检测器
shape_detector = dlib.shape_predictor('./face_recognition/weights/shape_predictor_68_face_landmarks.dat')
# 特征描述符
face_descriptor_extractor = dlib.face_recognition_model_v1('./weights/dlib_face_recognition_resnet_model_v1.dat')
# 开始时间
start_time = time.time()
# 执行次数
collect_count = 0
# csv Writer
f = open('./data/feature.csv','a',newline='')
csv_writer = csv.writer(f)
while True:
ret,frame = cap.read()
# 缩放
frame = cv2.resize(frame,(width//2,height//2))
# 镜像
frame = cv2.flip(frame,1)
# 转为灰度图
frame_gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
# 检测人脸
detections = hog_face_detector(frame,1)
#遍历人脸
for face in detections:
# 人脸坐标
l,t,r,b = face.left(),face.top(),face.right(),face.bottom()
# 获取人脸关键点 # 获取68个关键点
points = shape_detector(frame,face)
for point in points.parts():
cv2.circle(frame,(point.x,point.y),2,(0,255,0),-1)
# 矩形人脸框
cv2.rectangle(frame,(l,t),(r,b),(0,255,0),2)
# 采集
if collect_count < count:
# 当前时间
now_time = time.time()
if now_time - start_time > interval:
# 获取特征描述符
face_descriptor = face_descriptor_extractor.compute_face_descriptor(frame,points)
face_descriptor = [f for f in face_descriptor]
# 写入csv文件
line = [label_id,name,face_descriptor]
csv_writer.writerow(line)
collect_count+=1
print(('采集次数:{collect_count}'.format(collect_count=collect_count)))
start_time = now_time
else:
pass
else:
# 采集完毕
print('采集完毕')
return
# 显示画面
cv2.imshow('demo',frame)
# 退出条件
if cv2.waitKey(10) & 0xFF == ord('q'):
break
f.close()
cap.release()
cv2.destroyAllWindows()
# 获取并组装csv文件中的特征
def getFeatureList():
label_list = []
name_list = []
feature_list = None
with open('./data/feature.csv','r') as f:
csv_reader = csv.reader(f)
for line in csv_reader:
label_id = line[0]
label_list.append(label_id)
name = line[1]
name_list.append(name)
face_descriptor = eval(line[2])
face_descriptor = np.asarray(face_descriptor,dtype=np.float64)
face_descriptor = np.reshape(face_descriptor,(1,-1))
if feature_list is None:
feature_list = face_descriptor
else:
feature_list = np.concatenate((feature_list,face_descriptor),axis=0)
return label_list,name_list,feature_list
# 人脸识别
''''
1、实时获取视频中人脸的特征描述符
2、与库里特征做距离判断
3、找到预测值
4、结果存入csv
'''
def face_Recognizer(threshold):
# 检测人脸
cap = cv2.VideoCapture(1)
# 获取长宽
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 构造人脸检测器
hog_face_detector = dlib.get_frontal_face_detector()
# 关键点检测器
shape_detector = dlib.shape_predictor('./face_recognition/weights/shape_predictor_68_face_landmarks.dat')
# 特征描述符
face_descriptor_extractor = dlib.face_recognition_model_v1('./weights/dlib_face_recognition_resnet_model_v1.dat')
# 读取特征
label_list,name_list,feature_list = getFeatureList()
# 字典记录人脸识别记录
recog_record = {}
# csv写入
f = open('./data/attendance.csv','a')
csv_writer = csv.writer(f)
# 帧率信息
fps_time = time.time()
while True:
ret,frame = cap.read()
# 缩放
frame = cv2.resize(frame,(width//2,height//2))
# 镜像
frame = cv2.flip(frame,1)
# 检测人脸
detections = hog_face_detector(frame,1)
#遍历人脸
for face in detections:
# 人脸坐标
l,t,r,b = face.left(),face.top(),face.right(),face.bottom()
# 获取人脸关键点 # 获取68个关键点
points = shape_detector(frame,face)
# 获取特征描述符
face_descriptor = face_descriptor_extractor.compute_face_descriptor(frame,points)
face_descriptor = [f for f in face_descriptor]
# 计算距离
face_descriptor = np.asarray(face_descriptor,dtype=np.float64)
# face_descriptor = np.reshape(face_descriptor,(1,-1))
distances = np.linalg.norm((face_descriptor-feature_list),axis=1)
# 最短索引
min_index = np.argmin(distances)
# 最短距离
min_distance = distances[min_index]
if min_distance < threshold:
predict_id = label_list[min_index]
predict_name = name_list[min_index]
cv2.putText(frame,predict_name + str(round(min_distance,2)),(l,b+40),cv2.FONT_HERSHEY_COMPLEX_SMALL,2,(0,255,0),1)
now = time.time()
need_insert = False
# 判断是否识别过
if predict_name in recog_record:
pass
# 隔一段时间再存
if now - recog_record[predict_name] > 3:
# 超过阈值时间 再存一次
need_insert = True
recog_record[predict_name] = now
else:
need_insert = False
pass
else:
need_insert = True
recog_record[predict_name] = now
# 存入csv文件
if need_insert:
time_local = time.localtime(recog_record[predict_name])
time_str = time.strftime("%Y-%m-%d %H:%M:%S",time_local)
line = [ predict_id,predict_name,time_str]
csv_writer.writerow(line)
print('写入成功:{name},{time}'.format(name=predict_name,time=time_str))
else:
print('未识别')
# 矩形人脸框
cv2.rectangle(frame,(l,t),(r,b),(0,255,0),2)
# 计算帧率
now = time.time()
fps = 10/(now - fps_time)
fps_time = now
cv2.putText(frame,str(round(fps,2)),(20,30),cv2.FONT_HERSHEY_COMPLEX_SMALL,2,(0,255,0),1)
# 显示画面
cv2.imshow('demo',frame)
# 退出条件
if cv2.waitKey(10) & 0xFF == ord('q'):
break
f.close()
cap.release()
cv2.destroyAllWindows()
# face_Register()
face_Recognizer(0.5)
2 条评论
码人牛P
我菜