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

前言:

人脸识别技术已经在许多领域得到了广泛应用,例如安防、金融、医疗等等。人脸识别可以帮助我们识别和验证一个人的身份,这是一项非常重要的任务。本篇博客将介绍如何使用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中,可以按以下步骤进行操作:

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

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

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

代码解读

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

程序的大体流程如下:

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

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

  3. 循环处理捕获的图像:

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

代码中的函数 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 os

person_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 cv2
import os
import tkinter as tk
from PIL import Image, ImageTk,ImageDraw
import numpy as np

from PIL import ImageFont

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)

# 加载自定义字体
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()

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

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

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

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

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

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

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

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

 

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
扎眼的阳光的头像扎眼的阳光普通用户
上一篇 2023年11月2日
下一篇 2023年11月2日

相关推荐