简介
通过使用深度学习技术,实现对视频中人物性别和年龄的实时识别。通过应用预训练的卷积神经网络模型,我们能够检测视频中的人脸,并预测其性别和年龄范围。
代码步骤
- 导入所需的Python库,包括OpenCV、PIL和NumPy。
import cv2 from PIL import Image,ImageDraw,ImageFont import numpy as np
- 加载性别和年龄识别的预训练模型文件。
# 加载性别和年龄识别模型的路径 faceproto="opencv_face_detector.pbtxt" facemodel="opencv_face_detector_uint8.pb" ageproto="deploy_age.prototxt" agemodel="age_net.caffemodel" genderproto="deploy_gender.prototxt" gendermodel="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=['man','woman'] # 均值用于图像预处理 mean=(78.4263377603,87.7689143744,114.895847746)
- 定义函数:
getboxes
:用于从视频帧中检测人脸并返回边界框。-
获取视频帧的高度和宽度
# 定义一个函数来获取人脸检测的边界框 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()
-
处理置信度大于0.7的人脸,绘制人脸边界框
faceboxes=[] # 遍历检测结果 for i in range(detections.shape[2]): confindence=detections[0,0,i,2] # 只处理置信度大于0.7的人脸 if confindence>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
-
cv2addchinese
:用于在图像上添加中文文本。# 定义一个函数来在图像上添加中文文本 def cv2addchinese(img, text, position, textColor=255, textSize=30): if isinstance(img, np.ndarray): if len(img.shape) == 2: # 灰度图像 img_pil = Image.fromarray(img) else: # 彩色图像 img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) else: raise ValueError("img must be a numpy array") draw = ImageDraw.Draw(img_pil) fontstyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8") draw.text(position, text, font=fontstyle, fill=textColor) if len(img.shape) == 2: # 灰度图像 img_cv2 = np.array(img_pil, dtype=np.uint8) else: # 彩色图像 img_cv2 = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR) return img_cv2
- 视频处理:
- 使用OpenCV打开视频文件。
# 打开视频文件 cap=cv2.VideoCapture("xiao.mp4")
- 循环读取视频帧,对每一帧进行人脸检测。
while True: _,frame=cap.read() frame,faceboxes=getboxes(facenet,frame) if not faceboxes: print('no people') continue
- 对检测到的每个人脸,使用性别和年龄识别模型进行预测。
for facebox in faceboxes: x,y,x1,y1=facebox # 从帧中提取人脸区域 face=frame[y:y1,x:x1] # 将人脸区域转换为模型输入所需的blob blob=cv2.dnn.blobFromImage(face,1.0,(227,227),mean) 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=cv2addchinese(frame,result,(x,y-30)) cv2.imshow('result',frame)
- 使用OpenCV打开视频文件。
运行结果
完整代码
import cv2
from PIL import Image,ImageDraw,ImageFont
import numpy as np
# 加载性别和年龄识别模型的路径
faceproto="opencv_face_detector.pbtxt"
facemodel="opencv_face_detector_uint8.pb"
ageproto="deploy_age.prototxt"
agemodel="age_net.caffemodel"
genderproto="deploy_gender.prototxt"
gendermodel="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=['man','woman']
# 均值用于图像预处理
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=[]
# 遍历检测结果
for i in range(detections.shape[2]):
confindence=detections[0,0,i,2]
# 只处理置信度大于0.7的人脸
if confindence>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 cv2addchinese(img, text, position, textColor=255, textSize=30):
if isinstance(img, np.ndarray):
if len(img.shape) == 2: # 灰度图像
img_pil = Image.fromarray(img)
else: # 彩色图像
img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
else:
raise ValueError("img must be a numpy array")
draw = ImageDraw.Draw(img_pil)
fontstyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")
draw.text(position, text, font=fontstyle, fill=textColor)
if len(img.shape) == 2: # 灰度图像
img_cv2 = np.array(img_pil, dtype=np.uint8)
else: # 彩色图像
img_cv2 = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)
return img_cv2
# 打开视频文件
cap=cv2.VideoCapture("xiao.mp4")
while True:
_,frame=cap.read()
frame,faceboxes=getboxes(facenet,frame)
if not faceboxes:
print('no people')
continue
for facebox in faceboxes:
x,y,x1,y1=facebox
# 从帧中提取人脸区域
face=frame[y:y1,x:x1]
# 将人脸区域转换为模型输入所需的blob
blob=cv2.dnn.blobFromImage(face,1.0,(227,227),mean)
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=cv2addchinese(frame,result,(x,y-30))
cv2.imshow('result',frame)
if cv2.waitKey(60)==27:
break
cv2.destroyAllWindows()
cv2.release()