目录
2.2 face_recognition 库的安装与实例解析
python 中最常用的人脸识别库是基于 C++ 开发的 dlib 库。
dlib 库需要单独安装,dlib 库目前已经编译好的安装版本只支持 python 3.6 的版本。
这里再提供一个 python 3.7 版本的 dlib 库 whl 文件:链接:https://pan.baidu.com/s/1Fch0AqhZTmql7MpFyEDtYA 提取码:re7z
# -*-coding:GBK -*-
import dlib
from skimage import io
detector = dlib.get_frontal_face_detector() # 获取一个脸部检测器,这个监测器包含了脸部检测算法
win = dlib.image_window()
img = io.imread('E:/girl.png') # 读取带辨别的图像
# 利用脸部检测器读取待检测的图像数据,第二个参数1代表读取图片像素并放大1倍以便能够收集到更多的照片细节
# 返回结果是一组人脸区域的数据
ders = detector(img, 1)
win.set_image(img)
win.add_overlay(ders)
dlib.hit_enter_to_continue()
face_recognition 库是基于 dlib 进行了二次封装,号称世界上最简洁的人脸识别库。
训练数据集:Labeled Faces in the Wild,13000 多人脸作为训练数据集,识别效果取决于样本的数量以及质量。
windows 上安装: pip install -i https://pypi.douban.com/simple face_recognition
load_image_file 这个方法主要用于加载要识別的人脸图像,加载返回的数据是 Numpy 数組,记录了图片的所有像素的特征向量。
# -*-coding:GBK -*-
import face_recognition
image = face_recognition.load_image_file('E:/girl.jpg')
print(image)
face_locations 定位图中所有的人脸的像素位置。
# -*-coding:GBK -*-
import face_recognition
from PIL import Image
import cv2
# 通过 load_image_file 方法加载待识别图片
image = face_recognition.load_image_file('E:/girls.jpg')
# 通过 face_locations 得到图像中所有人脸位置
face_locations = face_recognition.face_locations(image)
for face_location in face_locations:
top, right, bottom, left = face_location # 结报操作,得到每张人脸的四个位置信息
print("已识别到人脸部位,限速区域为:top{}, right{}, bottom{}, left{}".format(top, right, bottom, left))
# face_image = image[top:bottom, left:right]
# pil_image = Image.fromarray(face_image)
# pil_image.show()
start = (left, top)
end = (right, bottom)
# 在图片上绘制矩形框
cv2.rectangle(image, start, end, (0,0,255), thickness=2)
cv2.imshow('window', image)
cv2.waitKey()
face_landmarks 识别人脸关键特征点。
# -*-coding:GBK -*-
import face_recognition
from PIL import Image, ImageDraw
image = face_recognition.load_image_file('E:/boys.jpg')
face_landmarks_list = face_recognition.face_landmarks(image)
pil_image = Image.fromarray(image)
d = ImageDraw.Draw(pil_image) # 生成一张PIL图像
for face_landmarks in face_landmarks_list:
facial_features = [
'chin',
'left_eyebrow',
'right_eyebrow',
'nose_bridge',
'nose_tip',
'left_eye',
'right_eye',
'bottom_lip'
]
for facial_feature in facial_features:
# print("每个人的面部特征显示在以下为位置:{}".format(facial_feature))
d.line(face_landmarks[facial_feature], width=5) # 直接调用PIL中的line方法在PIL图像中绘制线条,帮助我们观察特征点
pil_image.show()
face_encodings 获取图像文件中所有面部编码信息。
# -*-coding:GBK -*-
import face_recognition
image = face_recognition.load_image_file('E:/boys.jpg')
# 不管图像中有多少个人脸信息,返回值都是一个列表
face_encodings = face_recognition.face_encodings(image)
for face_encoding in face_encodings:
print("信息编码长度为:{}\n编码信息为:{}".format(len(face_encoding), face_encoding))
compare_faces 由面部编码信息进行面部识别匹配。
# -*-coding:GBK -*-
import face_recognition
# 加载一张合照
image1 = face_recognition.load_image_file('./facelib/yangmi+liukaiwei.jpeg')
# 加载一张单人照
image2 = face_recognition.load_image_file('./facelib/yangmi.jpg')
known_face_encodings = face_recognition.face_encodings(image1)
# face_encodings返回的是列表类型,我们只需要拿到第一个人脸编码即可
compare_face_encodings = face_recognition.face_encodings(image2)[0]
# 注意第二个参数,只能是答案个面部特征编码,不能传列表
matches = face_recognition.compare_faces(known_face_encodings, compare_face_encodings)
print(matches)
我们可以利用 cv2 模块中的 VideoCapture 方法,然后每次读取其中的一帧图像进行处理即可。
# -*-coding:GBK -*-
import cv2
from PIL import Image, ImageDraw
import numpy as np
# 1.调用摄像头
# 2.读取摄像头图像信息
# 3.在图像上添加文字信息
# 4.保存图像
cap = cv2.VideoCapture(0) # 调用第一个摄像头信息
while True:
ret, frame = cap.read()
# BGR是cv2 的图像保存格式,RGB是PIL的图像保存格式,在转换时需要做格式上的转换
img_PIL = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
draw = ImageDraw.Draw(img_PIL)
draw.text((100, 100), 'press q to exit', fill=(255, 255, 255))
# 将frame对象转换成cv2的格式
frame = cv2.cvtColor(np.array(img_PIL), cv2.COLOR_RGB2BGR)
cv2.imshow('capture', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
cv2.imwrite('out.jpg', frame)
break
cap.release()
整理人脸识别监控系统主要功能:
# -*-coding:GBK -*-
import face_recognition
import os
import cv2
from PIL import Image, ImageFont, ImageDraw
import numpy as np
import datetime
import threading
class Recorder:
pass
record_dic = {}
unknown_pic = []
flag_over = 0 # 定义一个是否进行来访记录的标记
# 定时去保存对比图像信息,并且将位置人员的图像保存下来
def save_recorder(name, frame):
global record_dic
global flag_over
global unknown_pic
if flag_over == 1: return
try:
record = record_dic[name]
seconds_diff = (datetime.datetime.now() - record.times[-1]).total_seconds()
if seconds_diff < 60 * 10:
return
record.times.append(datetime.datetime.now())
print('更新记录', record_dic, record.times)
except KeyError:
newRec = Recorder()
newRec.times = [datetime.datetime.now()]
record_dic[name] = newRec
print('添加记录', record_dic, newRec.times)
if name == '未知头像':
s = str(record_dic[name].times[-1])
# print(s)
# 未知人员的图片名称
filename = s[:10]+s[-6:] + '.jpg'
cv2.imwrite(filename, frame)
unknown_pic.append(filename)
# 解析已有人员的所有照片并得到照片名和人物面部编码信息
def load_img(path):
print('正在加载已知人员的图片...')
for dirpath, dirnames, filenames in os.walk(path):
print(filenames)
facelib = []
for filename in filenames:
filepath = os.sep.join([dirpath, filename])
# 把对应每张图片加载进来
face_image = face_recognition.load_image_file(filepath)
face_encoding = face_recognition.face_encodings(face_image)[0]
facelib.append(face_encoding)
return facelib,filenames
facelib, facenames = load_img('facelib')
# print(facenames)
video_capture = cv2.VideoCapture(0)
while True:
ret, frame = video_capture.read()
# 通过缩小图片(缩小为1/4),提高对比效率
small_frame = cv2.resize(frame, (0,0), fx=0.25, fy=0.25)
rgb_small_frame = small_frame[:,:,::-1] # 将opencv的BGR格式转换为RGB格式
face_locations = face_recognition.face_locations(rgb_small_frame)
face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)
face_names = []
# 循环多张人脸
for face_encoding in face_encodings:
matches = face_recognition.compare_faces(facelib, face_encoding, tolerance=0.39)
name = '未知头像'
if True in matches:
# 如果摄像头里面的头像匹配了已知人物头像,则取出第一个True的位置
first_match_index = matches.index(True)
name = facenames[first_match_index][:-4] # 取出文件上对应的人名
face_names.append(name)
for (top, right, bottom, left), name in zip(face_locations, face_names):
# 还原原图片大小
top *= 4
right *= 4
bottom *= 4
left *= 4
cv2.rectangle(frame, (left, top), (right, bottom), (0,0,255), thickness=2) # 标注人脸信息
img_PIL = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
font = ImageFont.truetype('simhei.ttf', 40)
draw = ImageDraw.Draw(img_PIL)
draw.text((left+6, bottom-6), name, font=font, fill=(255,255,255))
frame = cv2.cvtColor(np.asarray(img_PIL),cv2.COLOR_RGB2BGR)
save_recorder(name, frame)
cv2.imshow('capture', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
video_capture.release()
# -*-coding:GBK -*-
from scipy.spatial import distance
import dlib
import cv2
from imutils import face_utils
def eye_aspect_ratio(eye):
'''
计算EAR值
:param eye: 眼部特征点数组
:return: EAR值
'''
A = distance.euclidean(eye[1], eye[5])
B = distance.euclidean(eye[2], eye[4])
C = distance.euclidean(eye[0], eye[3])
return (A+B) / (2.0*C)
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
# 设置眼睛纵横比的阈值
EAR_THRESH = 0.3
# 我们假定连续3帧以上的EAR的值都小于阈值,才确认是产生了眨眼操作
EAR_CONSEC_FRAMES = 3
# 人脸特征点中对应眼睛的那几个特征点的序号
RIGHT_EYE_START = 37-1
RIGHT_EYE_END = 42-1
LEFT_EYE_START = 43-1
LEFT_EYE_END = 48-1
frame_counter = 0 # 连续帧的计数
blink_counter = 0 # 眨眼的计数
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 转化为灰度图像
rects = detector(gray, 1) # 人脸检测
if len(rects) > 0:
shape = predictor(gray, rects[0]) # 检测特征点
points = face_utils.shape_to_np(shape)
leftEye = points[LEFT_EYE_START:LEFT_EYE_END + 1] # 取出左眼特征点
rightEye = points[RIGHT_EYE_START:RIGHT_EYE_END + 1] # 取出右眼特征点
# 计算左右眼的EAR值
leftEAR = eye_aspect_ratio(leftEye)
rightEAR = eye_aspect_ratio(rightEye)
# 求左右眼EAR的平均值
ear = (leftEAR+rightEAR) / 2.0
# 实际判断一下眼轮廓部分代码并不是必须的
# 寻找左右眼的轮廓
leftEyeHull = cv2.convexHull(leftEye)
rightEyeHull = cv2.convexHull(rightEye)
# 绘制左右眼轮廓
cv2.drawContours(frame, [leftEyeHull], -1, (0,255,0), 1)
cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1)
# 如果EAR小于阈值,开始计算连续帧
if ear < EAR_THRESH:
frame_counter += 1
else:
if frame_counter >= EAR_CONSEC_FRAMES:
print('眨眼检测成功,请进入')
frame_counter += 1
break
frame_counter = 0
cv2.putText(frame, "COUNTER: {}".format(frame_counter), (150, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.putText(frame, "Blinks: {}".format(blink_counter), (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
# cv2.putText(frame, 'blink:{}'.format(blink_counter))
cv2.imshow('window', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
cv2.imwrite('out.jpg', frame)
break
cap.release()
cv2.destroyAllWindows()
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有