使用python的opencv实现人脸识别

简介:本项目主要使用python语言,主要的模块库有os,opencv-python,opencv-contrib-python。项目主要分为三个部分,人脸录入,训练数据,实现人脸的识别。本博客包含源代码,以及各个功能模块,需求分析的详细解释,当然本项目只是简单的实现人脸识别,可以在此基础上扩展。

一:项目功能及流程分析

我们项目的主要功能,也就是最终的实现效果是当我们打开摄像头后,在摄像头里会出现我的人脸头像,且对我的人脸进行识别,在画面中能够框出我的人脸部分并显示出画面中人脸的姓名。

项目主要包含以下三个大的模块:人脸录入、训练数据、人脸识别。

主要用到的模块:

  • os:为操作系统的访问提供相关功能的支持(处理文件和目录)
  • opencv-python:计算机视觉和机器学习软件库
  • opencv-contrib-python:opencv 的扩展模块

1、人脸录入模块。

主要目的:通过人脸录入模块去得到人脸的数据,然后通过已知数据去训练模型,得到人脸的姓名标签和人脸的一一对应关系,那么进行人脸的识别时,就能根据训练的数据去识别画面中的人脸是谁了,能够在画面中显示出它的名字。

主要功能:首先能打开摄像头,找到框出人脸的部分,且我们要对人脸部分截取保存,因为我们是训练姓名和人脸一一对应,所有别忘了保存图片的时候让用户输入姓名,为了减小图片大小,我们可以将截取的图片转化成灰度图片,不需要彩色的。步骤如下:

  • 打开摄像头。
  • 输入人脸对应的姓名。
  • 检测画面中的人脸部分。
  • 保存人脸图片。(灰度图片,不需要彩色)

 2、数据训练模块。

主要目的:通过保存的数据,使用模块自带的训练器,训练得到姓名和人脸的一一对应关系。

主要功能:读取文件的 图片和姓名,开始训练数据,训练结束将数据保存。步骤如下:

  • 读取保存的全部灰度图片和姓名。
  • 训练数据。
  • 保存数据。

 3、人脸识别模块。

 主要目的:根据所训练的数据,能够在我们打开摄像头的时候,标记出画面中的人脸部分,且在画面中显示人脸的姓名。

主要功能:能够打开摄像头,能够框出画面中的人脸部分,能够识别画面中的人脸并在画面中显示人脸的姓名。步骤如下:

  • 打开摄像头。
  • 检测人脸部分,框出人脸。
  • 进行人脸识别,在画面中显示人脸姓名。

二:项目具体实现代码及结果演示

1、建立项目文件

我们将本项目中用到一些路径定义为宏,保存到python文件中,命名为hong,py。将人脸灰度照片保存到文件夹中,建立文件夹data。训练数据也需要保存到文本里面,新建文本文件命名为Training_data。新建三个python文件,分别用于三个模块的具体实现。项目目录如下:

 宏文件源代码供参考:

INPUT_FACE_WINDOWS_NAME = 'input_face'
BGR_GREEN = (0, 255, 0)
BGR_RED = (0, 0, 255)
FACE_MIN_SIZE = (60, 60)
# 保存图片的路径
IMG_SAVE_PATH = './data'
# 级联人脸特征检测器
FACE_CLASSIFIER_PATH = 'D:/python_project/Lib/site-packages/cv2/data/haarcascade_frontalface_alt2.xml'TRAIN_DATA_SAVE_PATH = './Training_data'FACE_RECOGNITION_WINDOW_NAME = "Face recognition"
FONT_SCALE = 0.75  # 字体比例
TEXT_THICKNESS = 1  # 线条粗细
GRAPH_THICKNESS = 1

2、人脸录入模块代码实现。

import cv2 as cv
from hong import *
import osdef img_extract_faces(img):  # 将人脸图片转为灰度gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)  # 转成灰度图像face_classifier = cv.CascadeClassifier(FACE_CLASSIFIER_PATH)  # 加载级联检测器,人脸特征分类器return face_classifier.detectMultiScale(gray, minSize=FACE_MIN_SIZE), graydef get_image_name(name):  # 获取图片的命名名字,格式:1.lihua.jpg# 1.lihua.jpg 格式。如果文件中没有则加入,如果已有则替换# 把读出来的图片名称,用字典存,然后用name去字典里面找有没有。f = os.listdir(IMG_SAVE_PATH)  # os.listdir(IMG_SAVE_PATH)返回目标路径里的文件列表if len(f) == 0:  # 文件列表f的长度为0则表示没有图片,编号为1name_number = 1else:  # 说明原文件有人脸照片,如果出现相同人脸姓名替换成新的,没有编号为最大值max.name.jpg加入进去。name_map = {f.split('.')[1] : int(f.split('.')[0]) for f in os.listdir(IMG_SAVE_PATH)}name_number = name_map[name] if name in name_map else max(name_map.values())+1# return IMG_SAVE_PATH + str(name_number) + "." + name + ".jpg"return str(name_number) + "." + name + ".jpg"def save_face(faces, img, name):  # 保证只有一个人脸出现在画面中if len(faces) == 0:print('没有检测到人脸,请调整!!!')if len(faces) > 1:print('检测到多个人脸,请调整!!!')x, y, w, h = faces[0]# 保存人脸部分,保存到文件夹,格式为 1.李华.jpg 格式。如果文件中没有则加入,如果已有则替换cv.imwrite('./data/' + get_image_name(name), img[y: y + h, x: x + w])print('录入成功,按 q 键退出')def main():# 人脸录入部分是为了得到人脸的数据,然后后面对人脸进行训练。# 人脸数据信息主要有三个部分。1、人脸图片。 2、人脸名字。 3、编号(编号需要和名字需要统一。以为训练数据是拿序号和人脸进行比对)# 1、人脸图片(打开摄像头、只取人脸部分、给用户实时展示人脸的画面(把人脸框出来)、保存和退出)# 2、人脸名字。(用户输入)# 3、编号。(文件名称记录)# 打开摄像头cap = cv.VideoCapture(0)if not cap.isOpened():print('连接摄像头失败')# 输入人脸的名字name = input("请输入姓名:")if name == ' ':print('姓名不能为空,请重新输入!!!')print('姓名输入完成:按 s 保存,按 q 退出。')# 循环读取摄像头的每一帧画面,然后识别画面中的人脸,识别后只保存人脸部分,作为训练数据。while True:ret, frame = cap.read()if not ret:print('读取失败')break# 检测人脸,且提取人脸部分。这部分直接使用一个函数封装起来。faces, gray = img_extract_faces(frame)# 框出人脸for x, y, w, h in faces:cv.rectangle(img=frame, pt1=(x, y), pt2=(x+w, y+h),color=BGR_GREEN, thickness=1)cv.imshow(INPUT_FACE_WINDOWS_NAME, frame)# 保存和退出k = cv.waitKey(1)if k == ord('s'):# 保存图像,(只需保存灰度图像)save_face(faces, gray, name)elif k == ord('q'):break# 释放内存cap.release()cv.destroyAllWindows()if __name__ == '__main__':main()

 运行imput_face.py录入人脸:

 点击英文的s键,即可保存人脸到data文件中,如下图所示:

3、训练数据模块代码实现。

import cv2 as cv
import os
from hong import *
import numpy as npdef main():# 获取图片完整路径image_paths = [os.path.join(IMG_SAVE_PATH, f) for f in os.listdir(IMG_SAVE_PATH)]# 遍历列表中的图片faces = [cv.imread(image_path, 0) for image_path in image_paths]# 获取训练对象img_ids = [int(f.split('.')[0])for f in os.listdir(IMG_SAVE_PATH)]recognizer = cv.face.LBPHFaceRecognizer_create()recognizer.train(faces, np.array(img_ids))print(faces, np.array(img_ids))# 保存文件recognizer.write(TRAIN_DATA_SAVE_PATH)if __name__ == '__main__':main()

运行train.py文件训练data文件夹里面的数据: 

 

4、人脸识别模块代码实现。

"""通过摄像头识别人脸(LBPH识别器(训练的数据,和当前的人脸图片))得到编号。编号和人脸的对应关系,标记人脸和名字并展示画面创建识别器,加载训练数据读取文件构造编号和人脸的关系打开摄像头循环取每帧画面人脸检测且提取人脸部分遍历人脸进行识别框出人脸部分且实时展示画面(画面上带有  )关闭摄像头和窗口
"""
import os
import cv2 as cv
from cv2 import face
from hong import *
from train import *
from imput_face import img_extract_facesdef get_color_text(confidence, name):if confidence > 85:return BGR_RED, "unknown"return BGR_GREEN, namedef main():# 创建识别器recognizer = cv.face.LBPHFaceRecognizer_create()recognizer.read(TRAIN_DATA_SAVE_PATH)# 读取文件构造编号和人脸的关系。以字典的形式保存编号和人脸名字的关系name_map = {int(f.split('.')[0]): f.split('.')[1] for f in os.listdir(IMG_SAVE_PATH)}# 打开摄像头cap = cv.VideoCapture(0)if not cap.isOpened():print('连接摄像头失败')print("按q退出")# 循环取每帧画面while True:ret, frame = cap.read()if not ret:print('读取失败')break# 人脸检测,且提取人脸部分。faces, gray = img_extract_faces(frame)# 遍历人脸进行识别for x, y, w, h in faces:img_id, confidence = recognizer.predict(gray[y: y+h, x: x+w])# 返回图片编号和置信度。置信度为两张图片的相似程度# 框出人脸且实时展示画面color, text = get_color_text(confidence, name_map[img_id])cv.putText(img=frame, text=text, org=(x, y),fontFace=cv.FONT_HERSHEY_SIMPLEX, fontScale=FONT_SCALE,color=color, thickness=TEXT_THICKNESS)cv.circle(img=frame, center=(x+w//2, y+h//2),radius=w // 2,color=color, thickness=GRAPH_THICKNESS)cv.imshow(FACE_RECOGNITION_WINDOW_NAME, frame)if cv.waitKey(1) == ord('q'):break# 关闭摄像头,释放空间cap.release()cv.destroyAllWindows()if __name__ == '__main__':main()

 运行face_recognition.py文件进行人脸识别:

项目介绍到这里,感谢阅读!!!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/200848.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Emscripten学习笔记之内存模型

编译目标选择: 在WebAssembly标准出现前的很长一段时间内,Emscripten的编译目标是asm.js。自1.37.3起,Emscirpten才开始正式支持WebAssembly。 以asm.js为编译目标时,C/C代码被编译为.js文件;以WebAssembly为编译目标…

MVC、MVP、MVVM模式的区别

前言:这三个表现层框架设计模式是依次进化而形成MVC—>MVP—>MVVM。在以前传统的开发模式当中即MVC模式,前端人员只负责Model(数据库)、 View(视图)和 Controller /Presenter/ViewModel(控…

Google Guava 的Preconditions类各种用法

Preconditions类 提供静态方法列表&#xff0c;用于检查是否使用有效参数值调用方法或构造函数。如果前提条件失败&#xff0c;则会抛出指定异常。 前置依赖 引入 pom <dependency><groupId>com.google.guava</groupId><artifactId>guava</artif…

android开发市场被抢占,鸿蒙能入行吗?

根据最新的数据&#xff0c;华为Mate60系列在上市第二周就成功占据了国内手机市场的17%份额&#xff0c;排名第二。而机构预测&#xff0c;华为手机在第37周有望超过20%的市场份额&#xff0c;成为国内手机市场的冠军。 一开始&#xff0c;人们对HarmonyOSNEXT持保留态度&…

vite初识

Vite是伴随着Vue3正式版一起发布的&#xff0c;最开始Vite 1.0的版本是为Vue3服务的&#xff0c;并不是跨框架的。之后半年时间左右&#xff0c;出现了Vite 2.0版本&#xff0c;Vite 2.0真正脱离了和Vue3的强关联&#xff0c;以插件的方式&#xff0c;可以集成到目前流行的主流…

Apache Doris 在某工商信息商业查询平台的湖仓一体建设实践

本文导读&#xff1a; 信息服务行业可以提供多样化、便捷、高效、安全的信息化服务&#xff0c;为个人及商业决策提供了重要支撑与参考。本文以某工商信息商业查询平台为例&#xff0c;介绍其从传统 Lambda 架构到基于 Doris Multi-Catalog 的湖仓一体架构演进历程。同时通过一…

js中for 循环和 map 循环都是是什么,他们有什么区别

在JavaScript中&#xff0c;for循环和map循环都是用于迭代数组元素的常见方法。 for循环&#xff1a;for循环是一种常见的迭代结构&#xff0c;可以使用循环变量和循环条件来控制循环的次数。它可以遍历数组的索引&#xff0c;并通过索引访问数组中的元素。示例代码如下&#…

【头歌系统数据库实验】实验2 MySQL软件操作及建库建表建数据

目录 第1关&#xff1a;创建数据库 第2关&#xff1a;创建供应商表S&#xff0c;并插入数据 第3关&#xff1a;创建零件表P&#xff0c;并插入数据 第4关&#xff1a;创建工程项目表J&#xff0c;并插入数据 第5关&#xff1a;创建供应情况表SPJ&#xff0c;并插入数据 …

第一百九十回 自定义一个可选择的星期组件

文章目录 1. 概念介绍2. 实现方法2.1 实现思路2.2 实现方法3. 示例代码4. 内容总结我们在上一章回中介绍了"如何让Text组件中的文字自动换行"相关的内容,本章回中将介绍 如何自定义一个可选择的星期组件.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 我们在…

智能优化算法应用:基于类电磁机制算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于类电磁机制算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于类电磁机制算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.类电磁机制算法4.实验参数设定5.算法结果…

EasyRecovery14破解版 v14.0.0.4 官方免费版(含激活码)

软件介绍 EasyRecovery14高级版是一款功能强大的数据恢复软件&#xff0c;软件对比家庭版本它的使用更加广泛&#xff0c;在恢复数据方面软件可以做到最完整的损失恢复&#xff0c;无论是文档、音乐、软件都可以一键恢复&#xff0c;同时软件还可以对文件的名字、后缀进行修改…

ES6之Symbol

ES6中为我们新增了一个原始数据类型Symbol&#xff0c;让我为大家介绍一下吧&#xff01; Symbol它表示是独一无二的值 Symbol要如何创建 第一种创建方式&#xff1a; let sy Symbol()第二种创建方式&#xff1a; let sy Symbol.for()具体独一无二在哪呢&#xff1f;它们的地…

nodejs+vue+微信小程序+python+PHP天天网站书城管理系统的设计与实现-计算机毕业设计推荐

本项目主要分为前台模块与后台模块2个部分&#xff0c;详细描述如下&#xff1a;   &#xff08;1&#xff09;前台模块 首页: 首页可以起到导航的作用&#xff0c;用户想要了解网站 &#xff0c;网站首页为用户可以深入了解网站提供了一个平台&#xff0c;它就向一个“导游”…

react-router v6实现动态的title(react-router-dom v6)

前言 react-router-dom v6 默认不支持 title设置了&#xff0c;所以需要自己实现一下。 属性描述path指定路由的路径&#xff0c;可以是字符串或字符串数组。当应用的URL与指定的路径匹配时&#xff0c;该路由将会被渲染。element指定要渲染的React组件或元素。children代表…

Flutter桌面应用程序定义系统托盘Tray

文章目录 概念实现方案1. tray_manager依赖库支持平台实现步骤 2. system_tray依赖库支持平台实现步骤 3. 两种方案对比4. 注意事项5. 话题拓展 概念 系统托盘&#xff1a;系统托盘是一种用户界面元素&#xff0c;通常出现在操作系统的任务栏或桌面顶部。它是一个水平的狭长区…

深度学习在单线性回归方程中的应用--TensorFlow实战详解

深度学习在单线性回归方程中的应用–TensorFlow实战详解 文章目录 深度学习在单线性回归方程中的应用--TensorFlow实战详解1、人工智能<-->机器学习<-->深度学习2、线性回归方程3、TensorFlow实战解决单线性回归问题人工数据集生成构建模型训练模型定义损失函数定义…

发请求/传递过程中出现‘[object Object]‘的问题“

问题&#xff1a;post请求的时候data数据传过去的的时候显示data: [object Object] 问题代码&#xff1a; wx.request( { url: "", header: { "Content-Type": "application/x-www-form-urlencoded" }, method: "POST", data:…

【算法每日一练]-图论(保姆级教程篇11 tarjan模板篇)无向图的桥 #无向图的割点 #有向图的强连通分量

目录 预备知识 模板1&#xff1a;无向图的桥 模板2&#xff1a;无向图的割点 模板3&#xff1a;有向图的强连通分量 讲之前先补充一下必要概念&#xff1a; 预备知识 无向图的【连通分量】&#xff1a; 即极大联通子图&#xff0c;再加入一个节点就不再连通&#xff08;对…

Python 删除字典列表等元素问题

""" 在 Python 中&#xff0c;在迭代列表的同时修改它可能导致意外的结果&#xff0c; 因为这会破坏迭代器的状态。在你的代码中&#xff0c;当你尝试删除元素时&#xff0c; 迭代器可能会跳过下一个元素&#xff0c;导致删除的不是你预期的元素。 ""…

Kafka Schema介绍

Avro概述 简介 Apache Avro(以下简称 Avro,读音:阿夫罗)是一个数据序列化系统,是一种与编程语言无关的序列化格式,是提供一种共享数据文件的方式。Avro是Hadoop中的一个子项目,Avro是一个基于二进制数据传输高性能的中间件。Avro可以做到将数据进行序列化,适用于远程…