python基于opencv和tkinter实现人脸识别【内附完整代码】

晋升阁 2024-06-16 14:01:02 阅读 92

前言:

人脸识别技术已经在许多领域得到了广泛应用,例如安防、金融、医疗等等。人脸识别可以帮助我们识别和验证一个人的身份,这是一项非常重要的任务。本篇博客将介绍如何使用Python和OpenCV库进行人脸识别。我们将学习如何使用OpenCV中的人脸检测器检测图像中的人脸,如何与一个人的图像进行比较以检测是否属于该人,以及如何在GUI中显示识别结果。你可以嵌入到你的程序、机器上。现在,让我们开始学习人脸识别技术吧!

如果你已有python环境和opencv库可直接跳转到代码解读


目录

前言:

环境搭建:

安装Python

安装pip

安装OpenCV

配置环境变量

代码解读

程序的大体流程如下:

加载 Haar Cascade 分类器用于人脸检测。

打开摄像头并捕获实时图像。

循环处理捕获的图像:

关闭摄像头并销毁窗口。

代码解析

与person文件夹中的图像进行比较以检测人脸

 cv2AddChineseText方法

 完整代码


环境搭建:

安装Python

首先,你需要下载和安装Python。可以在Python官方网站上下载最新版本的Python安装程序:https://www.python.org/downloads/windows/请务必下载并安装3.x版本的Python,因为OpenCV不支持Python 2.x。

安装pip

pip是Python的包管理器,可以轻松地安装、升级和删除Python软件包。可以使用以下命令检查是否已经安装了pip:

pip --version

 如果pip没有安装,可以在终端中输入以下命令进行安装:

python -m ensurepip --default-pip

安装OpenCV

可以使用pip来安装OpenCV:

pip install opencv-python

配置环境变量

为了让Python能够找到OpenCV,需要将OpenCV的路径添加到系统的环境变量中。

首先,找到OpenCV安装的路径,一般在Python的安装目录下的Lib\site-packages目录中。例如,在我的电脑上,OpenCV安装在以下目录下:

C:\Users\username\AppData\Local\Programs\Python\Python39\Lib\site-packages\cv2

然后,将这个路径添加到系统的环境变量中。在Windows 10中,可以按以下步骤进行操作:

在Windows搜索栏中输入“环境变量”,并点击“编辑系统环境变量”;在“高级”选项卡下,点击“环境变量”按钮;在“系统变量”下方找到“Path”变量,点击“编辑”按钮;在“编辑环境变量”对话框中,点击“新建”按钮,并将OpenCV的路径添加进去。测试OpenCV最后,可以测试一下OpenCV是否已经正确安装。可以在终端中输入以下代码:

import cv2 print(cv2.__version__)

如果OpenCV已经成功安装,应该会显示OpenCV的版本号。

希望这个简要的教程可以帮助你在Windows上成功安装和配置OpenCV和Python。

代码解读

这是一个基于 OpenCV 库和 tkinter 库开发的人脸识别程序。它可以从摄像头实时获取视频,并在视频中检测人脸并显示其姓名。

程序的大体流程如下:

加载 Haar Cascade 分类器用于人脸检测。

打开摄像头并捕获实时图像。

循环处理捕获的图像:

将图像转换为灰度图像。使用 Haar Cascade 分类器检测人脸。如果检测到人脸,则查找是否存在与 person 文件夹中的某个人匹配的图像。如果找到匹配的人脸,则在图像中框出人脸并显示姓名。如果未找到匹配的人脸,则在图像中框出人脸但不显示姓名。将图像转换为 PIL Image 格式以在 GUI 中显示。更新标签以显示图像。处理 GUI 事件以避免程序挂起。

关闭摄像头并销毁窗口。

代码中的函数 cv2AddChineseText 用于在图像上添加中文文本。函数 cv2AddChineseText 接受四个参数:

img:要添加文本的图像。text:要添加的文本。position:文本的位置。textColor:文本颜色,默认为绿色。textSize:文本大小,默认为 30。

代码中的 person_images 列表用于存储 person 文件夹中的人脸图像。person_names 列表用于存储每个人脸图像对应的姓名。在处理捕获的图像时,程序将检查每个人脸图像是否匹配,并在图像中显示姓名。

代码解析

该程序主要通过计算机视觉技术实现人脸识别。首先,程序使用OpenCV库中的Haar Cascade分类器来检测输入图像中的人脸。然后,它会将人脸与事先保存在“person”文件夹中的图像进行比较,以确定是否存在匹配的人脸。如果存在匹配的人脸,则程序会在图像中框出人脸并显示相应的姓名。如果不存在匹配的人脸,则程序仅在图像中框出人脸。

下面是程序的主要部分的解释:

# 加载Haar Cascade分类器face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')# 打开摄像头并捕获实时图像cap = cv2.VideoCapture(0)# 读取person文件夹中的图像和姓名person_images = []person_names = []for filename in os.listdir('person'): if filename.endswith('.jpg'): # 使用utf-8编码打开文件 with open(os.path.join('person', filename), 'rb') as f: person_images.append(cv2.imdecode(np.frombuffer(f.read(), np.uint8), cv2.IMREAD_COLOR)) person_names.append(os.path.splitext(filename)[0])while True: ret, frame = cap.read() if not ret: break # 转换图像格式以进行人脸检测 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 使用Haar Cascade分类器检测人脸 faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5) # 在图像中框出检测到的人脸 for (x, y, w, h) in faces: # 检查人脸是否属于person文件夹中的某个人 found_person = False for i in range(len(person_images)): person_image = person_images[i] person_name = person_names[i] # 将person图像转换为灰度图像以进行比较 person_gray = cv2.cvtColor(person_image, cv2.COLOR_BGR2GRAY) # 检查是否存在与person图像相匹配的人脸 match = cv2.matchTemplate(gray[y:y + h, x:x + w], person_gray, cv2.TM_CCOEFF_NORMED) if match.max() > 0.8: # 如果找到匹配的人脸,则将其标记为“found_person”,并绘制人脸框 found_person = True cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) # 在人脸框上方写出人名 cv2.putText(frame, person_name, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2) break if not found_person: # 如果没有找到匹配的人脸,则将其标记为“unknown”,并绘制人脸框 cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2) cv2.putText(frame, 'unknown', (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2)

与person文件夹中的图像进行比较以检测人脸

我们已经成功地检测出了人脸,并将其框出来。现在我们将探讨如何与person文件夹中的图像进行比较以检测人脸。

首先,我们需要读取person文件夹中的图像和姓名。我们可以使用os模块中的listdir函数列出person文件夹中的所有文件名,然后使用cv2.imread函数读取每个图像。

import osperson_folder = 'person'person_images = []person_names = []# 获取person文件夹中的所有文件名for filename in os.listdir(person_folder):    # 如果文件名以'.jpg'或'.png'结尾,则读取该图像并将其添加到person_images列表中    if filename.endswith('.jpg') or filename.endswith('.png'):        image = cv2.imread(os.path.join(person_folder, filename))        person_images.append(image)        # 使用文件名中的数字作为该人员的姓名        person_names.append(filename.split('.')[0])

接下来,我们需要将每个person图像转换为灰度图像以进行比较。我们可以使用cv2.cvtColor函数将BGR图像转换为灰度图像。

for i in range(len(person_images)): person_image = person_images[i] # 将person图像转换为灰度图像以进行比较 person_gray = cv2.cvtColor(person_image, cv2.COLOR_BGR2GRAY)

现在,我们可以使用matchTemplate函数将当前人脸与person图像进行比较,以确定当前人脸是否属于person文件夹中的某个人。matchTemplate函数可以将当前人脸的灰度图像与person图像的灰度图像进行比较,并返回一个相似度矩阵。我们可以使用max方法获取相似度矩阵中的最大值,并将其与一个预设的阈值(例如0.8)进行比较,以确定当前人脸是否与person图像匹配。 

for (x, y, w, h) in faces: # 检查人脸是否属于person文件夹中的某个人 found_person = False for i in range(len(person_images)): person_image = person_images[i] person_name = person_names[i] # 将person图像转换为灰度图像以进行比较 person_gray = cv2.cvtColor(person_image, cv2.COLOR_BGR2GRAY) # 检查是否存在与person图像相匹配的人脸 match = cv2.matchTemplate(gray[y:y + h, x:x + w], person_gray, cv2.TM_CCOEFF_NORMED) if match.max() > 0.8: found_person = True # 将人物名称绘制在检测到的人脸上 cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.putText(frame, person_name, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) break # 如果找不到相应的人物,则将“Unknown”绘制在检测到的人脸上 if not found_person: cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2) cv2.putText(frame, 'Unknown', (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2) # 将帧显示在窗口中 cv2.imshow('Face Recognition', frame) # 等待退出键 if cv2.waitKey(1) & 0xFF == ord('q'): break# 释放资源cap.release()cv2.destroyAllWindows()

这段代码将每个检测到的人脸与存储在“person”文件夹中的图像进行比较。如果存在与任何一个图像匹配的人脸,则在该人脸上方框和标注该人的名称。否则,将该人脸框在红色方框内,并标注“Unknown”。(完整代码中没有加入这行,如果需要可以加上)

最后,它将帧显示在GUI窗口中,并等待退出键按下后释放资源并关闭窗口。

 cv2AddChineseText方法

在原生的cv2.putText()方法里并不支持中文只能显示英文,在网上查阅了很多方法都不奏效于是我决定重构这个方法:

def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=30): if (isinstance(img, np.ndarray)): # 判断是否OpenCV图片类型 img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) # 创建一个可以在给定图像上绘图的对象 draw = ImageDraw.Draw(img) # 字体的格式 fontStyle = ImageFont.truetype( "simsun.ttc", textSize, encoding="utf-8") # 绘制文本 draw.text(position, text, textColor, font=fontStyle) # 转换回OpenCV格式 return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)

 完整代码

import cv2import osimport tkinter as tkfrom PIL import Image, ImageTk,ImageDrawimport numpy as npfrom PIL import ImageFontdef cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=30): if (isinstance(img, np.ndarray)): # 判断是否OpenCV图片类型 img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) # 创建一个可以在给定图像上绘图的对象 draw = ImageDraw.Draw(img) # 字体的格式 fontStyle = ImageFont.truetype( "simsun.ttc", textSize, encoding="utf-8") # 绘制文本 draw.text(position, text, textColor, font=fontStyle) # 转换回OpenCV格式 return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)# 加载自定义字体font = ImageFont.truetype(r"C:\Users\ge\Desktop\test1\Cuesor\msyh.ttc", size=30)# 加载Haar Cascade分类器face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')# 创建GUI窗口root = tk.Tk()root.geometry('640x480')root.title('人脸识别')# 创建标签用于显示图像image_label = tk.Label(root)image_label.pack()# 打开摄像头并捕获实时图像cap = cv2.VideoCapture(0)# 创建 PhotoImage 对象photo = None# 读取person文件夹中的图像和姓名person_images = []person_names = []for filename in os.listdir('person'): if filename.endswith('.jpg'): # 使用utf-8编码打开文件 with open(os.path.join('person', filename), 'rb') as f: person_images.append(cv2.imdecode(np.frombuffer(f.read(), np.uint8), cv2.IMREAD_COLOR)) person_names.append(os.path.splitext(filename)[0])# 循环处理摄像头捕获的图像while True: ret, frame = cap.read() if not ret: break # 转换图像格式以进行人脸检测 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 使用Haar Cascade分类器检测人脸 faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5) # 在图像中框出检测到的人脸 for (x, y, w, h) in faces: # 检查人脸是否属于person文件夹中的某个人 found_person = False for i in range(len(person_images)): person_image = person_images[i] person_name = person_names[i] # 将person图像转换为灰度图像以进行比较 person_gray = cv2.cvtColor(person_image, cv2.COLOR_BGR2GRAY) # 检查是否存在与person图像相匹配的人脸 match = cv2.matchTemplate(gray[y:y + h, x:x + w], person_gray, cv2.TM_CCOEFF_NORMED) if match.max() > 0.8: print(person_name) found_person = True # 在图像中框出人脸并显示姓名 cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 255), 2) # 在图像中框出人脸并显示姓名 cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 255), 2) frame = cv2AddChineseText(frame, person_name, (x + (w/2)-10, y - 30), (0, 255, 255), 30) break # 如果没有找到匹配的人脸,则在图像中框出人脸但不显示姓名 if not found_person: cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) # 将图像转换为PIL Image格式以在GUI中显示 image = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) photo = ImageTk.PhotoImage(image) # 更新标签以显示图像 image_label.configure(image=photo) image_label.image = photo # 处理GUI事件以避免程序挂起 root.update()#关闭摄像头并销毁窗口cap.release()cv2.destroyAllWindows()

人脸识别技术在现代生活中有着广泛的应用,例如人脸解锁手机、人脸识别支付、安防领域等。但是,人脸识别技术还存在一些局限性和改进的空间。

首先,人脸识别技术的准确性受到许多因素的影响,例如光照、姿势、表情、遮挡等。为了提高人脸识别的准确性,可以采用更先进的算法,例如基于深度学习的人脸识别算法。此外,还可以通过采用更好的硬件设备来提高图像采集的质量。

其次,当前的人脸识别技术主要针对单个人脸进行识别,对于多个人脸的情况处理较为困难。为了解决这个问题,可以探索如何将多个人脸的特征进行有效地提取和匹配。

最后,人脸识别技术还涉及到隐私保护等伦理问题。在应用人脸识别技术时,需要注意隐私保护的问题,避免对个人隐私造成侵害。

总的来说,人脸识别技术在未来还有很大的发展空间,随着科技的不断进步,相信人脸识别技术的应用将更加广泛,也将更加普及化和便利化。

人脸识别技术正在广泛应用于各个领域,例如安全监控、人脸支付、人脸解锁等等。本文介绍的人脸识别应用程序只是冰山一角,随着技术的不断发展,我们可以期待更加高效、准确的人脸识别应用程序的出现。如果您对人脸识别技术感兴趣,不妨关注相关的技术发展和应用案例,为您的职业生涯增添一份技术的底气。感谢阅读本文,如果您觉得有用,请点赞、收藏和关注,谢谢啦!!

过几天我会在此基础上加上录入人脸信息的功能,感兴趣的小伙伴不要错过哦。

再次感谢不离不弃的粉丝,之后仍会不定期更新哦~~

 



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。