《OpenCV》—— dlib库(性别年龄预测)

发布于:2025-03-04 ⋅ 阅读:(11) ⋅ 点赞:(0)

dlib库

dlib 是一个现代化的 C++ 工具包,包含了机器学习算法和工具,用于创建复杂的软件来解决实际问题。它广泛应用于计算机视觉、机器学习、深度学习、图像处理等领域,同时也提供了 Python 接口,方便 Python 开发者使用。dlib 是一个功能强大、易于使用的工具包,在计算机视觉和机器学习领域有着广泛的应用。通过使用 dlib,开发者可以快速实现各种复杂的任务,如人脸检测、人脸关键点检测等。

主要特点
  • 丰富的机器学习算法:包含了各种机器学习算法,如支持向量机(SVM)、决策树、神经网络等。
  • 强大的计算机视觉功能:提供了人脸检测、人脸关键点检测、目标跟踪、图像分割等功能。
  • 跨平台支持:可以在 Windows、Linux、macOS 等多种操作系统上使用。
  • 易于使用:提供了简洁的 API,方便开发者使用。
python安装dlib库
pip install dlib

不过,在某些情况下,直接使用 pip 安装可能会遇到编译问题,因为 dlib 依赖于一些 C++ 编译工具。如果遇到问题,可以参考 dlib 的官方文档进行手动编译安装。

实例——性别年龄预测

本次实例使用预训练模型进行预测:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

代码:

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

# 定义人脸检测模型的配置文件和模型文件路径
faceProto = 'model/opencv_face_detector.pbtxt'
faceModel = 'model/opencv_face_detector_uint8.pb'
# 定义年龄预测模型的配置文件和模型文件路径
ageProto = 'model/deploy_age.prototxt'
ageModel = 'model/age_net.caffemodel'
# 定义性别预测模型的配置文件和模型文件路径
genderProto = 'model/deploy_gender.prototxt'
genderModel = 'model/gender_net.caffemodel'

# 加载年龄预测模型
ageNet = cv2.dnn.readNet(ageModel, ageProto)
# 加载性别预测模型
genderNet = cv2.dnn.readNet(genderModel, genderProto)
# 加载人脸检测模型
faceNet = cv2.dnn.readNet(faceModel, faceProto)

# 定义年龄分组列表
ageList = ['0-2岁', '4-6岁', '8-12岁', '15-20岁', '25-32岁', '38-43岁', '48-53岁', '60-100岁']
# 定义性别列表
genderList = ['男性', '女性']
# 定义图像均值,用于图像预处理
mean = (78.4263377603, 87.7689143744, 114.895847746)

def getBoxes(net, frame):
    """
    该函数用于从输入的帧中检测人脸,并返回绘制了人脸框的帧和人脸框的坐标列表
    :param net: 人脸检测网络
    :param frame: 输入的图像帧
    :return: 绘制了人脸框的帧和人脸框的坐标列表
    """
    # 获取帧的高度和宽度
    frameHeight, frameWidth = frame.shape[:2]
    # 对输入的帧进行预处理,将其转换为适合网络输入的 blob 格式
    blob = cv2.dnn.blobFromImage(frame, 1.0, (300, 300), [104, 117, 123], True, False)
    # 将预处理后的 blob 输入到网络中
    net.setInput(blob)
    # 进行前向传播,得到检测结果
    detections = net.forward()

    faceBoxes = []
    # 遍历检测结果中的每一个检测框
    for i in range(detections.shape[2]):
        # 获取当前检测框的置信度
        confidence = detections[0, 0, i, 2]

        # 如果置信度大于 0.7,则认为该检测框是有效的人脸框
        if confidence > 0.7:
            # 计算人脸框的左上角和右下角坐标
            x1 = int(detections[0, 0, i, 3] * frameWidth)
            y1 = int(detections[0, 0, i, 4] * frameHeight)
            x2 = int(detections[0, 0, i, 5] * frameWidth)
            y2 = int(detections[0, 0, i, 6] * frameHeight)
            # 将人脸框的坐标添加到列表中
            faceBoxes.append([x1, y1, x2, y2])
            # 在帧上绘制人脸框
            cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), int(round(frameHeight / 150)), 6)
    return frame, faceBoxes

def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=20):
    """
    该函数用于在 OpenCV 图像上添加中文文本
    :param img: 输入的 OpenCV 图像
    :param text: 要添加的中文文本
    :param position: 文本的位置
    :param textColor: 文本的颜色,默认为绿色
    :param textSize: 文本的大小,默认为 20
    :return: 添加了中文文本的 OpenCV 图像
    """
    # 判断输入的 img 是否为 OpenCV 格式的图片(即 numpy.ndarray 类型)
    if isinstance(img, np.ndarray):
        # 如果是 OpenCV 格式,将其从 BGR 颜色空间转换为 RGB 颜色空间,
        # 并将其转换为 PIL 库可以处理的 Image 对象
        img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

    # 在 img 图片上创建一个绘图对象,用于后续绘制文本
    draw = ImageDraw.Draw(img)

    # 定义字体的格式,使用 "simsun.ttc" 字体文件,指定字体大小为 textSize,
    # 并设置编码为 UTF - 8 以支持中文显示
    fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")

    # 在指定的 position 位置,使用指定的 textColor 颜色和 fontStyle 字体绘制文本
    draw.text(position, text, textColor, font=fontStyle)

    # 将绘制好文本的 PIL 图片转换回 numpy.ndarray 类型,并将颜色空间从 RGB 转换回 BGR,
    # 以符合 OpenCV 的要求
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)

# 打开摄像头
cap = cv2.VideoCapture(0)
while True:
    # 读取一帧图像
    ret, frame = cap.read()
    # 水平翻转图像,使显示效果更自然
    img = cv2.flip(frame, 1)
    # 如果读取失败,则跳出循环
    if not ret:
        break
    # 调用 getBoxes 函数检测人脸,并返回绘制了人脸框的帧和人脸框的坐标列表
    frame, faceBoxes = getBoxes(faceNet, img)
    # 如果没有检测到人脸,则打印提示信息并继续下一次循环
    if not faceBoxes:
        print('当前镜头中没有人')
        continue
    # 遍历检测到的每一个人脸框
    for faceBox in faceBoxes:
        # 获取人脸框的左上角和右下角坐标
        x1, y1, x2, y2 = faceBox
        # 从帧中裁剪出人脸区域
        face = frame[y1:y2, x1:x2]
        # 对裁剪出的人脸区域进行预处理,将其转换为适合网络输入的 blob 格式
        blob = cv2.dnn.blobFromImage(face, 1.0, (227, 227), mean)
        # 将预处理后的 blob 输入到性别预测网络中
        genderNet.setInput(blob)
        # 进行前向传播,得到性别预测结果
        genderOuts = genderNet.forward()
        # 根据预测结果的索引,从性别列表中获取对应的性别
        gender = genderList[genderOuts[0].argmax()]
        # 将预处理后的 blob 输入到年龄预测网络中
        ageNet.setInput(blob)
        # 进行前向传播,得到年龄预测结果
        ageOuts = ageNet.forward()
        # 根据预测结果的索引,从年龄列表中获取对应的年龄分组
        age = ageList[ageOuts[0].argmax()]

        # 组合性别和年龄信息
        result = "{},{}".format(gender, age)
        # 调用 cv2AddChineseText 函数在帧上添加中文文本
        frame = cv2AddChineseText(frame, result, (x1, y1 - 30))
    # 显示处理后的帧
    cv2.imshow('result', frame)

    # 等待按键事件
    key = cv2.waitKey(1)
    # 如果按下 ESC 键,则跳出循环
    if key == 27:
        break

# 释放摄像头资源
cap.release()
# 关闭所有 OpenCV 窗口
cv2.destroyAllWindows()

可自行运行代码进行测试结果
这里使用图片进行测试:
在这里插入图片描述