实时人脸性别与年龄识别:基于OpenCV与深度学习模型的实现

在当今数字化时代,计算机视觉技术正以前所未有的速度改变着我们的生活与工作方式。其中,人脸检测与分析作为计算机视觉领域的重要分支,已广泛应用于安防监控、智能交互、社交媒体等多个场景。本文将详细介绍如何利用OpenCV库结合深度学习模型,实现一个实时人脸性别与年龄识别的项目,旨在帮助读者快速掌握相关技术,并激发大家在实际应用中进一步探索的灵感。

一、项目背景与意义

人脸作为人类最显著的生物特征之一,蕴含着丰富的信息,如性别、年龄、表情等。能够实时准确地识别这些信息,对于提升人机交互体验、优化社会服务管理等方面具有重大意义。例如,在商业领域,商家可通过分析顾客的性别与年龄分布,精准定位目标客户群体,实现个性化营销;在安防领域,实时人脸分析有助于快速识别可疑人员,提高公共安全防范能力。本项目正是基于这样的背景,致力于搭建一个简单高效的人脸性别与年龄识别系统,为相关应用提供技术支持。

二、技术选型与环境搭建

(一)技术选型

  1. OpenCV:OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉与机器学习软件库,提供了大量的图像与视频处理功能。其简单易用的API接口、高效的性能以及强大的社区支持,使其成为计算机视觉项目中常用的工具库。在本项目中,我们将利用OpenCV进行视频帧的读取、图像预处理、人脸检测框绘制等操作。
  2. 深度学习模型:为了实现性别与年龄的识别功能,我们采用了预训练的深度学习模型。这些模型基于大量的标注数据训练而成,能够自动学习人脸图像中的特征,从而准确地判断性别与年龄。具体来说,我们使用了基于Caffe框架训练的性别识别模型与年龄识别模型,以及用于人脸检测的OpenCV自带的深度学习模型。这些模型在实际应用中表现出较高的准确率与鲁棒性,能够满足我们项目的需求。
  3. Python:Python语言以其简洁明了的语法、丰富的库资源以及强大的跨平台能力,成为计算机视觉与深度学习领域广泛使用的编程语言。本项目基于Python进行开发,便于快速实现功能并进行调试。

好的,我将为每行代码添加详细的注释,帮助你更好地理解代码的功能和实现细节。

三、项目实现步骤

(一)人脸检测模块

人脸检测是整个项目的基础,其目的是从输入的图像或视频帧中准确地定位出人脸区域,以便后续进行性别与年龄的识别。在本项目中,我们使用了 OpenCV 提供的深度学习人脸检测模型,其基于 SSD(Single Shot MultiBox Detector)架构,能够快速准确地检测出人脸位置。

1. 模型加载

通过 cv2.dnn.readNet 函数加载人脸检测模型文件:

faceProto = "model1/opencv_face_detector.pbtxt"  # 人脸检测模型的配置文件路径
faceModel = "model1/opencv_face_detector_uint8.pb"  # 人脸检测模型的权重文件路径
faceNet = cv2.dnn.readNet(faceModel, faceProto)  # 加载人脸检测模型
2. 检测框获取

将输入的视频帧转换为模型所需的输入格式(通过 cv2.dnn.blobFromImage 函数),然后将数据输入到模型中,获取检测结果。根据检测结果中的置信度(confidence)筛选出置信度大于 0.7 的人脸检测框,并将其坐标记录下来:

def getBoxes(net, frame):
    frameHeight, frameWidth = frame.shape[:2]  # 获取视频帧的高和宽

    # 将视频帧转换为模型所需的输入格式
    blob = cv2.dnn.blobFromImage(frame, 1.0, (300, 300), [104, 117, 123], True, False)
    net.setInput(blob)  # 设置输入
    detections = net.forward()  # 获取检测结果

    faceBoxes = []  # 用于存储人脸检测框
    for i in range(detections.shape[2]):  # 遍历检测结果
        confidence = detections[0, 0, i, 2]  # 获取置信度
        if confidence > 0.7:  # 筛选置信度大于 0.7 的检测框
            x1 = int(detections[0, 0, i, 3] * frameWidth)  # 计算检测框的左上角 x 坐标
            y1 = int(detections[0, 0, i, 4] * frameHeight)  # 计算检测框的左上角 y 坐标
            x2 = int(detections[0, 0, i, 5] * frameWidth)  # 计算检测框的右下角 x 坐标
            y2 = int(detections[0, 0, i, 6] * frameHeight)  # 计算检测框的右下角 y 坐标
            faceBoxes.append([x1, y1, x2, y2])  # 将检测框坐标添加到列表中
            cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), int(round(frameHeight / 150)), 6)  # 在视频帧上绘制检测框
    return frame, faceBoxes  # 返回绘制了检测框的视频帧和检测框坐标
(二)性别与年龄识别模块

在获取到人脸检测框后,我们对每个检测到的人脸区域分别进行性别与年龄的识别。

1. 性别识别
(1)模型加载

使用 cv2.dnn.readNet 函数加载性别识别模型文件:

genderProto = "model1/deploy_gender.prototxt"  # 性别识别模型的配置文件路径
genderModel = "model1/gender_net.caffemodel"  # 性别识别模型的权重文件路径
genderNet = cv2.dnn.readNet(genderModel, genderProto)  # 加载性别识别模型
(2)识别过程

将人脸区域图像转换为模型所需的输入格式(通过 cv2.dnn.blobFromImage 函数),然后将数据输入到性别识别模型中,获取模型输出的性别预测结果。根据输出结果中概率最大的类别确定性别:

blob = cv2.dnn.blobFromImage(face, 1.0, (227, 227), mean)  # 将人脸区域图像转换为模型所需的输入格式
genderNet.setInput(blob)  # 设置输入
genderOuts = genderNet.forward()  # 获取性别预测结果
gender = genderList[genderOuts[0].argmax()]  # 根据概率最大的类别确定性别
2. 年龄识别
(1)模型加载

使用 cv2.dnn.readNet 函数加载年龄识别模型文件:

ageProto = "model1/deploy_age.prototxt"  # 年龄识别模型的配置文件路径
ageModel = "model1/age_net.caffemodel"  # 年龄识别模型的权重文件路径
ageNet = cv2.dnn.readNet(ageModel, ageProto)  # 加载年龄识别模型
(2)识别过程

与性别识别类似,将人脸区域图像转换为模型所需的输入格式后,输入到年龄识别模型中,获取模型输出的年龄预测结果。根据输出结果中概率最大的类别确定年龄范围:

ageNet.setInput(blob)  # 设置输入
ageOuts = ageNet.forward()  # 获取年龄预测结果
age = ageList[ageOuts[0].argmax()]  # 根据概率最大的类别确定年龄范围
(三)结果展示模块

为了将识别结果直观地展示给用户,我们采用了在视频帧上绘制中文文本的方式。由于 OpenCV 本身不支持直接绘制中文字符,因此我们借助 Pillow 库实现了这一功能。

1. 文本绘制函数实现

定义一个 cv2AddChineseText 函数,将输入的 OpenCV 图像转换为 Pillow 图像,然后使用 Pillow 的 ImageDraw 模块在图像上绘制中文文本,最后将图像转换回 OpenCV 格式:

from PIL import Image, ImageDraw, ImageFont
import numpy as np
import cv2

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))  # 实现 array 到 image 的转换
    draw = ImageDraw.Draw(img)  # 在 img 图片上创建一个绘图的对象
    # 字体的格式
    fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")
    draw.text(position, text, textColor, font=fontStyle)  # 绘制文本
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)  # 转换回 OpenCV 格式
2. 结果展示

在主循环中,对于每个检测到的人脸区域,将性别与年龄的识别结果组合成字符串,然后调用 cv2AddChineseText 函数将其绘制在人脸检测框上方:

result = "{},{}".format(gender, age)  # 将性别与年龄的识别结果组合成字符串
frame = cv2AddChineseText(frame, result, (x1, y1 - 30))  # 将结果绘制在人脸检测框上方
(四)实时视频处理与交互
1. 摄像头视频流读取

通过 cv2.VideoCapture 函数打开摄像头设备,获取实时视频流。在主循环中,逐帧读取视频帧,并将其传递给人脸检测与性别年龄识别模块进行处理:

cap = cv2.VideoCapture(0)  # 打开摄像头设备
while True:
    _, frame = cap.read()  # 逐帧读取视频帧
    frame = cv2.flip(frame, 1)  # 翻转视频帧,使其与镜像一致
    frame, faceBoxes = getBoxes(faceNet, frame)  # 获取人脸检测框
    if not faceBoxes:  # 如果没有检测到人脸
        print("当前镜头中没人")
        continue
    for faceBox in faceBoxes:  # 遍历每个检测到的人脸区域
        # 性别与年龄识别过程
        # ...
    cv2.imshow("result", frame)  # 显示处理后的视频帧
    if cv2.waitKey(1) == 27:  # 按下 ESC 键退出
        break
cv2.destroyAllWindows()  # 关闭所有 OpenCV 窗口
cap.release()  # 释放摄像头资源

希望这些注释能帮助你更好地理解代码的实现细节。如果你有任何问题或需要进一步的解释,请随时告诉我。

  1. 用户交互:在视频窗口中,用户可以通过按下Esc键退出程序,实现简单的用户交互功能。

五、总结

通过本项目的实现,我们成功搭建了一个基于OpenCV与深度学习模型的实时人脸性别与年龄识别系统。在项目过程中,我们详细介绍了人脸检测、性别与年龄识别以及结果展示等关键模块的实现原理与代码实现,并探讨了项目优化与改进的方向。希望本文能够为对计算机视觉与深度学习感兴趣的读者提供一定的参考与启发,大家可以在实际项目中根据具体需求对代码进行修改与拓展,探索更多有趣的应用场景。未来,随着技术的不断发展,相信人脸分析技术将在更多领域发挥更大的作用,为我们的生活带来更多便利与创新。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐