热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python实现多人脸识别

本篇文章是使用python通过调用电脑摄像头实时检测摄像头画面识别画面中的人脸这里的python版本是3.9,各个版本思路上相似我的大体思路是:采集

本篇文章是使用python通过调用电脑摄像头实时检测摄像头画面识别画面中的人脸

这里的python版本是3.9,各个版本思路上相似

我的大体思路是:采集人脸数据---->训练模型---->实现人脸识别

第一步:采集人脸数据

首先要导入cv库

import cv2

如果没有opencv库的话要用pip先安装一个

pip install opencv-python

采集人脸要用到调用摄像头

capture = cv2.VideoCapture(1)

在这里需要说明的是代码后面括号里的数字1代表着调用外接的摄像头,0是调用电脑的摄像头

调用完结束就开始读取画面了

success, frame = capture.read()
# success用来判断摄像头是否调用成功,frame代表捕捉的每一帧图像

读取完之后要转换为灰度图像

转换灰度图像有个好处就是提高图像的准确度,说到灰度就想起来华为之前的一部手机—华为P9,双摄设计,其中一个就是黑白镜头,因为这颗黑白镜头而大大提高了成像质量

gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

在这里需要调用一个叫分类器的东西,这个文件我是从官网上下载的

网址:Home - OpenCV

 然后点击library---->release

 我下载的版本号是4.5.5,仅供参考

下载解压,解压之后进入opencv文件夹,找到这个路径:opencv\sources\data\haarcascades

然后导入分类器

face_detect = cv2.CascadeClassifier('填xml文件路径,例opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')
# 路径要具体到文件然后再跟上文件的名字face = face_detect.detectMultiScale(gray, 1.01, 5, 0, (100, 100), (300, 300))
# 框定人脸区域

 然后用for循环实时刷新,注意缩进

for x, y, w, h in face:# x,y指横纵坐标,左上角开始,h为高,w为宽cv2.rectangle(frame, (x, y), (x + w, y + h), color=(0, 0, 225), thickness=2)

然后开启摄像头窗口

# 开启窗口
cv2.imshow('result', frame)

后面再用waitkey保持画面的连续

c = cv2.waitKey(1)

加一个if判断,用来保存捕捉的图片和退出程序

if ord('k') == cv2.waitKey(1):cv2.imwrite('D:/testPhoto/lq/' + str(num) + '.jpg',frame)print(str(num),'保存成功')num += 1
if ord('q') == cv2.waitKey(1): # 按下q退出break

最后整个文件的代码是这样的:

import cv2num = 1
capture = cv2.VideoCapture(0) # 0为电脑内置摄像头 使用电脑摄像头时为0,使用外接摄像头时为1
while (True):# 摄像头读取,success为是否成功打开摄像头,true,false。 frame为视频的每一帧图像success, frame = capture.read()# frame = cv2.flip(frame, 1) # 摄像头是和人对立的,将图像左右调换回来正常显示。# 将采集到的图像转换为灰度图像,提高识别度gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 导入分类器face_detect = cv2.CascadeClassifier('D:/code/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')face = face_detect.detectMultiScale(gray, 1.01, 5, 0, (100, 100), (300, 300))# 框入人脸,for循环用来实时刷新for x, y, w, h in face:# x,y指横纵坐标,左上角开始,h为高,w为宽cv2.rectangle(frame, (x, y), (x + w, y + h), color=(0, 0, 225), thickness=2)# 开启窗口cv2.imshow('result', frame)# 用waitKey保持画面连续c = cv2.waitKey(1)if ord('k') == cv2.waitKey(1):cv2.imwrite('D:/testPhoto/lq/' + str(num) + '.jpg',frame)print(str(num),'保存成功')num += 1if ord('q') == cv2.waitKey(1): # 按下q退出breakcv2.destroyAllWindows()

while循环是用来保持摄像头画面的,num的作用是用来记录照片保存了多少张

第二步:训练模型

这里需要用到pillow库,需要用到pip下载

pillow简单来说就是可以为python提供图像处理功能

pip install pillow

首先需要用到一行代码,他的功能就是连接目录与文件名或目录,生成一个列表,列举文件夹下所有的文件

ImagePaths = [os.path.join(path, f) for f in os.listdir(path)]

建立一个存放数据的集合

facesSamples = []
ids = []

然后再一次调用分类器

face_detector = cv2.CascadeClassifier()
# 括号内跟分类器路径

然后用for循环遍历所有的图片并且进一步处理图片

for ImagePath in ImagePaths:# 将图片转换为灰度图片img = Image.open(ImagePath).convert('L')# 将图像转换为数组img_numpy = np.array(img, 'uint8')# 为了获取id,将图片和路径分裂并获取faces = face_detector.detectMultiScale(img_numpy)id = 1# 将获取的图片和id添加到list中for x, y, w, h in faces:ids.append(id)facesSamples.append(img_numpy[y:y + h, x:x + w])print('id:', id)print('fs:', facesSamples)return facesSamples, ids

在末尾部分设置了图片路径和yml文件保存的地址等信息

# 图片路径path = 'D:/testPhoto/sjs/'# 获取图像数组和id标签数组faces, ids = get_image_lable(path)# 加载识别器recognizer = cv2.face.LBPHFaceRecognizer_create()# 训练模型recognizer.train(faces, np.array(ids))# 保存模型recognizer.write('D:/testPhoto/sjs/train.yml')

训练模型这部分整体的代码是这样子的

import cv2
import os
from PIL import Image
import numpy as npdef get_image_lable(path):ImagePaths = [os.path.join(path, f) for f in os.listdir(path)]# 新建集合存放数据facesSamples = []ids = []# 调用分类器face_detector = cv2.CascadeClassifier('D:/code/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')for ImagePath in ImagePaths:# 将图片转换为灰度图片img = Image.open(ImagePath).convert('L')# 将图像转换为数组img_numpy = np.array(img, 'uint8')# 为了获取id,将图片和路径分裂并获取faces = face_detector.detectMultiScale(img_numpy)id = 1# 将获取的图片和id添加到list中for x, y, w, h in faces:ids.append(id)facesSamples.append(img_numpy[y:y + h, x:x + w])print('id:', id)print('fs:', facesSamples)return facesSamples, idsif __name__ == '__main__':# 图片路径path = 'D:/testPhoto/sjs/'# 获取图像数组和id标签数组faces, ids = get_image_lable(path)# 加载识别器recognizer = cv2.face.LBPHFaceRecognizer_create()# 训练模型recognizer.train(faces, np.array(ids))# 保存模型recognizer.write('D:/testPhoto/sjs/train.yml')cv2.destroyAllWindows()

第三步:实时识别

这里识别人脸采用的算法是LBPH

recognizer_sjs = cv2.face.LBPHFaceRecognizer_create()
recognizer_jhs = cv2.face.LBPHFaceRecognizer_create()

recognizer_sjs这个是我自己起的名字,可以根据个人喜好更换

将之前训练好的模型导入

recognizer_sjs.read('D:/train.yml/')

具体的路径因人而异

到这一步,再次调用分类器

cascade_path = "D:/code/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml"
face_cascade = cv2.CascadeClassifier(cascade_path)

设置好名字,可能是我的原因,在我的电脑上没办法用中文的字体标注出来,所以建议还是用英文的字体

idum_sjs = 0
idum_jhs = 1
names = ['fxxtsjs','jhs']

这里的idum后面设定的数字和下面的name是对应的,比如说我这个设定的idum_sjs名字就是fxxtsjs,往下顺延即可

加载标注名字所用的字体,我选择的是opencv自带的

fOnt= cv2.FONT_HERSHEY_SIMPLEX

然后就可以打开摄像头了

cam = cv2.VideoCapture(0)
minW = 0.1 * cam.get(3)
minH = 0.1 * cam.get(4)

下面需要添加一个while循环,用来确保摄像头画面连续不间断

while True:ret, img = cam.read()gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 识别人脸faces = face_cascade.detectMultiScale(gray,scaleFactor=1.2,minNeighbors=5,minSize=(int(minW), int(minH)))

紧接着添加一个for循环,让识别的框一直出现在画面上

for (x, y, w, h) in faces:cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)idnum_sjs, confidence_sjs = recognizer_sjs.predict(gray[y:y + h, x:x + w])idnum_jhs, confidence_jhs = recognizer_jhs.predict(gray[y:y + h, x:x + w])

然后开始计算识别结果

if confidence_sjs <50:idnum_sjs = names[idum_sjs]cv2.putText(img, str(idnum_sjs), (x + 5, y - 5), font, 1, (0, 0, 255), 1)
elif confidence_jhs <50:idnum_jhs = names[idum_jhs]cv2.putText(img, str(idnum_jhs), (x + 5, y - 5), font, 1, (0, 0, 255), 1)
else:idnum = &#39;unknown&#39;

最后展现画面

cv2.imshow(&#39;camera&#39;, img)

实时识别的整体代码如下

# -----检测、校验并输出结果-----
import cv2# 准备识别方法
recognizer_sjs = cv2.face.LBPHFaceRecognizer_create()
recognizer_jhs = cv2.face.LBPHFaceRecognizer_create()
# 引用之前的模型
recognizer_sjs.read(&#39;D:/testPhoto/sjs/train.yml/&#39;)
recognizer_jhs.read(&#39;D:/testPhoto/jhs/train.yml/&#39;)
# 调用人脸分类器
cascade_path = "D:/code/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml"
face_cascade = cv2.CascadeClassifier(cascade_path)
# 加载一个字体,以便标注
fOnt= cv2.FONT_HERSHEY_SIMPLEX
# 设置ID与标注的name
idum_sjs = 0
idum_jhs = 1
names = [&#39;fxxtsjs&#39;,&#39;jhs&#39;]# 调用摄像头
cam = cv2.VideoCapture(0)
minW = 0.1 * cam.get(3)
minH = 0.1 * cam.get(4)while True:ret, img = cam.read()gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 识别人脸faces = face_cascade.detectMultiScale(gray,scaleFactor=1.2,minNeighbors=5,minSize=(int(minW), int(minH)))# 进行校验for (x, y, w, h) in faces:cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)idnum_sjs, confidence_sjs = recognizer_sjs.predict(gray[y:y + h, x:x + w])idnum_jhs, confidence_jhs = recognizer_jhs.predict(gray[y:y + h, x:x + w])# 计算出一个检验结果if confidence_sjs <50:idnum_sjs = names[idum_sjs]# 注上姓名cv2.putText(img, str(idnum_sjs), (x + 5, y - 5), font, 1, (0, 0, 255), 1)elif confidence_jhs <50:idnum_jhs = names[idum_jhs]# 注上姓名cv2.putText(img, str(idnum_jhs), (x + 5, y - 5), font, 1, (0, 0, 255), 1)else:idnum = &#39;unknown&#39;# 展示结果cv2.imshow(&#39;camera&#39;, img)k = cv2.waitKey(20)if k == 27:breakelif ord(&#39;q&#39;) == cv2.waitKey(1): # 按下q退出break# 释放资源
cam.release()
cv2.destroyAllWindows()

 我做出来的效果是这样的

最后提几点注意的地方:

1.人脸识别是我自己第一次做,所以上面的这些代码还有些不完美的地方,欢迎大家在评论区留言     并提出宝贵的意见,我会认真阅读并采纳

2.这段代码可以实现录入多个人脸,并且可以同时实时识别,添加其他人脸的时候需要注意路径的     正确与否,第三部添加多个人脸的地方就是在几乎每个出现sjs和jhs的地方,第三步添加人脸需     要改动的好像有准备识别方法中的recognize,下面的id名字,name中的名称以及标注姓名那里


推荐阅读
  • 展开全部下面的代码是创建一个立方体Thisexamplescreatesanddisplaysasimplebox.#Thefirstlineloadstheinit_disp ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • 使用Spring AOP实现切面编程的步骤和注意事项
    本文介绍了使用Spring AOP实现切面编程的步骤和注意事项。首先解释了@EnableAspectJAutoProxy、@Aspect、@Pointcut等注解的作用,并介绍了实现AOP功能的方法。然后详细介绍了创建切面、编写测试代码的过程,并展示了测试结果。接着讲解了关于环绕通知的使用方法,并修改了FirstTangent类以添加环绕通知方法。最后介绍了利用AOP拦截注解的方法,只需修改全局切入点即可实现。使用Spring AOP进行切面编程可以方便地实现对代码的增强和拦截。 ... [详细]
  • 如何优化Webpack打包后的代码分割
    本文介绍了如何通过优化Webpack的代码分割来减小打包后的文件大小。主要包括拆分业务逻辑代码和引入第三方包的代码、配置Webpack插件、异步代码的处理、代码分割重命名、配置vendors和cacheGroups等方面的内容。通过合理配置和优化,可以有效减小打包后的文件大小,提高应用的加载速度。 ... [详细]
  • 从批量eml文件中提取附件的Python代码实现方法
    本文介绍了使用Python代码从批量eml文件中提取附件的实现方法,包括获取eml附件信息、递归文件夹下所有文件、创建目的文件夹等步骤。通过该方法可以方便地提取eml文件中的附件,并保存到指定的文件夹中。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文介绍了如何在wxpython中将matplotlib图表嵌入到自定义窗体中的方法。通过调用FigureCanvasWx类,可以实现在自定义窗体中显示matplotlib图表。同时,还介绍了与此相关的一些类和参数。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • 这篇文章主要介绍了Python拼接字符串的七种方式,包括使用%、format()、join()、f-string等方法。每种方法都有其特点和限制,通过本文的介绍可以帮助读者更好地理解和运用字符串拼接的技巧。 ... [详细]
  • RouterOS 5.16软路由安装图解教程
    本文介绍了如何安装RouterOS 5.16软路由系统,包括系统要求、安装步骤和登录方式。同时提供了详细的图解教程,方便读者进行操作。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
author-avatar
我可不是文章
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有