好用的在线地图网站,泉州专业做网站,鹤壁做网站的联系方法,淘宝网官网登录首页目录
1基于CNN的性别分类建模原理
1.1 人脸识别
1.2 性别预测
1.3 年龄预测
1.4 结果
2 代码
参考 本教程中#xff0c;我们将讨论应用于面部的深层学习的有趣应用。我们将估计年龄#xff0c;并从单个图像中找出该人的性别。模型由GilLevi和TalHassner训练#xff0…目录
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 iteratorusing namespace cv;using namespace cv::dnn;using namespace std;/*** brief Get the Face Box object 人脸定位** param net 人脸检测网络* param frame 检测图像* param conf_threshold 阈值* return tupleMat, vectorvectorint 元组容器可返回多个值*/tupleMat, vectorvectorint 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::vectorint 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.ptrfloat());vectorvectorint bboxes;for (int i 0; i detectionMat.rows; i){//预测概率float confidence detectionMat.atfloat(i, 2);if (confidence conf_threshold){//左上角点坐标被归一化int x1 static_castint(detectionMat.atfloat(i, 3) * frameWidth);int y1 static_castint(detectionMat.atfloat(i, 4) * frameHeight);//右下角角点坐标被归一化int x2 static_castint(detectionMat.atfloat(i, 5) * frameWidth);int y2 static_castint(detectionMat.atfloat(i, 6) * frameHeight);vectorint 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);//年龄段标签vectorstring ageList { (0-2), (4-6), (8-12), (15-20), (25-32),(38-43), (48-53), (60-100) };//性别标签vectorstring 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);//人脸坐标vectorvectorint 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结果vectorfloat 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);vectorfloat 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 modulesimport cv2 as cvimport timeimport argparsedef getFaceBox(net, frame, conf_threshold0.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(descriptionUse this script to run age and gender recognition using OpenCV.)parser.add_argument(--input, helpPath 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.pbtxtfaceModel age_gender/model/opencv_face_detector_uint8.pbageProto age_gender/model/age_deploy.prototxtageModel age_gender/model/age_net.caffemodelgenderProto age_gender/model/gender_deploy.prototxtgenderModel age_gender/model/gender_net.caffemodelMODEL_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 networkageNet 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 streamcap cv.VideoCapture(args.input if args.input else 0)padding 20while 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, swapRBFalse)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/