目录

1基于CNN的性别分类建模原理

1.1 人脸识别

1.2 性别预测

1.3 年龄预测

1.4 结果

2 代码

参考


本教程中,我们将讨论应用于面部的深层学习的有趣应用。我们将估计年龄,并从单个图像中找出该人的性别。模型由GilLevi和TalHassner训练(https://talhassner.github.io/home/publication/2015_CVPR)。本文介绍了如何在OpenCV中使用该模型的步骤说明。Opencv版本3.4.3以上。代码教程代码可以分为四个部分:

1基于CNN的性别分类建模原理

作者使用非常简单的卷积神经网络结构,类似于Caffenet和Alexnet。网络使用3个卷积层、2个全连接层和一个最终的输出层。下面给出了这些层的细节。COV1:第一卷积层具有96个内核大小7的节点。COV2:第二个卷积层Conv层具有256个具有内核大小5的节点。CONV3:第三个CONV层具有384个内核大小为3的节点。两个完全连接的层各自具有512个节点。

训练数据来源:https://talhassner.github.io/home/projects/Adience/Adience-data.html

检测程序主要有四块:检测人脸检测、性别检测、年龄显示和输出。

1.1 人脸识别

我们将使用人脸检测器(tensorflow模型)进行人脸检测。该模型很简单,即使在CPU上也是相当快的。详细见论文:

https://arxiv.org/pdf/1502.00046.pdf

1.2 性别预测

将性别预测设定为一个分类问题。性别预测网络(caffe模型)中的输出层类型为两类,2个节点表示“男性”和“女性”两类。以这两个输出的最大值作为最终的性别。

1.3 年龄预测

理想情况下,年龄预测应该作为一个回归问题来处理。然而通过回归准确估计年龄是很有挑战性的。即使是人类也无法通过观察一个人来准确预测年龄。但是我们能够知道他们是20多岁还是30多岁。由于这个原因,把这个问题描述为一个分类问题是明智的,因为我们试图估计这个人所处的年龄组。例如,0-2范围内的年龄是一个类,4-6是另一个类,依此类推。因此数据集分为以下8个年龄组[(0-2)、(4-6)、(8-12)、(15-20)、(25-32)、(38-43)、(48-53)、(60-100)]。因此,年龄预测网络在最后一层有8个节点,表示所述年龄范围。

应该记住,从一幅图像中预测年龄并不是一个很容易解决的问题,因为感知到的年龄取决于许多因素,而同龄的人在世界各地可能看起来很不一样。而且,人们非常努力地隐藏他们的真实年龄!

我们加载年龄网络(caffe模型)并使用前向通道获得输出。由于网络结构类似于性别网络,所以我们可以从所有输出中提取出最大值来得到预测的年龄组

1.4 结果

尽管性别预测网络表现良好,但年龄预测网络仍未达到我们的预期。所以添加人脸对齐算法或者数据样本很多时候,可以通过回归的模型来检测。但是性别人脸检测还是很准确的。

2 代码

在VS2017下运行了C++代码,其中OpenCV版本至少要3.4.5以上。不然模型读取会有问题。三个模型文件太大,见下载链接:

https://download.csdn.net/download/luohenyj/10993309

​​​​​​​https://github.com/luohenyueji/OpenCV-Practical-Exercise

如果没有积分(系统自动设定资源分数)看看参考链接。我搬运过来的,大修改没有。

其中tensorflow和caffe模型都可以用opencv中的readnet函数读取,流程很简单。看看代码就会。

代码提供了C++和Python版本,但是python版本没有运行,原因opencv版本太低,不想升级。代码都有详细的注释。

C++版本:

#include <tuple>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <iterator>
using namespace cv;
using namespace cv::dnn;
using namespace std;/*** @brief Get the Face Box object 人脸定位** @param net 人脸检测网络* @param frame 检测图像* @param conf_threshold 阈值* @return tuple<Mat, vector<vector<int>>> 元组容器,可返回多个值*/
tuple<Mat, vector<vector<int>>> getFaceBox(Net net, Mat &frame, double conf_threshold)
{//图像复制Mat frameOpenCVDNN = frame.clone();int frameHeight = frameOpenCVDNN.rows;int frameWidth = frameOpenCVDNN.cols;//缩放尺寸double inScaleFactor = 1.0;//检测图大小Size size = Size(300, 300);// std::vector<int> meanVal = {104, 117, 123};Scalar meanVal = Scalar(104, 117, 123);cv::Mat inputBlob;inputBlob = cv::dnn::blobFromImage(frameOpenCVDNN, inScaleFactor, size, meanVal, true, false);net.setInput(inputBlob, "data");//四维矩阵输出cv::Mat detection = net.forward("detection_out");//提取结果信息cv::Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());vector<vector<int>> bboxes;for (int i = 0; i < detectionMat.rows; i++){//预测概率float confidence = detectionMat.at<float>(i, 2);if (confidence > conf_threshold){//左上角点,坐标被归一化int x1 = static_cast<int>(detectionMat.at<float>(i, 3) * frameWidth);int y1 = static_cast<int>(detectionMat.at<float>(i, 4) * frameHeight);//右下角角点,坐标被归一化int x2 = static_cast<int>(detectionMat.at<float>(i, 5) * frameWidth);int y2 = static_cast<int>(detectionMat.at<float>(i, 6) * frameHeight);vector<int> box = { x1, y1, x2, y2 };//人脸坐标bboxes.push_back(box);//图像框选cv::rectangle(frameOpenCVDNN, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(0, 255, 0), 2, 4);}}return make_tuple(frameOpenCVDNN, bboxes);
}int main(void)
{//人脸模型string faceProto = "model/opencv_face_detector.pbtxt";string faceModel = "model/opencv_face_detector_uint8.pb";//年龄模型string ageProto = "model/age_deploy.prototxt";string ageModel = "model/age_net.caffemodel";//性别模型string genderProto = "model/gender_deploy.prototxt";string genderModel = "model/gender_net.caffemodel";//均值Scalar MODEL_MEAN_VALUES = Scalar(78.4263377603, 87.7689143744, 114.895847746);//年龄段标签vector<string> ageList = { "(0-2)", "(4-6)", "(8-12)", "(15-20)", "(25-32)","(38-43)", "(48-53)", "(60-100)" };//性别标签vector<string> genderList = { "Male", "Female" };//导入网络Net ageNet = cv::dnn::readNet(ageProto, ageModel);Net genderNet = cv::dnn::readNet(genderProto, genderModel);Net faceNet = cv::dnn::readNetFromTensorflow(faceModel, faceProto);//打开摄像头VideoCapture cap;cap.open(0);if (cap.isOpened()){cout << "camera is opened!" << endl;}else{return 0;}int padding = 20;while (waitKey(1) < 0){// read frame 读图Mat frame;cap.read(frame);if (frame.empty()){waitKey();break;}frame = imread("./images/couple1.jpg");//人脸坐标vector<vector<int>> bboxes;//人脸检测结果图Mat frameFace;//人脸定位//tie()函数解包frameFace和bboxestie(frameFace, bboxes) = getFaceBox(faceNet, frame, 0.7);//人脸判断if (bboxes.size() == 0){cout << "No face detected, checking next frame." << endl;continue;}//逐个提取人脸检测for (auto it = begin(bboxes); it != end(bboxes); ++it){//框选人脸Rect rec(it->at(0) - padding, it->at(1) - padding, it->at(2) - it->at(0) + 2 * padding, it->at(3) - it->at(1) + 2 * padding);//避免人脸框选超过图像边缘rec.width = ((rec.x + rec.width) > frame.cols) ? (frame.cols - rec.x - 1) : rec.width;rec.height = ((rec.y + rec.height) > frame.rows) ? (frame.rows - rec.y - 1) : rec.height;// take the ROI of box on the frame,原图中提取人脸Mat face = frame(rec);//性别检测Mat blob;blob = blobFromImage(face, 1, Size(227, 227), MODEL_MEAN_VALUES, false);genderNet.setInput(blob);// string gender_preds; 获取前向传播softmax结果vector<float> genderPreds = genderNet.forward();// find max element index max_element用于找寻最大值// distance function does the argmax() work in C++ distance返回最大值和第一个值下标的距离int max_index_gender = std::distance(genderPreds.begin(), max_element(genderPreds.begin(), genderPreds.end()));//获得检测结果string gender = genderList[max_index_gender];cout << "Gender: " << gender << endl;//年龄识别ageNet.setInput(blob);vector<float> agePreds = ageNet.forward();// finding maximum indicd in the age_preds vector 找到年龄预测最大下表int max_indice_age = std::distance(agePreds.begin(), max_element(agePreds.begin(), agePreds.end()));string age = ageList[max_indice_age];cout << "Age: " << age << endl;// label 输出标签string label = gender + ", " + age;//在人脸定位图上显示结果cv::putText(frameFace, label, Point(it->at(0), it->at(1) - 15), cv::FONT_HERSHEY_SIMPLEX, 0.9, Scalar(0, 255, 255), 2, cv::LINE_AA);}//保存结果imshow("Frame", frameFace);imwrite("out.jpg", frameFace);}
}

python版本:

# Import required modules
import cv2 as cv
import time
import argparsedef getFaceBox(net, frame, conf_threshold=0.7):frameOpencvDnn = frame.copy()frameHeight = frameOpencvDnn.shape[0]frameWidth = frameOpencvDnn.shape[1]blob = cv.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])cv.rectangle(frameOpencvDnn, (x1, y1), (x2, y2), (0, 255, 0), int(round(frameHeight/150)), 8)return frameOpencvDnn, bboxesparser = argparse.ArgumentParser(description='Use this script to run age and gender recognition using OpenCV.')
parser.add_argument('--input', help='Path to input image or video file. Skip this argument to capture frames from a camera.')args = parser.parse_args()faceProto = "age_gender/model/opencv_face_detector.pbtxt"
faceModel = "age_gender/model/opencv_face_detector_uint8.pb"ageProto = "age_gender/model/age_deploy.prototxt"
ageModel = "age_gender/model/age_net.caffemodel"genderProto = "age_gender/model/gender_deploy.prototxt"
genderModel = "age_gender/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 = cv.dnn.readNet(ageModel, ageProto)
genderNet = cv.dnn.readNet(genderModel, genderProto)
faceNet = cv.dnn.readNet(faceModel, faceProto)# Open a video file or an image file or a camera stream
cap = cv.VideoCapture(args.input if args.input else 0)
padding = 20
while cv.waitKey(1) < 0:# Read framet = time.time()hasFrame, frame = cap.read()if not hasFrame:cv.waitKey()breakframeFace, bboxes = getFaceBox(faceNet, frame)if not bboxes:print("No face Detected, Checking next frame")continuefor bbox in bboxes:# print(bbox)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 = cv.dnn.blobFromImage(face, 1.0, (227, 227), MODEL_MEAN_VALUES, swapRB=False)genderNet.setInput(blob)genderPreds = genderNet.forward()gender = genderList[genderPreds[0].argmax()]# print("Gender Output : {}".format(genderPreds))print("Gender : {}, conf = {:.3f}".format(gender, genderPreds[0].max()))ageNet.setInput(blob)agePreds = ageNet.forward()age = ageList[agePreds[0].argmax()]print("Age Output : {}".format(agePreds))print("Age : {}, conf = {:.3f}".format(age, agePreds[0].max()))label = "{},{}".format(gender, age)cv.putText(frameFace, label, (bbox[0], bbox[1]-10), cv.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 255), 2, cv.LINE_AA)cv.imshow("Age Gender Demo", frameFace)# cv.imwrite("age-gender-out-{}".format(args.input),frameFace)print("time : {:.3f}".format(time.time() - t))

参考

https://www.learnopencv.com/age-gender-classification-using-opencv-deep-learning-c-python/

[OpenCV实战]1 基于深度学习识别人脸性别和年龄相关推荐

  1. 基于深度学习的人脸性别识别系统(含UI界面,Python代码)

    摘要:人脸性别识别是人脸识别领域的一个热门方向,本文详细介绍基于深度学习的人脸性别识别系统,在介绍算法原理的同时,给出Python的实现代码以及PyQt的UI界面.在界面中可以选择人脸图片.视频进行检 ...

  2. 毕业设计 基于深度学习的人脸性别年龄识别 - 图像识别 opencv

    文章目录 0 前言 1 课题描述 课题意义 2 实现效果 3 算法实现原理 3.1 数据集 3.2 深度学习识别算法 3.3 特征提取主干网络 3.4 总体实现流程 4 具体实现 4.1 预训练数据格 ...

  3. python dlib caffe人脸相似度_基于深度学习的人脸识别系统(Caffe+OpenCV+Dlib)【一】如何配置caffe属性表...

    前言 基于深度学习的人脸识别系统,一共用到了5个开源库:OpenCV(计算机视觉库).Caffe(深度学习库).Dlib(机器学习库).libfacedetection(人脸检测库).cudnn(gp ...

  4. 基于深度学习的人脸识别系统(Caffe+OpenCV+Dlib)【三】VGG网络进行特征提取

    前言 基于深度学习的人脸识别系统,一共用到了5个开源库:OpenCV(计算机视觉库).Caffe(深度学习库).Dlib(机器学习库).libfacedetection(人脸检测库).cudnn(gp ...

  5. 基于深度学习的人脸识别系统系列(Caffe+OpenCV+Dlib)——【六】设计人脸识别的识别类...

    前言 基于深度学习的人脸识别系统,一共用到了5个开源库:OpenCV(计算机视觉库).Caffe(深度学习库).Dlib(机器学习库).libfacedetection(人脸检测库).cudnn(gp ...

  6. 开发基于深度学习的人脸识别【考勤/签到】系统

    开发基于深度学习的人脸识别[考勤/签到]系统 人脸识别介绍 平台环境需求 技术点 系统流程 细节设计 人脸检测 人脸关键点定位 人脸特征提取 模型的训练 模型的部署 MySQL数据库的使用 MFC工程 ...

  7. 基于深度学习的人脸识别与管理系统(UI界面增强版,Python代码)

    摘要:人脸检测与识别是机器视觉领域最热门的研究方向之一,本文详细介绍博主自主设计的一款基于深度学习的人脸识别与管理系统.博文给出人脸识别实现原理的同时,给出Python的人脸识别实现代码以及PyQt设 ...

  8. dlib 使用OpenCV,Python和深度学习进行人脸识别 源代码

    请直接访问原文章 dlib 使用OpenCV,Python和深度学习进行人脸识别 源代码 https://hotdog29.com/?p=595 在 2019年7月7日 上张贴 由 hotdog发表回 ...

  9. python模块cv2人脸识别_手把手教你使用OpenCV,Python和深度学习进行人脸识别

    使用OpenCV,Python和深度学习进行人脸识别 在本教程中,你将学习如何使用OpenCV,Python和深度学习进行面部识别.首先,我们将简要讨论基于深度学习的面部识别,包括"深度度量 ...

  10. 基于深度学习的人脸检测和关键点检测推理实践(OpenCV实现,含代码)

    目录 一.任务概述 二.环境准备 三.实现步骤 3.1 Python推理 3.2 C++推理 3.2.1 环境准备 3.2.2 推理 3.3 Java推理 一.任务概述 最近项目中大量场景需要用到人脸 ...

最新文章

  1. android脚步---使用framelayout实现霓虹灯效果
  2. CSAPC08台湾邀请赛_T1_skyline
  3. 此三层非彼三层——MVCamp;UBD
  4. php7.0 yield,PHP7中生成器的新特性 yield-from amp;amp; return-values
  5. 【C++基础】异常处理机制概要
  6. 后疫情时代,银行从数字化转型到智能化“迁徙”
  7. TV Distortion Bundle mac - AE画面像素破损信号干扰失真插件
  8. android json字符串转成json对象_在PHP中处理JSON数组以及对象
  9. 计算机内存不足吃鸡怎么办,Win10玩吃鸡游戏提示虚拟内存不足怎么办?
  10. web服务器IIS详细错误代码以及解释
  11. (SQL)删除表中字段有中文的记录
  12. matlab 换热器仿真,matlab 换热器仿真 - 百度学术
  13. Python AutoCAD 选择集
  14. 蝌蚪网课助手mac_疫情期间如何录网课?(干货教程)手把手教你录出高质量网课。...
  15. 陌生人交友软件有哪些?陌生人社交APP排名|良心推荐
  16. Camera相机研发介绍
  17. kibana Percentile Ranks计算的逻辑
  18. 防控青光眼的3大武器
  19. 查看电脑支持最大内存和内存条型号
  20. 破解入门(三)-----脱壳的常用方法

热门文章

  1. 深入理解bootloader_1----- bootloader的初步概念
  2. ae预览绿条不完整_AE不能预览全部视频的原因分析及解决方案
  3. 安装西门子TIA Portal V15.1提示先决条件不足如何处理?
  4. java声音变音代码实现_大话音频变声原理 附简单示例代码
  5. 有关printf输出08x格式详解
  6. uni-swipe-action失效?
  7. unity跳跃按钮_Unity——#04 跳跃
  8. 百度地图API计算经纬度
  9. nmos和pmos区别、工作原理及基本结构详解
  10. 互联网金融指导意见落地 行业发展开始步入正轨