Python开发系统实战项目:人脸识别门禁监控系统
前段时间来到中关村重庆基地实训,老师要求每人提交一张本人白底免冠照片用于录入门禁监控系统,我当时想:好高级哇,一张照片就可以耶;神经网络训练模型还得好多张图片不断轮次迭代才能产生好的效果呢。当时的我非常好奇,心生崇拜之意,一直梦想着自己也能开发出这样一个系统,然而,不久之后的现在,成功了!回头再看门口那个门禁监控系统:呵~不过如此!
目录
1 人脸识别应用所涉及到的功能模块
2 人脸识别的基本过程
2.1 dlib 库的安装与实例解析
2.2 face_recognition 库的安装与实例解析
2.2.1 load_image_file
2.2.2 face_locations
2.2.3 face_landmarks
2.2.4 face_encodings
2.2.5 compare_faces
2.2.6 获取摄像头的图像信息
3 实现人脸识别的监控系统
3.1 人脸识别监控系统
3.2 眨眼活体检测
1 人脸识别应用所涉及到的功能模块
- 摄像头调用
- 脸部图像识别和处理
- 活体检测
- 多线程的应用
- 定时器的调用
2 人脸识别的基本过程
- 人脸的 68 个基本特征点位置以及顺序。判断 68 个特征点在图像上面是否存在、是否完整;
- 人脸 detect,这一步主要就是定位人脸在图像中的位置,利用目标检测算法输出人脸位置矩形框;
- 人脸 shape predictor,这一步就是要找出眼睛眉毛鼻子嘴巴具体的点位;
- 人脸对齐 alignment,这一步主要是通过投影几何变换出一张标准脸;
- 人脸识别,这一步就是在对挤的人脸图像上提取 128 维的特征向量,根据特征向量间的距离来进行判断识别。
python 中最常用的人脸识别库是基于 C++ 开发的 dlib 库。
2.1 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 iodetector = 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()
2.2 face_recognition 库的安装与实例解析
face_recognition 库是基于 dlib 进行了二次封装,号称世界上最简洁的人脸识别库。
训练数据集:Labeled Faces in the Wild,13000 多人脸作为训练数据集,识别效果取决于样本的数量以及质量。
windows 上安装: pip install -i https://pypi.douban.com/simple face_recognition
2.2.1 load_image_file
load_image_file 这个方法主要用于加载要识別的人脸图像,加载返回的数据是 Numpy 数組,记录了图片的所有像素的特征向量。
# -*-coding:GBK -*-
import face_recognitionimage = face_recognition.load_image_file('E:/girl.jpg')
print(image)
2.2.2 face_locations
face_locations 定位图中所有的人脸的像素位置。
- 返回值是一个列表形式,列表中每一行是一张人脸的位置信息,包括[top, right, bottom, left],也可以认为每个人脸就是一组元组信息。主要用于标识图像中所有的人脸信息。
# -*-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()
2.2.3 face_landmarks
face_landmarks 识别人脸关键特征点。
- 参数仍然是待检测的图像对象,返回值是包含面部特征点字典的列表,列表长度就是图像中的人脸数。
- 面部特征包括以下几个部分:nose_bridge (鼻梁)、right _eyebrow (右眼眉)、left_eyebrow (左眼眉)、right_eye(右眼)、left_eye(左眼)、chin(下巴)、 nose_tip(下鼻部)、bottom_lip (下嘴唇)
- 勾勒脸部大体轮廓
# -*-coding:GBK -*-
import face_recognition
from PIL import Image, ImageDrawimage = 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()
2.2.4 face_encodings
face_encodings 获取图像文件中所有面部编码信息。
- 返回值是一个编码列表,参数仍然是要识别的图像对象。如果后续访问时,需要注意加上索引或遍历来进行访问。每张人脸的编码信息是一个 128 维向量。
- 面部编码信息是进行人像对比的重要参数。
# -*-coding:GBK -*-
import face_recognitionimage = 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))
2.2.5 compare_faces
compare_faces 由面部编码信息进行面部识别匹配。
- 主要用于匹配两个面部特征编码,利用这两个特征向量的内积来衡量相似度,根据阈值确认是否是同一个人。
- 第一个参数就是一个面部编码列表(很多张脸), 第二个参数就是给出单个面部编码(一张脸), compare_faces 会将第二个参数中的编码信息与第一个参数中的所有编码信息依次匹配,返回值是一个布尔列表,匹配成功则返回 True,匹配失败则返回 False,顺序与第一个参数中脸部编码顺序一致。
- 参数里有一个 tolerance = 0.6,大家可以根据实际的效果进行调整,一般经验值是 0.39。
tolerance 值越小,匹配越严格。
# -*-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)
2.2.6 获取摄像头的图像信息
我们可以利用 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)breakcap.release()
3 实现人脸识别的监控系统
整理人脸识别监控系统主要功能:
- 打开摄像头读取图像 ok
- 与已知人物头像进行对比,识别哪些是已知人员,哪些是未知人员 ok
- 在摄像头图像上直接标注对比结果 ok
- 记录每次对比的结果,并将未知人员的图像进行保存
- 活体检测
3.1 人脸识别监控系统
# -*-coding:GBK -*-
import face_recognition
import os
import cv2
from PIL import Image, ImageFont, ImageDraw
import numpy as np
import datetime
import threadingclass Recorder:passrecord_dic = {}
unknown_pic = []flag_over = 0 # 定义一个是否进行来访记录的标记
# 定时去保存对比图像信息,并且将位置人员的图像保存下来
def save_recorder(name, frame):global record_dicglobal flag_overglobal unknown_picif flag_over == 1: returntry:record = record_dic[name]seconds_diff = (datetime.datetime.now() - record.times[-1]).total_seconds()if seconds_diff < 60 * 10:returnrecord.times.append(datetime.datetime.now())print('更新记录', record_dic, record.times)except KeyError:newRec = Recorder()newRec.times = [datetime.datetime.now()]record_dic[name] = newRecprint('添加记录', 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,filenamesfacelib, 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 *= 4right *= 4bottom *= 4left *= 4cv2.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'):breakvideo_capture.release()
3.2 眨眼活体检测
# -*-coding:GBK -*-
from scipy.spatial import distance
import dlib
import cv2
from imutils import face_utilsdef 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-1frame_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 += 1else:if frame_counter >= EAR_CONSEC_FRAMES:print('眨眼检测成功,请进入')frame_counter += 1breakframe_counter = 0cv2.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)breakcap.release()
cv2.destroyAllWindows()
Python开发系统实战项目:人脸识别门禁监控系统相关推荐
- python人脸识别门禁系统_树莓派人脸识别门禁系统图文教程
前面发布了人脸识别门禁系统的系列视频教程,现在补上图文版,方便查看指令和代码,这篇文章也是对之前的文章的更新与完善. 本系统中树莓派调用百度智能云人脸识别API,实现人脸识别门禁,主要分为三个模块来实 ...
- python人脸识别门禁系统_智能人脸识别门禁系统
龙源期刊网 http://www.qikan.com.cn 智能人脸识别门禁系统 作者:吕琳涵 朱畅 钟华 林晓毅 来源:<世界家苑 · 学术> 2018 年第 12 期 摘 要:此项目是 ...
- python人脸识别门禁系统毕设_人脸识别门禁系统 毕业设计 可移植树莓派
[实例简介] 基于python的人脸识别门禁系统,实现对人脸的录入与识别功能 ,毕业设计 附论文 可移植树莓派 [实例截图] [核心代码] 人脸识别毕业设计源码 └── 人脸识别毕业设计源码 ├── ...
- 人脸识别小区门禁系统_小区人脸识别门禁系统安全吗?
人脸识别门禁系统主要是通过上传人脸图片,通过系统算法采集人脸特征,然后储存在人脸特征数据库上.当有人员通过时,摄像头抓取人脸图片与后台庞大的人脸模板进行对比,确认是否是社区或楼层住户就可以自由通行.获 ...
- python 语音识别机器人控制系统_python人脸识别+语音识别 的监控系统
使用流程 添加成员-->训练模型-->监控 注:添加成员后,数据仅仅保存在后台,并没有在模型里.所以此时监控,就没有这次新添加的成员.只有训练模型后才会存入在模型里 主页 添加成员 ...
- python人脸识别门禁系统生产厂家_人脸识别门禁硬件生产厂家
随着现代科技的不断发展,现在的中国已经迈入5G时代,人工智能技术也正逐步广泛运用到了各行各业中,尤其人脸识别技术,已在各大行业中广泛使用. 人脸识别技术是基于人的脸部特征信息进行身份识别的生物识别技术 ...
- 无法识别的配置节appsettings_人脸识别门禁考勤系统安装使用注意事项
人脸识别门禁考勤系统安装使用注意事项 1.正常步骤安装人脸识别门禁考勤系统后,配置需要连接的数据库[DATABASE](如果使用非人脸识别门禁考勤系统自带的mysql,修改attsite.ini文件) ...
- python人脸识别门禁_树莓派人脸识别门禁系统图文教程
前面发布了人脸识别门禁系统的系列视频教程,现在补上图文版,方便查看指令和代码,这篇文章也是对之前的文章的更新与完善. 本系统中树莓派调用百度智能云人脸识别API,实现人脸识别门禁,主要分为三个模块来实 ...
- python人脸识别门禁系统毕设_树莓派人脸识别门禁系统代码以及代码分析——opencv拍照调用FACE++处理...
树莓派人脸识别门禁系统的总体设计 硬件包括:树莓派3B.电源模块.转5V降压模块.触摸感应传感器模块.声光报警模块和驱动模块. 由此设计出的人脸识别门禁系统总体结构框图如下: 总体结构框图 程序运行时 ...
最新文章
- PHP文件上传,下载,Sql工具类!
- 机器学习第10天:模型评价方法及代码实现
- Python:利用python语言绘制多个子图经典案例、代码实现之详细攻略
- 新天龙官网服务器更新消息,新天龙八部怀旧服太火,增开7组服务器不够用,还得继续扩容...
- java数组重复_JAVA数组去除重复数据
- C语言学习笔记---字符读取函数scanf()、gets()、fgets()
- python判断字符串出现的次数_【如何判断python字符串出现次数?这几种方法你一定要学会】- 环球网校...
- Python基础-函数,高阶函数
- python基础知识——文件
- 细说PHP(精要版)
- 如何让电脑快速蓝屏(只是个玩笑)
- 【Java 8 新特性】Java Map compute() 示例 | 指定 key 的值进行计算后替换
- mysql外文文献中英文3千字_MySQL数据库管理外文中英文翻译文献.doc
- 嵌入式设备开发专题《NB-IoT开发,解读SIM卡、USIM卡、UICC卡、eSIM卡的区别》
- 计算H时M分S秒以后是_消防考试必会计算题汇总!
- 分享几个css素材的网站
- 四川嘉弘恒信:拼多多双11红包怎么用
- Visual Studio代码:高级用户指南
- 拍照翻译软件 拍照识别 云脉慧眼
- npm install下载依赖项时报错 fatal: unable to access ‘https://github.com/nhn/raphael.git/‘: Failed to connect
热门文章
- 华为云桌面——云端上“最卷的云”
- 【模拟】仙人球的残影
- aws ec2 linux 密码,AWS EC2 丢失密钥处理办法
- Linux平台基于socket的文件传输服务器和客户端
- 安徽省计算机二级考试vfp试题,安徽省计算机二级VFP考试理论模拟试题附答案
- Coding and Paper Letter(八十一)
- matlab函数purelin
- 好用的录音转文字方法
- 关于《概率论与数理统计》最全假设检验总结
- endnote参考文献排版_Endnote 导入参考文献的时候,格式错误太多了。是否有什么解决办法?...