cpp-BP神经网络与特征脸实现人脸表情识别(二)-实现人脸识别


最新网络的c++实现位于 http://blog.csdn.net/mr_w1997/article/details/72353659

包含本篇所用到的神经网络  http://blog.csdn.net/mr_w1997/article/details/54973376


我使用的是 yale 大学的人脸库 解压后将文件夹放入项目文件的文件夹中 链接:http://download.csdn.net/detail/mr_w1997/9752209


以下为笑脸的训练与测试 需要 了解PCA原理,opencv简单的使用以及opencv的pca类 楼主使用 VS2015 加 opencv

基本思路就是 将图片通过PCA降维,将降维后的数据输入网络,并指定输出值进行训练 详情搜索 PCA数学原理、PCA实现人脸降维,特征脸与BP神经网络实现人脸识别


代码如下:

#include 
#include 
#include 
#include "net.h"
#include 
#include 
#include 
#include 

#define TEST_FACE 3

#define TESTNUM 4
#define ITEMNUM 11
#define GROUPNUM 15
#define WIDTH 100
#define HEIGHT 100
#define FEATURENUM 6


using namespace std;

string int2str(const int num)
{
	char tmp[10];
	sprintf(tmp, "%d", num);
	string str = tmp;
	return str;
}

void copyRow(cv::Mat Dest, cv::Mat Sour, int cnt)
{
	for (int i = 0; i < Sour.cols; ++i)
		Dest.at(cnt, i) = Sour.at(0, i);
}

int main()
{
	string head = "Yale人脸库\\yalefaces\\";
	string tail = ".bmp";

	cv::Mat database(GROUPNUM, WIDTH*HEIGHT, CV_32FC1);
	cv::Mat row_tmp;
	for (int i = 0; i < GROUPNUM; ++i)
	{
		string gnum;
		if (i + 1 < 10)
			gnum = int2str(0) + int2str(i+1) + "\\";
		else
			gnum = int2str(i+1) + "\\";
	
		string name = head + gnum;
		string znum = "s" + int2str(TEST_FACE) + tail;
		name += znum;

		cv::Mat data = cv::imread(name.c_str(), CV_LOAD_IMAGE_GRAYSCALE);

		cv::Mat tdata;
		data.convertTo(tdata, CV_32FC1);
			
		tdata.reshape(1, 1).row(0).convertTo(row_tmp, CV_32FC1);
		copyRow(database, row_tmp, i);
		
	}

	cv::PCA pca(database, cv::Mat(), CV_PCA_DATA_AS_ROW, FEATURENUM);
	cv::Mat eigenvectors = pca.eigenvectors.clone();
	
	for (int i = 0; i < eigenvectors.rows; ++i)
	{
		cv::normalize(eigenvectors.row(i), eigenvectors.row(i), 255);
	}
	
	cv::Mat Result = pca.project(database);
	
	int in = FEATURENUM;
	int ou = 4;
	double **outputs = new double*[ITEMNUM] {
			new double[ou]{0,0,0,0},
			new double[ou]{1,0,0,0},
			new double[ou]{0,1,0,0},
			new double[ou]{0,0,1,0},
			new double[ou]{0,0,0,1},
			new double[ou]{1,1,0,0},
			new double[ou]{0,1,1,0},
			new double[ou]{0,0,1,1},
			new double[ou]{1,0,1,0},
			new double[ou]{0,1,0,1},
			new double[ou]{1,0,0,1}
		};
	DataSet *trainingSet = new DataSet(in, ou);
	DataSet *testSet = new DataSet(in, ou);
	double *tmp_data = new double[in];
	for (int i = 0; i < GROUPNUM; ++i)
	{
		for (int j = 0; j < in; ++j)
		{
			tmp_data[j] = Result.at(i, j);
		}

		if(iAddRow(tmp_data, outputs[TEST_FACE - 1]);
		else
			trainingSet->AddRow(tmp_data, outputs[TEST_FACE - 1]);
	}
	if (tmp_data)
		delete tmp_data;
	trainingSet->Normaliz();
	testSet->Normaliz();

	//层激励函数类型 神经元个数... 学习速率
	MultiLayerPerceptron *m = new MultiLayerPerceptron(FUNCTYPE_LINEAR, FEATURENUM, FUNCTYPE_SIGMOID, 2* FEATURENUM + 3, FUNCTYPE_SIGMOID, ou, 0.9);
	
	//学习1000次
	for (int i = 0; i < 1000; ++i)
		m->Learn(trainingSet);
	
	m->Test(testSet);
	
	cv::namedWindow("Gone Girl");
	cv::Mat aaa = database.row(10).reshape(1, HEIGHT);
	for (int i = 0; i < aaa.rows; ++i)
		for (int j = 0; j < aaa.cols; ++j)
			aaa.at(i, j) /= 255;
	cv::imshow("Gone Girl", aaa);
	cv::waitKey(0);

	system("pause");
	return 0;
}

1.

#define TEST_FACE 3			所测试表情的序号 1-11(数据集中每人有11张图片,即11种表情) 手动更改比较low

#define TESTNUM 4			用于测试的训练数据个数为4  用于训练的为11-4
#define ITEMNUM 11			每个人有11张图片
#define GROUPNUM 15			15个人
#define WIDTH 100			图片宽 像素
#define HEIGHT 100			图片高
#define FEATURENUM 6			pca后所保留特征向量的个数

2.

cv::Mat data = cv::imread(name.c_str(), CV_LOAD_IMAGE_GRAYSCALE);

cv::Mat tdata;
data.convertTo(tdata, CV_32FC1);
			
tdata.reshape(1, 1).row(0).convertTo(row_tmp, CV_32FC1);
copyRow(database, row_tmp, i);
读取图片并且转化为浮点型,将其重塑成行向量并且拷贝至 row_tmp,将行向量拷贝至database中,database每一行是一张图片的数据,

ps(若要显示浮点数据图片,应将每个元素除以255 即 a /= 255,否则为白色)

3.

cv::PCA pca(database, cv::Mat(), CV_PCA_DATA_AS_ROW, FEATURENUM);
cv::Mat eigenvectors = pca.eigenvectors.clone();
	
for (int i = 0; i < eigenvectors.rows; ++i)
{
	cv::normalize(eigenvectors.row(i), eigenvectors.row(i), 255);
}
	
cv::Mat Result = pca.project(database);

通过 PCA 获取新的特征向量 eigenvectors 注意!!需要分别归一化每一行特征向量,之后方可显示特征脸,否则特征脸为黑色。
通过 project 获取新的数据 Result

	int in = FEATURENUM;
	int ou = 4;
	double **outputs = new double*[ITEMNUM] {
			new double[ou]{0,0,0,0},
			new double[ou]{1,0,0,0},
			new double[ou]{0,1,0,0},
			new double[ou]{0,0,1,0},
			new double[ou]{0,0,0,1},
			new double[ou]{1,1,0,0},
			new double[ou]{0,1,1,0},
			new double[ou]{0,0,1,1},
			new double[ou]{1,0,1,0},
			new double[ou]{0,1,0,1},
			new double[ou]{1,0,0,1}
		};
	DataSet *trainingSet = new DataSet(in, ou);
	DataSet *testSet = new DataSet(in, ou);
	double *tmp_data = new double[in];
	for (int i = 0; i < GROUPNUM; ++i)
	{
		for (int j = 0; j < in; ++j)
		{
			tmp_data[j] = Result.at(i, j);
		}

		if(iAddRow(tmp_data, outputs[TEST_FACE - 1]);
		else
			trainingSet->AddRow(tmp_data, outputs[TEST_FACE - 1]);
	}
	if (tmp_data)
		delete tmp_data;
	trainingSet->Normaliz();
	testSet->Normaliz();

建立训练集以及测试集 并且归一化

	//层激励函数类型 神经元个数... 学习速率
	MultiLayerPerceptron *m = new MultiLayerPerceptron(FUNCTYPE_LINEAR, FEATURENUM, FUNCTYPE_SIGMOID, 2* FEATURENUM + 3, FUNCTYPE_SIGMOID, ou, 0.9);
	
	//学习1000次
	for (int i = 0; i < 1000; ++i)
		m->Learn(trainingSet);
	
	m->Test(testSet);

训练并且测试

附上一张笑脸表情的结果

cpp-BP神经网络与特征脸实现人脸表情识别(二)-实现人脸识别_第1张图片



你可能感兴趣的:(projects)