Pycaffemodel来实现年龄和性别识别
1 说明
=====
1.1 效果图
图片静态识别有bug
视频和摄像头识别,动态可变
1.2 源代码来源:https://github.com/spmallick/learnopencv
1.3 对源代码进行修改、注释、增加,便于理解。
1.4 模型文件来自,或者参考这里的源代码#感谢作者,提供这两个模型:age_net.caffemodel和gender_net.caffemodel https://github.com/Roggu123/Algorithm 解压后 Algorithm-master/Practice/CV/FaceDetection/age_gender 下找到
2 准备
=====
2.1 环境:python3.8+opencv4.4.0+深度deepin-linux操作系统+微软编辑器vscode。
2.2 文件结构:
3 AgeGender.py代码
================
3.1 #第1步:导入模块 import cv2 import math
3.2 #blob = cv2.dnn.blobFromImage(image, scalefactor=1.0, size, mean, swapRB=True,crop=False,ddepth = CV_32F )
#参数
"""
1.image,这是传入的,需要进行处理的图像。
2.scalefactor,执行完减均值后,需要缩放图像,默认是1。
3.size,这是神经网络,真正支持输入的值。
4.mean,这是我们要减去的均值,可以是R,G,B均值三元组,或者是一个值,每个通道都减这值。
如果执行减均值,通道顺序是R、G、B。 如果,输入图像通道顺序是B、G、R,那么请确保swapRB = True,交换通道。
5.swapRB,OpenCV认为图像 通道顺序是B、G、R,而减均值时顺序是R、G、B,
为了解决这个矛盾,设置swapRB=True即可。
6.crop,如果crop裁剪为真,则调整输入图像的大小,使调整大小后的一侧等于相应的尺寸,另一侧等于或大于。
然后,从中心进行裁剪。如果"裁剪"为"假",则直接调整大小而不进行裁剪并保留纵横比。
"""#第2步:获取脸部框函数 def getFaceBox(net, frame, conf_threshold=0.7): frameOpencvDnn = frame.copy() frameHeight = frameOpencvDnn.shape[0] frameWidth = frameOpencvDnn.shape[1] #关键参数 blob = cv2.dnn.blobFromImage(frameOpencvDnn, 1.0, (300, 300), [104, 117, 123], True, False) net.setInput(blob) detections = net.forward() bboxes = [] for i in range(detections.shape[2]): confidence = detections[0, 0, i, 2] if confidence > conf_threshold: 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) bboxes.append([x1, y1, x2, y2]) cv2.rectangle(frameOpencvDnn, (x1, y1), (x2, y2), (0, 255, 0), int(round(frameHeight/150)), 8) return frameOpencvDnn, bboxes
3.3 主要是自己喜欢微软编辑器vscode,点击运行即可。#第3步:路径管理,自己增加的 import os curpath = os.path.realpath(__file__) # 获取当前AgeGender.py代码的绝对路径 dirpath = os.path.dirname(curpath) # 获取当前文件的文件夹路径
3.4 #第4步:现有的模型加载 faceProto = dirpath+"/model/opencv_face_detector.pbtxt" #√ faceModel = dirpath+"/model/opencv_face_detector_uint8.pb" #√ ageProto = dirpath+"/model/age_deploy.prototxt" #√ ageModel = dirpath+"/model/age_net.caffemodel" #自行下载 genderProto =dirpath+ "/model/gender_deploy.prototxt" #√ genderModel = dirpath+"/model/gender_net.caffemodel" #自行下载 MODEL_MEAN_VALUES = (78.4263377603, 87.7689143744, 114.895847746) ageList = ["(0-2)", "(4-6)", "(8-12)", "(15-20)", "(25-32)", "(38-43)", "(48-53)", "(60-100)"] genderList = ["Male", "Female"] # Load network加载网络 ageNet = cv2.dnn.readNet(ageModel, ageProto) #读取预训练模型 genderNet = cv2.dnn.readNet(genderModel, genderProto) faceNet = cv2.dnn.readNet(faceModel, faceProto) padding = 20
3.5 #第5步:加载图片或者视频识别 #视频类 #cap = cv2.VideoCapture(0) #摄像头识别 cap = cv2.VideoCapture(dirpath+"/v1.mp4") #视频识别 #图片类 #常规是image,为了与视频代码兼容 #这里采用frame代替原来的image #frame= cv2.imread(dirpath+"/3.jpeg")
3.6 #第6步:循环 while cv2.waitKey(1) < 0: #图片识别时,可注释掉 #---视频类--- hasFrame, frame = cap.read() if not hasFrame: cv2.waitKey() break #---视频类--- frameFace, bboxes = getFaceBox(faceNet, frame) if not bboxes: continue for bbox in bboxes: face = frame[max(0,bbox[1]-padding):min(bbox[3]+padding,frame.shape[0]-1),max(0,bbox[0]-padding):min(bbox[2]+padding, frame.shape[1]-1)] blob = cv2.dnn.blobFromImage(face, 1.0, (227, 227), MODEL_MEAN_VALUES, swapRB=False) genderNet.setInput(blob) genderPreds = genderNet.forward() #性别 gender = genderList[genderPreds[0].argmax()] ageNet.setInput(blob) agePreds = ageNet.forward() #年龄 age = ageList[agePreds[0].argmax()] label = "{},{}".format(gender, age) #输出字体颜色:0, 255, 255=黄色;0, 0, 255=红色 cv2.putText(frameFace, label, (bbox[0], bbox[1]-10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2, cv2.LINE_AA) #窗口展示 cv2.imshow("Age Gender Demo", frameFace)
4 小结:
可能由于现有的模型,训练数据太少,导致可能出现bug。
可以自行训练数据集,训练好了自己再用这个套用,当然这是一件浩大的工程,提高识别精度。
一般人,玩玩技术知道怎么回事就可以了。
自己让代码运行起来,并加入相关代码,复习python相关知识(编程思维和路径管理)。
希望大家喜欢。