1. 环境准备:搭建Python开发环境

在开始构建人脸识别系统之前,我们需要先准备好开发环境。我推荐使用Windows 10系统配合PyCharm IDE,这是目前最稳定的组合。实测下来,Python 3.9版本与相关库的兼容性最好,不容易出现各种奇怪的报错。

首先需要安装Python解释器。建议直接从Python官网下载3.9.x版本的安装包,安装时务必勾选"Add Python to PATH"选项,这样后续在命令行中使用python命令会更方便。安装完成后,可以在命令行输入python --version验证是否安装成功。

接下来安装PyCharm社区版,这是完全免费的版本,对于我们的需求来说已经足够。安装过程很简单,一路点击"下一步"即可。安装完成后首次启动时,建议创建一个新的Python项目,选择刚才安装的Python 3.9作为解释器。

提示:如果你之前已经安装了其他版本的Python,建议使用虚拟环境来隔离不同项目的依赖。在PyCharm中创建项目时,可以直接勾选"New environment using Virtualenv"选项。

2. 安装OpenCV(cv2)库

OpenCV是计算机视觉领域的基石库,我们的人脸识别系统将重度依赖它。在Python中,OpenCV通过cv2模块提供接口。安装cv2有两种主流方式,我都亲自测试过,各有优缺点。

第一种方式是通过PyCharm的包管理器直接安装。打开PyCharm的设置,找到"Python Interpreter"选项,点击"+"按钮搜索并安装以下两个包:

  • opencv-python(包含OpenCV的主要功能)
  • opencv-contrib-python(包含额外的贡献模块)

这种方式最简单,适合新手。但有时候可能会遇到下载速度慢的问题,这时可以尝试第二种方法:使用清华镜像源通过命令行安装。打开cmd窗口(Win+R输入cmd),执行以下命令:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-contrib-python

安装完成后,可以在Python交互环境中输入import cv2来测试是否安装成功。如果没有报错,并且能打印出版本号(print(cv2.__version__)),说明安装正确。

3. 安装face_recognition库及其依赖

face_recognition是一个基于dlib构建的高级人脸识别库,它封装了很多复杂的功能,让我们可以用简单的API实现强大的人脸识别能力。但安装过程稍微复杂一些,需要先安装几个前置依赖。

首先需要安装CMake工具,这是编译dlib所必需的。同样使用清华源加速安装:

pip install cmake -i https://pypi.tuna.tsinghua.edu.cn/simple

接下来是最关键的dlib库安装。dlib是一个用C++编写的机器学习工具包,face_recognition的核心功能都依赖于它。由于dlib包含C++代码,安装时需要编译,所以我们需要确保系统已经安装了Visual Studio的C++构建工具。

注意:如果没有安装Visual Studio的C++组件,dlib安装几乎肯定会失败。建议安装Visual Studio 2019或2022,安装时务必勾选"使用C++的桌面开发"工作负载。

安装好Visual Studio后,就可以安装dlib了:

pip install dlib -i https://pypi.tuna.tsinghua.edu.cn/simple

最后安装face_recognition库本身。由于这个库比较大,建议使用豆瓣源加速下载:

pip --default-timeout=100 install face_recognition -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

安装完成后,可以写一个简单的测试脚本验证是否安装成功:

import face_recognition
print(face_recognition.__version__)

4. 实现基础人脸识别功能

现在环境已经准备就绪,我们可以开始编写第一个真正的人脸识别程序了。我将带你一步步实现一个能够检测图片中人脸并标注出来的简单系统。

首先准备一张测试图片,最好是包含清晰正面人像的照片。创建一个新的Python文件,导入必要的库:

import cv2
import face_recognition
import numpy as np

加载图片文件并进行人脸检测:

# 加载图片
image = face_recognition.load_image_file("test.jpg")

# 查找图片中所有人脸的位置
face_locations = face_recognition.face_locations(image)

face_locations将返回一个列表,其中每个元素都是一个表示人脸位置的元组(top, right, bottom, left)。我们可以用OpenCV把这些位置标注出来:

# 转换颜色空间从RGB到BGR(OpenCV使用BGR)
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)

# 遍历检测到的每个人脸
for (top, right, bottom, left) in face_locations:
    # 在脸上画一个矩形框
    cv2.rectangle(image, (left, top), (right, bottom), (0, 255, 0), 2)

# 显示结果图像
cv2.imshow("Face Detection", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

这个简单的例子已经实现了基本的人脸检测功能。运行程序后,你应该能看到输入的图片中所有人脸都被绿色矩形框标注出来了。

5. 进阶:人脸特征点检测与识别

除了简单的人脸检测外,face_recognition库还提供了更强大的功能——人脸特征点检测和人脸识别。让我们继续扩展我们的程序。

人脸特征点检测可以定位人脸上的关键点,如眼睛、鼻子、嘴巴等位置。这在很多应用中都非常有用:

# 加载图片
image = face_recognition.load_image_file("test.jpg")

# 查找所有人脸特征点
face_landmarks_list = face_recognition.face_landmarks(image)

face_landmarks_list是一个包含字典的列表,每个字典对应一张人脸,包含了各个面部特征的位置。我们可以把这些特征点也画出来:

# 转换颜色空间
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)

for face_landmarks in face_landmarks_list:
    # 标注每个面部特征
    for facial_feature in face_landmarks.keys():
        for point in face_landmarks[facial_feature]:
            cv2.circle(image, point, 2, (0, 0, 255), -1)

cv2.imshow("Facial Landmarks", image)
cv2.waitKey(0)

要实现真正的人脸识别(即判断两张图片中是否是同一个人),我们需要先获取人脸的特征编码(face encoding)。这个编码是一个128维的向量,可以唯一地表示一张人脸:

# 获取第一张图片的人脸编码
image1 = face_recognition.load_image_file("person1.jpg")
encoding1 = face_recognition.face_encodings(image1)[0]

# 获取第二张图片的人脸编码
image2 = face_recognition.load_image_file("person2.jpg")
encoding2 = face_recognition.face_encodings(image2)[0]

# 比较两个人脸编码
results = face_recognition.compare_faces([encoding1], encoding2)
print("是同一个人吗?", results[0])

6. 构建实时人脸识别系统

现在我们已经掌握了所有基础技术,可以将其组合起来构建一个实时的人脸识别系统了。这个系统将使用摄像头实时捕获视频流,并识别其中的人脸。

首先初始化摄像头:

# 获取摄像头视频流(0表示默认摄像头)
video_capture = cv2.VideoCapture(0)

# 加载已知人脸(这里以一张图片为例)
known_image = face_recognition.load_image_file("known_person.jpg")
known_encoding = face_recognition.face_encodings(known_image)[0]

然后进入主循环,不断从摄像头读取帧并进行人脸识别:

while True:
    # 获取一帧视频
    ret, frame = video_capture.read()
    
    # 将帧从BGR颜色(OpenCV使用)转换为RGB颜色(face_recognition使用)
    rgb_frame = frame[:, :, ::-1]
    
    # 查找视频帧中的所有脸和编码
    face_locations = face_recognition.face_locations(rgb_frame)
    face_encodings = face_recognition.face_encodings(rgb_frame, face_locations)
    
    # 遍历每个检测到的人脸
    for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):
        # 看看是否匹配已知人脸
        matches = face_recognition.compare_faces([known_encoding], face_encoding)
        
        name = "Unknown"
        if matches[0]:
            name = "Known Person"
        
        # 在脸上画框
        cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
        
        # 在框下方标注名字
        cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
        font = cv2.FONT_HERSHEY_DUPLEX
        cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)
    
    # 显示结果图像
    cv2.imshow('Video', frame)
    
    # 按q键退出
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放摄像头资源
video_capture.release()
cv2.destroyAllWindows()

这个实时系统可以扩展为识别多个人。只需要预先建立一个已知人脸的数据库,包含他们的名字和对应的编码,然后在主循环中与检测到的人脸进行比对即可。

7. 性能优化与常见问题解决

在实际使用中,你可能会遇到性能问题或各种错误。这里分享一些我在项目中积累的经验和解决方案。

性能优化技巧:

  1. 降低视频分辨率:高清视频处理起来很耗资源,可以设置摄像头分辨率:
    video_capture.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
    video_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
    
  2. 减少处理频率:不需要每一帧都进行人脸识别,可以每隔几帧处理一次。
  3. 缩小检测区域:如果知道人脸大致出现的位置,可以只处理视频的特定区域。

常见问题及解决方案:

  1. dlib安装失败:确保安装了正确版本的Visual Studio C++工具,并且CMake可用。如果还是失败,可以尝试预编译的wheel文件。
  2. 人脸检测不准确:尝试调整face_recognition.face_locations()的参数,如model="cnn"(需要GPU支持)或调整tolerance参数。
  3. 内存泄漏:长时间运行后程序变慢,确保及时释放不再需要的资源,特别是视频捕获对象。

提高识别准确率的方法:

  1. 使用多张图片训练:为每个人收集不同角度、光照条件下的照片,计算平均编码。
  2. 调整对比度和亮度:在识别前对图像进行预处理。
  3. 添加活体检测:防止照片欺骗,可以通过要求用户转头或眨眼来实现。

我在实际项目中发现,face_recognition库在良好光照条件下的正面人脸识别准确率很高,但在侧脸或光线不足时性能会下降。这时候可以结合OpenCV的其他功能,比如直方图均衡化,来提高识别率。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐