OpenCv-C++-深度神经网络(DNN)模块-使用CCN模型预测性别与年龄

版权声明:本文为博主原创文章,转载请附上博文链接! https://blog.csdn.net/Daker_Huang/article/details/87738935

本文本次将使用CNN训练的模型预测性别与年龄,关于CNN的原理,可以参考一下文章:
1、https://www.cnblogs.com/fydeblog/p/7450413.html
2、https://blog.csdn.net/liangchunjiang/article/details/79030681
3、https://blog.csdn.net/ice_actor/article/details/78648780

模型文件下载:https://download.csdn.net/download/daker_huang/10972270
学会看描述文件是一项必备的技能,根据.prototxt描述文件,我们需要设置相关参数,如性别的描述文件中:
在这里插入图片描述
上图中输入层是"data",图像大小是227*227。
在这里插入图片描述
上图中最后一层是"prob",也是net.forword()中需要填写的。
这里还需要用到人脸检测的部分,因为计算机是通过脸部判断性别与年龄的。

实例:

#include<opencv2/opencv.hpp>
#include<iostream>
#include<opencv2/dnn.hpp>

using namespace cv;
using namespace std;
using namespace cv::dnn;

//年龄预测的3大文件
string age_model = "D:/test/dnn/gender and  age_dnn/age_net.caffemodel";
string age_prototxt = "D:/test/dnn/gender and  age_dnn/deploy_age.prototxt";
string age_label = "D:/test/dnn/gender and  age_dnn/age_labels.txt";

//性别预测的3大文件
string gender_model = "D:/test/dnn/gender and  age_dnn/gender_net.caffemodel";
string gender_prototxt = "D:/test/dnn/gender and  age_dnn/deploy_gender.prototxt";
string gender_label = "D:/test/dnn/gender and  age_dnn/gender_labels.txt";


//人脸检测文件
string face_file = "D:/OpenCv/opencv 4.0.0/sources/data/haarcascades/haarcascade_frontalface_alt.xml";


void age_predict(Net &net, Mat &image);//预测年龄
void gender_predict(Net &net, Mat &image);//预测性别


vector<string> age_labels();  //年龄标签
vector<string> gender_labels();  //性别标签

int main(int argc, char** argv)
{
	Mat src = imread("D:/test/cnn_gender_age_people.png");
	
	if (!src.data)
	{
		cout << "图片未找到..." << endl;
		return -1;
	}



	CascadeClassifier faces_clf;
	faces_clf.load(face_file);

	//namedWindow("input image", WINDOW_AUTOSIZE);
	//imshow("input image", src);


	Mat gray;

	cvtColor(src, gray, COLOR_BGR2GRAY);
	vector<Rect>faces;//存储人脸矩形数据
	Mat dst;
	
	faces_clf.detectMultiScale(gray, faces, 1.02, 2, 0, Size(24, 24));
	Net age_net = readNetFromCaffe(age_prototxt, age_model);
	Net gender_net = readNetFromCaffe(gender_prototxt, gender_model);

	for (size_t t = 0; t < faces.size(); t++)
	{

		dst = src(faces[t]);  //划取roi区域
		rectangle(src, faces[t], Scalar(30, 255, 30), 2, 8, 0);

		age_predict(age_net, dst);
		gender_predict(gender_net, dst);

	}
	namedWindow("output result image", WINDOW_AUTOSIZE);
	imshow("output result image", src);

	waitKey(0);
	return 0;
}

vector<string> age_labels()
{
	vector<string>agenames;
	ifstream fs(age_label);
	if (!fs.is_open())
	{
		cout << "标签文件不存在,请检查路径..." << endl;
		exit(-1);
	}
	string names;
	while (!fs.eof())
	{
		getline(fs, names);
		if (names.length())
		{
			string temp = names.substr(names.find(" ") + 1);
			agenames.push_back(temp);
		}
	}

	return agenames;

}
vector<string> gender_labels()
{
	vector<string>gendernames;
	ifstream fs(gender_label);
	if (!fs.is_open())
	{
		cout << "标签文件不存在,请检查路径..." << endl;
		exit(-1);
	}
	string names;
	while (!fs.eof())
	{
		getline(fs, names);
		if (names.length())
		{
			string temp = names.substr();
			gendernames.push_back(temp);
		}
	}

	return gendernames;
}



void age_predict(Net & net, Mat & image)
{
	Mat inputblob = blobFromImage(image, 1.0, Size(227, 227));
	net.setInput(inputblob, "data");
	Mat prob = net.forward("prob");
	Mat reprob = prob.reshape(1, 1);//把probreshape成1行n列的矩阵
	double classprob;    //相似度
	Point index_name;      //标签所在的位置
	minMaxLoc(reprob, NULL, &classprob, NULL, &index_name);
	int classid = index_name.x;
	vector<string>ages = age_labels();
	putText(image, format("age:%s", ages.at(classid).c_str()), Point(2, 20),
		FONT_HERSHEY_SIMPLEX, 0.6, Scalar(0, 0, 255), 2, 8, 0);
}

void gender_predict(Net & net, Mat & image)
{
	Mat inputblob = blobFromImage(image, 1.0, Size(227, 227));
	net.setInput(inputblob, "data");
	Mat prob = net.forward("prob");
	Mat reprob = prob.reshape(1, 1);//把probreshape成1行n列的矩阵
	double classprob;    //相似度
	Point index_name;      //标签所在的位置
	minMaxLoc(reprob, NULL, &classprob, NULL, &index_name);
	int classid = index_name.x;
	vector<string>genders = gender_labels();
	putText(image, format("sex:%s", genders.at(classid).c_str()), Point(2, 50),
		FONT_HERSHEY_SIMPLEX, 0.6, Scalar(66, 118, 175), 2, 8, 0);
}



运行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Daker_Huang/article/details/87738935