《OpenCV》—— dlib库(性别年龄预测)
文章目录
- dlib库
- 主要特点
- python安装dlib库
- 实例——性别年龄预测
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()
可自行运行代码进行测试结果
这里使用图片进行测试: