opencv学习:基于深度学习的视频人物性别和年龄识别及完整代码实现

简介

通过使用深度学习技术,实现对视频中人物性别和年龄的实时识别。通过应用预训练的卷积神经网络模型,我们能够检测视频中的人脸,并预测其性别和年龄范围。

代码步骤

  1. 导入所需的Python库,包括OpenCV、PIL和NumPy。
    import cv2
    from PIL import Image,ImageDraw,ImageFont
    import numpy as np
  2. 加载性别和年龄识别的预训练模型文件。
    # 加载性别和年龄识别模型的路径
    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"
  3. 初始化人脸,年龄和性别识别网络
    # 初始化年龄和性别识别网络
    # 年龄识别模型的配置文件和权重文件
    agenet=cv2.dnn.readNet(agemodel,ageproto)
    # 性别识别模型的配置文件和权重文件
    gendernet=cv2.dnn.readNet(gendermodel,genderproto)
    # 人脸检测模型的配置文件和权重文件
    facenet=cv2.dnn.readNet(facemodel,faceproto)
  4. 生成年龄和性别的标签列表
    # 年龄和性别的标签列表
    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)
  5. 定义函数
    • 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
  6. 视频处理
    • 使用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)

运行结果

完整代码

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()

猜你喜欢

转载自blog.csdn.net/mohanyelong/article/details/143175156