python基于opencv和tkinter实现人脸识别

python基于opencv和tkinter实现人脸识别 杨工-深圳 2024-03-14 17:53:46 84

前言:

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

环境搭建:

安装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 库开发的人脸识别程序。它可以从摄像头实时获取视频,并在视频中检测人脸并显示其姓名。

程序的大体流程如下:

1.加载 Haar Cascade 分类器用于人脸检测。
2.打开摄像头并捕获实时图像。
3.循环处理捕获的图像:
  • 将图像转换为灰度图像。
  • 使用 Haar Cascade 分类器检测人脸。
  • 如果检测到人脸,则查找是否存在与 person 文件夹中的某个人匹配的图像。
  • 如果找到匹配的人脸,则在图像中框出人脸并显示姓名。
  • 如果未找到匹配的人脸,则在图像中框出人脸但不显示姓名。
  • 将图像转换为 PIL Image 格式以在 GUI 中显示。
  • 更新标签以显示图像。
  • 处理 GUI 事件以避免程序挂起。
  • 关闭摄像头并销毁窗口。
4.代码中的函数 cv2AddChineseText 用于在图像上添加中文文本。函数 cv2AddChineseText 接受四个参数:

代码中的函数 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个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
杨工-深圳
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区