马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
一、引言
在盘算机视觉领域,人脸分析是一个热门且应用广泛的研究方向。其中,人脸性别年事检测能够主动识别图像或视频流中人脸的性别和年事信息,具有诸多实际应用场景,如市场调研、安防监控、用户个性化体验等。OpenCV 作为一个强大的盘算机视觉库,提供了丰富的工具和预训练模型来实现这一功能。
二、原理概述
人脸检测:起首需要在输入的图像或视频帧中检测出人脸。OpenCV 常用的人脸检测方法基于 Haar 级联检测器或基于深度学习的目标检测算法(如 SSD、YOLO 等)。Haar 级联检测器通过构建一系列简单的 Haar 特性,并使用 AdaBoost 算法训练出一个强分类器来识别图像中的人脸区域。基于深度学习的方法则通过在大规模人脸数据集上训练卷积神经网络(CNN),学习人脸的特性模式,从而实现更准确的人脸检测。
性别年事预测:一旦检测到人脸,将人脸区域进行预处理(如裁剪、归一化等)后输入到预训练的性别年事预测模型中。这些模型通常也是基于深度学习的 CNN 架构。在训练过程中,模型学习到不同年事和性别人脸的特性表示,通过对输入人脸图像的特性提取和分析,预测出该人脸对应的性别(通常为男性或女性)和年事范围(如儿童、青少年、成年人、老年人等)。
- pip install opencv - python
复制代码 下载预训练模型:
人脸检测模型:对于 Haar 级联人脸检测,可以从 OpenCV 官方的 GitHub 仓库下载haarcascade_frontalface_default.xml文件。该文件包含了训练好的 Haar 级联分类器参数。
性别年事预测模型:性别年事预测模型通常基于深度学习,如 Caffe 模型。可以从相关开源项目中下载预训练的deploy_gender.prototxt和gender_net.caffemodel文件用于性别预测,以及deploy_age.prototxt和age_net.caffemodel文件用于年事预测。这些模型在大规模人脸数据集上进行了训练,具有肯定的准确性。
预备输入数据:预备用于检测的图像或视频文件。确保图像或视频中的人脸清晰可见,光线条件良好,以提高检测的准确性。
三、代码实现
1.导入必要的库
- import cv2
- from PIL import Image, ImageDraw, ImageFont
- import numpy as np
复制代码 导入cv2库用于盘算机视觉处理,PIL库中的Image、ImageDraw、ImageFont用于在图像上绘制中文字符,numpy库用于数值盘算。
2.加载模型文件路径
获取路径:通过网盘分享的文件:model2
链接: https://pan.baidu.com/s/1gS-5xqOexYyMQ_wUQJTR0w 提取码: ued3
- faceProto = "model2/opencv_face_detector.pbtxt"
- faceModel = "model2/opencv_face_detector_uint8.pb"
- ageProto = "model2/deploy_age.prototxt"
- ageModel = "model2/age_net.caffemodel"
- genderProto = "model2/deploy_gender.prototxt"
- genderModel = "model2/gender_net.caffemodel"
复制代码 定义人脸检测、年事预测和性别预测模型的配置文件(.pbtxt或.prototxt)和权重文件(.pb或.caffemodel)的路径。
3.读取模型
- ageNet = cv2.dnn.readNet(ageModel, ageProto)
- genderNet = cv2.dnn.readNet(genderModel, genderProto)
- faceNet = cv2.dnn.readNet(faceModel, faceProto)
复制代码 使用cv2.dnn.readNet函数读取年事、性别和人脸检测模型,以便后续用于推理
4.定义年事和性别标签列表及均值
- ageList = ['0-2岁', '4-6岁', '8-12岁', '15-20岁', '25-32岁', '38-43岁', '48-53岁', '60-100岁']
- genderList = ['男性', '女性']
- mean = (78.4263377603, 87.7689143744, 114.895847746)
复制代码 创建年事和性别标签列表,用于将模型预测的类别索引转换为实际的年事范围和性别形貌。同时定义了图像归一化所需的均值。
5.人脸检测函数
- 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 = []
- for i in range(detections.shape[2]):
- confidence = detections[0, 0, i, 2]
- if confidence > 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
复制代码 这个函数接受一个模型net和一个视频帧frame作为输入。起首获取帧的高度和宽度,然后使用cv2.dnn.blobFromImage将帧转换为得当模型输入的 blob 格式,设置模型输入并进行前向推理得到检测结果。遍历检测结果,筛选出置信度大于 0.7 的检测框,将其坐标转换为实际图像中的坐标并添加到faceBoxes列表中,同时在原帧上绘制检测框。最后返回绘制了检测框的帧和检测框坐标列表。
6.在图像上绘制中文字符的函数
- def cv2AddchineseText(img, text, position, textColor=(0, 255, 0), textSize=30):
- if isinstance(img, np.ndarray):
- img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
- draw = ImageDraw.Draw(img)
- fontStyle = ImageFont.truetype("simhei.ttf", textSize, encoding="utf-8")
- draw.text(position, text, textColor, font=fontStyle)
- return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
复制代码 该函数用于在图像上绘制中文字符。起首判断输入的图像是否为 OpenCV 的numpy.ndarray格式,如果是则将其转换为PIL的Image格式。然后使用ImageDraw和ImageFont设置字体样式并在图像上指定位置绘制文本,最后再将图像转换回 OpenCV 的BGR格式并返回
7.主循环
- cap = cv2.VideoCapture(0)
- while True:
- _, frame = cap.read()
- frame = cv2.flip(frame, 1)
- frame, faceBoxes = getBoxes(faceNet, frame)
- if not faceBoxes:
- print("当前镜头中没有人")
- continue
- for faceBox in faceBoxes:
- x1, y1, x2, y2 = faceBox
- face = frame[y1:y2, x1: x2]
- 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 = cv2AddchineseText(frame, result, (x1, y1 - 30))
- cv2.imshow("result", frame)
- if cv2.waitKey(1) == 27:
- break
- cv2.destroyAllWindows()
- cap.release()
复制代码 初始化摄像头设备,通过cv2.VideoCapture(0)打开默认摄像头。进入无限循环,不停读取摄像头的帧,使用cv2.flip对帧进行水平翻转(以实现镜像结果)。调用getBoxes函数进行人脸检测,获取绘制了检测框的帧和检测到的人脸框列表。如果没有检测到人脸,则打印提示信息并继续下一次循环。对于检测到的每一张人脸,提取人脸区域,将其转换为得当性别和年事模型输入的 blob 格式,分别输入到性别和年事预测模型中进行推理,获取预测结果并从标签列表中找到对应的性别和年事形貌,将两者组合成结果字符串,使用cv2AddchineseText函数在图像上绘制结果。最后使用cv2.imshow显示处理后的帧,当用户按下Esc键(键值为 27)时,退出循环。循环竣事后,开释摄像头资源并关闭所有 OpenCV 窗口。
完整代码:
- import cv2
- from PIL import Image, ImageDraw, ImageFont
- import numpy as npfaceProto = "model2/opencv_face_detector.pbtxt"
- faceModel = "model2/opencv_face_detector_uint8.pb"
- ageProto = "model2/deploy_age.prototxt"
- ageModel = "model2/age_net.caffemodel"
- genderProto = "model2/deploy_gender.prototxt"
- genderModel = "model2/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 = ['男性', '女性']
- 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 = []
- for i in range(detections.shape[2]):
- confidence = detections[0, 0, i, 2]
- if confidence > 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, faceBoxesdef 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)) draw = ImageDraw.Draw(img) fontStyle = ImageFont.truetype("simhei.ttf", textSize, encoding="utf-8") draw.text(position, text, textColor, font=fontStyle) return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)cap = cv2.VideoCapture(0) # 装载摄像头while True: _, frame = cap.read() frame = cv2.flip(frame, 1) frame, faceBoxes = getBoxes(faceNet, frame) if not faceBoxes: print("当前镜头中没有人") continue for faceBox in faceBoxes: x1, y1, x2, y2 = faceBox face = frame[y1:y2, x1: x2] 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 = cv2AddchineseText(frame, result, (x1, y1 - 30)) cv2.imshow("result", frame) if cv2.waitKey(1) == 27: breakcv2.destroyAllWindows()cap.release()
复制代码 最后实现对人脸性别年事的检测
四、总结
通过 OpenCV,我们可以方便地实现人脸性别年事检测。使用其提供的预训练模型和丰富的函数接口,联合简单的代码编写,就能够搭建起一个实用的人脸分析系统。希望本文能资助你快速上手并在实际项目中应用这一技能
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |