年龄性别预测
-
任务:使用OpenCV和Caffe深度学习框架(通过OpenCV的dnn模块接口)来实现实时的人脸检测、年龄估计和性别识别,并在检测到的人脸旁边绘制中文的年龄和性别信息。
-
流程:
- 模型初始化
- 变量初始化
- 获取人脸包围框
- 调用模型预测
- 添加中文
1. 模型初始化
代码初始化了三个Caffe模型:一个人脸检测模型、一个年龄估计模型和一个性别识别模型。
将这些模型同它们的参数权重文件加载到一起:这些模型的配置文件(.prototxt
)和权重文件(.caffemodel
或.pb
对于OpenCV dnn模块)的路径被指定。
"""-----模型初始化-----"""
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) # 人脸
2. 初始化变量
将年龄范围和性别标签分别存放在列表中。
设置模型输入图像的均值,用于预处理图像。
"""-----变量初始化-----"""
ageList = ['0-2岁','4-6岁','8-12岁','15-20岁','25-32岁','28-43岁','48-53岁','60-100岁']
genderList = ['男性','女性']
mean = (78.4263377603,87.7689143744,114.895847746) # 模型均值
3. 获取人脸包围框
将图片转化为深度学习模型所需的输入格式,然后调用模型训练,将置信度大于0.7的保存下来,认定它们属于人脸,画出人脸框:
def getBoxes(net,frame):
frameHeight,frameWidth = frame.shape[:2]
# 将图像转换为深度学习模型所需的输入格式,即blob(二进制对象)。
blob = cv2.dnn.blobFromImage(frame,1.0,(300,300),
[104,117,123],True,False)
net.setInput(blob) # 调用网络模型,输入图片进行人脸检测
detections = net.forward()
faceBoxes = [] # 存储检测到的人脸
xx = detections.shape[2]
for i in range(detections.shape[2]):
# confidence中每一行保存7个数据,第三个表示置信度,第4,5,6,7分别表示人脸归一化后的坐标位置
confidence = detections[0,0,i,2]
if confidence > 0.7: # 筛选一下,将置信度大于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)
# 返回绘制了人脸框的帧frame、人脸包围框faceBoxes
return frame,faceBoxes
4. 调用中文
将测试识别结果用中文形式显示在结果上:
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("simfang.ttf",textSize,encoding="Utf-8")
draw.text(position,text,textColor,font=fontStyle) # 绘制文本
return cv2.cvtColor(np.asarray(img),cv2.COLOR_BGR2RGB) # 转换回OpenCV格式
5. 主循环
调用函数和模型,对视频进行预测:
"""-----打开摄像头,将每一帧画面传入神经网络中-----"""
cap = cv2.VideoCapture(0)
while True:
_, frame = cap.read() # 如果正确读取,ret为True
# 获取人脸包围框、绘制人脸包围框
frame,faceBoxes = getBoxes(faceNet,frame)
if not faceBoxes:
print("当前镜头中没有人")
continue
# 遍历每一个人脸包围框
for faceBox in faceBoxes:
# 处理frame,将其处理为符合DNN输入的格式
x,y,x1,y1 = faceBox
face = frame[y:y1,x:x1]
blob = cv2.dnn.blobFromImage(face,1.0,(227,227),mean) # 模型输入为227*277
# 调用模型,预测性别
genderNet.setInput(blob)
genderOuts = genderNet.forward()
gender = genderList[genderOuts[0].argmax()]
# 调用模型,预测年龄
ageNet.setInput(blob)
ageOuts = ageNet.forward()
age = ageList[ageOuts[0].argmax()]
result = "{},{}".format(gender,age) # 格式化文本
frame = cv2ADDChineseText(frame,result,(x,y-30)) # 输出中文性别和年龄
cv2.imshow("result",frame)
if cv2.waitKey(1) == 27: # 退出程序
break
cv2.destroyAllWindows()
cap.release()
6. 完整代码
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岁','28-43岁','48-53岁','60-100岁']
genderList = ['男性','女性']
mean = (78.4263377603,87.7689143744,114.895847746) # 模型均值
"""-----自定义函数,获取人脸包围框-----"""
def getBoxes(net,frame):
frameHeight,frameWidth = frame.shape[:2]
# 将图像转换为深度学习模型所需的输入格式,即blob(二进制对象)。
blob = cv2.dnn.blobFromImage(frame,1.0,(300,300),
[104,117,123],True,False)
net.setInput(blob) # 调用网络模型,输入图片进行人脸检测
detections = net.forward()
faceBoxes = [] # 存储检测到的人脸
xx = detections.shape[2]
for i in range(detections.shape[2]):
# confidence中每一行保存7个数据,第三个表示置信度,第4,5,6,7分别表示人脸归一化后的坐标位置
confidence = detections[0,0,i,2]
if confidence > 0.7: # 筛选一下,将置信度大于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)
# 返回绘制了人脸框的帧frame、人脸包围框faceBoxes
return frame,faceBoxes
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("simfang.ttf",textSize,encoding="Utf-8")
draw.text(position,text,textColor,font=fontStyle) # 绘制文本
return cv2.cvtColor(np.asarray(img),cv2.COLOR_BGR2RGB) # 转换回OpenCV格式
"""-----打开摄像头,将每一帧画面传入神经网络中-----"""
cap = cv2.VideoCapture(0)
while True:
_, frame = cap.read() # 如果正确读取,ret为True
# 获取人脸包围框、绘制人脸包围框
frame,faceBoxes = getBoxes(faceNet,frame)
if not faceBoxes:
print("当前镜头中没有人")
continue
# 遍历每一个人脸包围框
for faceBox in faceBoxes:
# 处理frame,将其处理为符合DNN输入的格式
x,y,x1,y1 = faceBox
face = frame[y:y1,x:x1]
blob = cv2.dnn.blobFromImage(face,1.0,(227,227),mean) # 模型输入为227*277
# 调用模型,预测性别
genderNet.setInput(blob)
genderOuts = genderNet.forward()
gender = genderList[genderOuts[0].argmax()]
# 调用模型,预测年龄
ageNet.setInput(blob)
ageOuts = ageNet.forward()
age = ageList[ageOuts[0].argmax()]
result = "{},{}".format(gender,age) # 格式化文本
frame = cv2ADDChineseText(frame,result,(x,y-30)) # 输出中文性别和年龄
cv2.imshow("result",frame)
if cv2.waitKey(1) == 27: # 退出程序
break
cv2.destroyAllWindows()
cap.release()
总结
本篇介绍了,如何使用已有的OpenCV和Caffe深度学习框架(通过OpenCV的dnn模块接口)来实现实时的人脸检测、年龄估计和性别识别,并在检测到的人脸旁边绘制中文的年龄和性别信息。