opencv学习笔记六十九:人脸识别综合实践

1、下载人脸数据集,典型的有ORL,yale,我这里下载的是ORL人脸数据集,下载网址https://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html。

2、将所有图片的路径保存在一个txt文件中,方便后面读取所有图片。

    //ifstream主要对文件读操作
    //ofstream主要对文件进行读写

    #include
    ofstream file;
	file.open("path.txt");//新建并打开文件
	char str[50] = {};
	for (int i = 1; i <= 40; i++) {
		for (int j = 1; j <= 10; j++) {	
			sprintf_s(str, "orl_faces/s%d/%d.pgm;%d", i, j, i);//将数字转换成字符
			file << str << endl;//写入
		}		
	}

 生成的路径文件如下,前面为人脸路径,后面为该人脸对应的标签:

opencv学习笔记六十九:人脸识别综合实践_第1张图片

2、采集自己的人脸:通过摄像头用haar人脸检测实时采集人脸图片,采集后的图片尺寸归一化,即与ORL数据集中图像的尺寸一致,然后保存成jpg格式,可以查看,尽量保持眼睛在一条直线上,表情尽量多样,然后把不好的数据删掉,留下10张放到下载的数据集一起。  

//采集人脸数据

#include
using namespace cv;
using namespace std;

int main() {
	namedWindow("input", CV_WINDOW_AUTOSIZE);
	VideoCapture capture(0);
	if (!capture.isOpened()) {
		printf("could not open camera\n");
		return -1;
	}

	string path = "haarcascade_frontalface_alt.xml";
	CascadeClassifier faceDetector;
	faceDetector.load(path);

	Mat frame, gray, dst;
	vectorfaces;
	int count = 0;
	while (capture.read(frame)) {
		cvtColor(frame, gray, CV_BGR2GRAY);
		faceDetector.detectMultiScale(gray, faces, 1.1, 3, 0, Size(50, 50));
		for (int i = 0; i < faces.size(); i++) {
			if (count % 5 == 0) {
				resize(frame(faces[i]), dst, Size(112, 92));
				imwrite(format("face capture/%d.jpg", count), dst);
			}
			rectangle(frame, faces[i], Scalar(0, 255, 0), 2);
		}

		imshow("face", frame);
		char c = waitKey(10);
		if (c == 27) {
			break;
		}
		count++;

	}
	capture.release();
	waitKey(0);
	return 0;
}

3、将jpg格式转为ORL数据集中的格式pgm。

//将jpg图片转换为pgm格式
#include
using namespace cv;

int main() {
	for (int i = 0; i < 10; i++) {
		Mat src = imread(format("face capture/%d.jpg", i + 1));
		cvtColor(src, src, CV_BGR2GRAY);
		imwrite(format("face capture/%d.pgm", i + 1), src);
	}
	waitKey(0);
	return 0;
}

4、新建putText.h头文件项和putText.cpp项,用于显示中文。

5、读取数据,将人脸图像全部读取出来放在一个vecto images中,人脸图像对应的标签放在一个vector labels中。

6、创建、训练、保存、读取模型:有了以上两组数据,就可创建人脸识别模型,opencv中封装的也是最常见的三种人脸识别算法分别为EigenFace、FisherFace、LBPH,这三种算法的原理在我前面博客都有讲解,  随便选取其中一种即可。然后对人脸进行训练,将训练好的模型保存成xml(二进制)格式文件,这样不用每次运行时都训练,下次识别直接将该模型读取进来即可。这里有点需要注意的是,opencv3.3版本以前保存和读取是使用save和load,opencv3.3以后是通过write和read实现模型的保存和读取,所以你用save保存的模型,在opencv3.3以后的版本中不能使用,会出现如下错误:OpenCV Error: Unspecified error (This Eigenfaces model is not computed yet. Did you call Eigenfaces::train?) 

7、实时识别

#include
#include
#include"putText.h"
using namespace cv;
using namespace cv::face;
using namespace std;

int main(int arc, char** argv) {
	//【1】读入模型需要输入的数据,用来训练的图像vectorimages和标签vectorlabels
	string filename = string("path.txt");
	ifstream file(filename);
	if (!file) { printf("could not load file"); }
	vectorimages;
	vectorlabels;
	char separator = ';';
	string line, path, classlabel;
	while (getline(file, line)) {
		stringstream lines(line);
		getline(lines, path, separator);
		getline(lines, classlabel);
	    printf("%d\n", atoi(classlabel.c_str()));
		images.push_back(imread(path, 0));
		labels.push_back(atoi(classlabel.c_str()));//atoi(ASCLL to int)将字符串转换为整数型
	}
	

	//【2】创建模型,训练模型
	Ptr model = EigenFaceRecognizer::create();
	model->train(images, labels);
	model->write("EigenFaceModel.xml");

	//【3】读入训练好的模型,不用每次运行时都训练了
        // model->read("EigenFaceModel.xml");

	//【4】打开摄像头
	VideoCapture capture(0);
	if (!capture.isOpened()) {
		printf("could not open camera\n");
		return -1;
	}

	//【5】haar人脸检测
	string path2 = "haarcascade_frontalface_alt.xml";
	CascadeClassifier faceDetector;
	faceDetector.load(path2);

	//【6】实时识别
	Mat frame,gray,dst;
	vectorfaces;
	while (capture.read(frame)) {
		cvtColor(frame, gray, CV_BGR2GRAY);
		faceDetector.detectMultiScale(gray, faces, 1.1, 3, 0, Size(50, 50));
		for (int i = 0; i < faces.size(); i++) {		
			resize(gray(faces[i]), dst, Size(112, 92));
			int predictedLabel = model->predict(dst);
			rectangle(frame, faces[i], Scalar(0, 0, 255), 2);
			//putText(frame, format("%s", (predictedLabel == 41 ? "xiaobin" : "unknow")), faces[i].tl(), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 255, 0), 1);
			putTextZH(frame,  (predictedLabel == 41 ? "童小彬" : "识别错误"), faces[i].tl(), Scalar(0, 255, 0),18);
		}
		imshow("result", frame);		
		char c = waitKey(10);
		if (c == 27) {
			break;
		}	
	}
	waitKey(0);
	return 0;
}

opencv学习笔记六十九:人脸识别综合实践_第2张图片

通过大量实验对比发现,LBPH的效果最佳,可能是由于它基本上不受光照的影响。 

你可能感兴趣的:(opencv,实时人脸识别,人脸识别综合实践)