结合以下链接中的文章有助于理解此篇案例:
- OpenCV中的 cnn 模块
此案例是通过使用OpenCV中的cnn模块来调用别人已经训练好的深度学习模型,此篇案例中用到了人脸检测模型、年龄预测模型,性别预测模型。
-
以下链接中是这三种模型所需要的模型文件和配置文件
-
完整代码如下:
import cv2 from PIL import Image, ImageDraw, ImageFont import numpy as np # ======模型初始化====== # 模型(网络模型/预训练模型):face/age/gender(脸、年龄、性别) 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) # ======年龄初始化====== # 年龄段和性别 共有8个年龄区间,区间范围可自行更改 ageList = ['0-2岁', '4-6岁', '8-12岁', '15-22岁', '25-32岁', '38-43岁', '48-53岁', '60-100岁'] genderList = ['男性', '女性'] mean = (78.4263377603, 87.7689143744, 114.895847746) # 模型均值 # ======自定义函数,获取人脸包围框====== def getBoxes(net, frame): frameHeight, frameWidth = frame.shape[:2] # 获取高度、宽度 # 实现图像预处理,从原始图像构建一个符合人工神经网络输入格式的四维块。 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个数据,第3个数据表示置信度,第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图片上创建一个绘图的对象 # 字体的格式 C 盘中的 Windows/Fonts 中,复制到此文件夹下可看到文件名 fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8") draw.text(position, text, textColor, font=fontStyle) # 绘制文本 return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR) # 转换回 OpenCV 格式 """ 打开摄像头,将每一帧画面传入神经网络中 """ cap = cv2.VideoCapture(0) # 0-->电脑自带摄像头,1-->电脑外接摄像头 while True: _, frame = cap.read() # frame = cv2.flip(frame,1) # 镜像处理 # 获取人脸包围框、绘制人脸包围框(可能多个) frame, faceBoxes = getBoxes(faceNet, frame) if not faceBoxes: print("当前镜头中没有人") continue # 遍历每一个人脸包围框 for faceBoxe in faceBoxes: # 处理每一帧画面frame,将其处理为符合DNN输入的格式 x, y, x1, y1 = faceBoxe 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: # 按下ESc键,退出程序 break cv2.destroyAllWindows() cap.release()