前言:
人脸识别技术已经在许多领域得到了广泛应用,例如安防、金融、医疗等等。人脸识别可以帮助我们识别和验证一个人的身份,这是一项非常重要的任务。本篇博客将介绍如何使用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 库开发的人脸识别程序。它可以从摄像头实时获取视频,并在视频中检测人脸并显示其姓名。
程序的大体流程如下:
加载 Haar Cascade 分类器用于人脸检测。
打开摄像头并捕获实时图像。
循环处理捕获的图像:1. 将图像转换为灰度图像。2. 使用 Haar Cascade 分类器检测人脸。3. 如果检测到人脸,则查找是否存在与
person
文件夹中的某个人匹配的图像。4. 如果找到匹配的人脸,则在图像中框出人脸并显示姓名。5. 如果未找到匹配的人脸,则在图像中框出人脸但不显示姓名。6. 将图像转换为 PIL Image 格式以在 GUI 中显示。7. 更新标签以显示图像。8. 处理 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 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()
人脸识别技术在现代生活中有着广泛的应用,例如人脸解锁手机、人脸识别支付、安防领域等。但是,人脸识别技术还存在一些局限性和改进的空间。
首先,人脸识别技术的准确性受到许多因素的影响,例如光照、姿势、表情、遮挡等。为了提高人脸识别的准确性,可以采用更先进的算法,例如基于深度学习的人脸识别算法。此外,还可以通过采用更好的硬件设备来提高图像采集的质量。
其次,当前的人脸识别技术主要针对单个人脸进行识别,对于多个人脸的情况处理较为困难。为了解决这个问题,可以探索如何将多个人脸的特征进行有效地提取和匹配。
最后,人脸识别技术还涉及到隐私保护等伦理问题。在应用人脸识别技术时,需要注意隐私保护的问题,避免对个人隐私造成侵害。
总的来说,人脸识别技术在未来还有很大的发展空间,随着科技的不断进步,相信人脸识别技术的应用将更加广泛,也将更加普及化和便利化。
人脸识别技术正在广泛应用于各个领域,例如安全监控、人脸支付、人脸解锁等等。本文介绍的人脸识别应用程序只是冰山一角,随着技术的不断发展,我们可以期待更加高效、准确的人脸识别应用程序的出现。如果您对人脸识别技术感兴趣,不妨关注相关的技术发展和应用案例,为您的职业生涯增添一份技术的底气。感谢阅读本文,如果您觉得有用,请点赞、收藏和关注,谢谢啦!!
过几天我会在此基础上加上录入人脸信息的功能,感兴趣的小伙伴不要错过哦。
再次感谢不离不弃的粉丝,之后仍会不定期更新哦~~
版权归原作者 晋升阁 所有, 如有侵权,请联系我们删除。