c++_opencv的人脸识别起步三训练自己的模型

1、Creating the CSV File

照片需要在程序中读取它,我决定使用CSV文件读取它。一个CSV文件包含文件名,紧跟一个标签。
/path/to/image.ext;0假设/path/to/image.ext是图像,就像你在windows下的c:/faces/person0/image0.jpg。最后我们给它一个标签0。这个标签类似代表这个照片的名字,所以同一张的照片的标签都一样。
打开DOS命令即打开命令控制台,进入相对路径下去,然后进入储存照片的路径下去输入f:\opencv_example\pic>dir /b/s *.jpg >at.txt
即可生成at.txt文件在这里插入图片描述

2、读取CSV文件函数

void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator = ';')
{       
    std::ifstream file(filename.c_str(), ifstream::in);//c_str()函数可用可不用,无需返回一个标准C类型的字符串
    if (!file)
    {
        string error_message = "No valid input file was given, please check the given filename.";
        CV_Error(CV_StsBadArg, error_message);
    }
    string line, path, classlabel;
    while (getline(file, line))//从文本文件中读取一行字符,未指定限定符默认限定符为“/n”
    {
        stringstream liness(line);//这里采用stringstream主要作用是做字符串的分割
        getline(liness, path, separator);//读入图片文件路径以分好作为限定符
        getline(liness, classlabel);//读入图片标签,默认限定符
        if (!path.empty() && !classlabel.empty())//如果读取成功,则将图片和对应标签压入对应容器中 
        {
            images.push_back(imread(path, 0));
            labels.push_back(atoi(classlabel.c_str()));
        }
    }
}

3、开始训练模型

(1)创建一个图像容器和标签容器(createEigenFaceRecognizer()函数来创建分类器时是可以人为指定训练结果的维数以及判别阈值,这里我们采用系统默认的参数)来存储训练图像以及对应人脸标签,然后调用void read_csv()填充这两个容器;
(2)然后创建一个PCA人脸分类器,暂时命名为model吧,创建完成后,调用其中的成员函数train()(train()函数的执行时间与训练样本图片数目有关)来完成分类器的训练。
(3)训练得到的分类器model用save()函数保存成XML文件存储下来,下次用的时候直接用laod()加载就行,

#include<iostream>
#include <fstream>
#include <sstream>
#include <opencv2\opencv.hpp>
#include <opencv2\face.hpp>
#include <windows.h>  
#include  <direct.h>  


using namespace cv;
using namespace std;
using namespace face;

CascadeClassifier face_cascades;
//读取CSV文件函数
void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator = ';')
{
	std::ifstream file(filename.c_str(), ifstream::in);//c_str()函数可用可不用,无需返回一个标准C类型的字符串
	if (!file)
	{
		string error_message = "No valid input file was given, please check the given filename.";
		CV_Error(CV_StsBadArg, error_message);
	}
	string line, path, classlabel;
	while (getline(file, line))//从文本文件中读取一行字符,未指定限定符默认限定符为“/n”
	{
		stringstream liness(line);//这里采用stringstream主要作用是做字符串的分割
		getline(liness, path, separator);//读入图片文件路径以分好作为限定符
		getline(liness, classlabel);//读入图片标签,默认限定符
		if (!path.empty() && !classlabel.empty())//如果读取成功,则将图片和对应标签压入对应容器中 
		{
			images.push_back(imread(path, 0));
			labels.push_back(atoi(classlabel.c_str()));
		}
	}
}


int main()
{
	char   buffer[MAX_PATH];
	_getcwd(buffer, MAX_PATH);
	printf("The  buffer  is:   %s ", buffer);
	string fn_csv;
	fn_csv = buffer;
	fn_csv = fn_csv + "F:\\opencv_example\\pic\\at.txt";
	//string fn_csv = "./pic/at.txt";//读取你的CSV文件路径.  相对路径读取失败linux

	vector<Mat> images;// 2个容器来存放图像数据和对应的标签
	vector<int> labels;
	read_csv(fn_csv, images, labels);//从csv文件中批量读取训练数据
	Ptr<FaceRecognizer> model = createEigenFaceRecognizer();
	model->train(images, labels);
	model->save("F:\\opencv_example\\pic\\MyFaceRecognizer.xml");//保存路径
	return 0;
}

4、程序

还可以输出一些与训练集相关的结构,比如训练集的均值特征脸、重构特征脸等
//获得特征值,特征向量,均值 平均脸
Mat eigenvalues = model->getEigenValues();
Mat eigenvectors = model->getEigenVectors();
Mat mean = model->getMean();
Mat meanFace = mean.reshape(1, height);
Mat dst;
dst = normal(meanFace, dst);
imshow(“Mean Face”, dst);

//特征脸
for (int i = 0; i < min(10, eigenvectors.cols); i++)
{
	Mat ev = eigenvectors.col(i).clone();
	Mat eigenFace = ev.reshape(1, height);
	Mat grayscale;
	grayscale = normal(eigenFace, grayscale);
	Mat colorface;
	applyColorMap(grayscale, colorface, COLORMAP_BONE);
	char* winTitle = new char[128];
	sprintf(winTitle, "eigenface_%d", i);
	imshow(winTitle, colorface);
}

//重建人脸
for (int num = min(10, eigenvectors.cols); num < min(300, eigenvectors.cols); num += 15)
{
	Mat evs = Mat(eigenvectors, Range::all(), Range(0, num));
	Mat projection = LDA::subspaceProject(evs, mean, image[0].reshape(1, 1));
	Mat reconstruction = LDA::subspaceReconstruct(evs, mean, projection);

	Mat result = reconstruction.reshape(1, height);
	reconstruction = normal(result, reconstruction);
	char* winTitle = new char[128];
	sprintf(winTitle, "recon_face_%d", num);
	imshow(winTitle, reconstruction);
}
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值