欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

经典人脸识别算法小结——EigenFace, FisherFace & LBPH(上)

程序员文章站 2022-07-12 20:57:21
...

该文章由下面两部分组成:

1).经典人脸识别算法小结——EigenFace, FisherFace & LBPH(上),这部分介绍人脸开源库,和图片的读取等准备工作。

2).经典人脸识别算法小结——EigenFace, FisherFace & LBPH(下),这部分介绍三种人脸识别算法。


1. 人脸数据库

在开始之前,首先介绍几个常用的开源face database,上面可以下载人脸图像作为学习算法的数据库。目前可以开放的数据库比较多,而且其中一些也有特别的针对性,本文我们将用到的是AT&T Laboratories Cambridge开放的ORL数据库,可以点击链接,下载数据库。该数据库一共包含了40个人的人脸数据,每一组有10张不同条件下的照片,可以点击链接预览

另外还有很多其他的数据库,可以参考:

1).人脸数据库汇总

2).FaceDataset常用的人脸数据库

3).常用人脸数据库


2. 人脸数据读取

由于图片较多,需要先得到一个图片的list,再按照list一个个去读,比较方便。程序如下,如果对里面的函数不了解,可以参考VS编译——C/C++遍历库目录得到附加依赖项列表,里面的两篇参考博客中有详细的讲解。

#include<io.h>  //for _findxxxx function
#include<iostream>  
#include<string>  
#include<vector>  
#include<direct.h>//for _chdir()  
#include<fstream>  

using namespace std;

int getList(string dir, string fileType, vector<string> &fileList, string label);
int cf_findFileFromDir(string mainDir, vector<string> &files);

int main()
{
	string dir = "D:\\Opencv Picture\\Face\\ORL";//需要读取的文件夹路径
	const char *pDir = dir.c_str();
	vector<string> fileList;
	_chdir(pDir);//设置工作路径  
	ofstream list;
	//以写入的方式打开.txt文件,没有的话就创建该文件  
	list.open("d:\\Opencv Picture\\Face\\list.txt", ios::out);
	cf_findFileFromDir(dir, fileList);
	for (vector<string>::iterator it = fileList.begin(); it < fileList.end(); ++it)
	{
		list << *it << '\n';
	}
	list.close();
	return 0;
}

int cf_findFileFromDir(string mainDir, vector<string> &fileList)
{
	fileList.clear();
	const char *dir = mainDir.c_str();
	_chdir(dir);//设置工作

	long long hFile;
	_finddata_t fileinfo;

	if ((hFile = _findfirst("*.*", &fileinfo)) != -1)
	{
		do
		{
			if ((fileinfo.attrib & _A_SUBDIR))//找到文件夹(找到子目录,且没有读写限制)  
			{
				if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)//"."和".."分别代表当前目录和父级目录,读取文件时,前两个会检测到这两个,这里是为了避开他们
				{
					//获取子目录的路径
					char subdir[_MAX_PATH];
					strcpy_s(subdir, dir);
					strcat_s(subdir, "\\");
					strcat_s(subdir, fileinfo.name);
					string label_t = fileinfo.name;

					/*int pos = label.find("s");
					label.erase(pos, 1);*/
					string label = label_t.substr(1, label_t.length()-1);

					//读取子目录下的.pgm
					string filetype="*.pgm";
					getList(subdir,filetype,fileList,label);
				}
			}

		} while (_findnext(hFile, &fileinfo) == 0);
		_findclose(hFile);
		return 1;
	}
	else
		return -1;
}

//在dir路径下读取fileType类型的文件,在fileList下保存文件的地址,label保存标签值
int getList(string dir,string fileType, vector<string> &fileList,string label)
{
	const char *pDir = dir.c_str();
	_chdir(pDir);//设置工作路径  

	struct _finddata_t fileinfo;
	long long hFile;//类型很关键,win10一定要long long类型  
	if ((hFile = _findfirst(fileType.c_str(), &fileinfo)) == -1)
		return -1;
	else {
		do {
			cout << fileinfo.name << endl; //显示文件名字
			string finalDir=dir;
			finalDir = finalDir + "\\" + fileinfo.name+";"+label;
			fileList.push_back(finalDir);
		} while (_findnext(hFile, &fileinfo) == 0);
	}
	return 0;
}

生成的list.txt如下,分号前面的是图片的路径,空格后面是图片对应的label。

经典人脸识别算法小结——EigenFace, FisherFace & LBPH(上)