来自于2015年CVPR的一篇paper《Age and Gender Classification using Convolutional Neural Networks》。
Paper所用的网络包含:3个卷积层,还有2个全连接层。这个算是层数比较少的CNN网络模型了,这样可以避免过拟合。对于年龄的识别,paper仅仅有8个年龄段,相当于8分类模型,对于性别识别自然而然是二分类问题了。
首先上Model Zoo下载年龄和性别的caffe模型及其描述文件,下载网址https://talhassner.github.io/home/publication/2015_CVPR
步骤:
- 加载模型文件和描述文件
- 列出分类的标签文件
- 人脸检测,将脸部图像转换为网络输入的格式
- 网络输入
- 前向传播
#include<opencv2\opencv.hpp>
using namespace cv;
using namespace dnn;
using namespace std;
String age_model = "age_net.caffemodel";
String age_txt = "deploy_age.prototxt";
String gender_model = "gender_net.caffemodel";
String gender_txt = "deploy_gender.prototxt";
String haar_xml = "haarcascade_frontalface_alt.xml";
void predict_age(Net &net, Mat &image);
void predict_gender(Net &net, Mat &image);
vector<String>ageLabels() {
vector<String>ages;
ages.push_back("0-2");
ages.push_back("4-6");
ages.push_back("8-13");
ages.push_back("15-20");
ages.push_back("25-32");
ages.push_back("38-43");
ages.push_back("48-53");
ages.push_back("60-");
return ages;
}
vector<String> ages = ageLabels();
int main(int arc, char** argv) {
Mat src = imread("1.jpg");
namedWindow("input", CV_WINDOW_AUTOSIZE);
imshow("input", src);
CascadeClassifier detector;
detector.load(haar_xml);
vector<Rect>faces;
Mat gray;
cvtColor(src, gray, CV_BGR2GRAY);
detector.detectMultiScale(gray, faces, 1.02, 3, 0, Size(30, 30));
//读入模型文件和描述文件
Net age_net = readNetFromCaffe(age_txt, age_model);
Net gender_net = readNetFromCaffe(gender_txt, gender_model);
for (int i = 0; i < faces.size(); i++) {
rectangle(src, faces[i], Scalar(0, 255, 0), 2);
predict_age(age_net, src(faces[i]));
predict_gender(gender_net, src(faces[i]));
}
imshow("output", src);
waitKey(0);
return 0;
}
void predict_age(Net &net, Mat &image) {
//将图像转化为网络输入的格式
Mat blob = blobFromImage(image, 1.0, Size(227, 227));
//输入
net.setInput(blob,"data");
//前向传播
Mat prob = net.forward("prob");
Point classNum;
double classProb;
minMaxLoc(prob, NULL, &classProb, NULL, &classNum);
putText(image, format("%s", ages.at(classNum.x).c_str()), Point(2, 15), FONT_HERSHEY_PLAIN, 1, Scalar( 0, 0, 255), 1);
}
void predict_gender(Net &net, Mat &image) {
Mat blob = blobFromImage(image, 1.0, Size(227, 227));
net.setInput(blob, "data");
Mat prob = net.forward("prob");
Point classNum;
double classProb;
putText(image, format("%s",(prob.at<float>(0,0)>prob.at<float>(0, 1)? "female":"male")), Point(2, 25), FONT_HERSHEY_PLAIN, 1, Scalar(0, 0, 255), 1);
}