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

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

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

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

    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;//写入
		}		
	}

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

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

//人脸数据采集

#include<opencv2\opencv.hpp>
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;
	vector<Rect>faces;
	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<opencv2\opencv.hpp>
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<Mat> images中,人脸图像对应的标签放在一个vector<int> 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<opencv2\opencv.hpp>
#include<opencv2\face.hpp>
#include"putText.h"

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

//char win_title[40] = {};
int main(int arc, char** argv) {
	//【1】读入模型需要输入的数据,用来训练的图像vector<Mat>images和标签vector<int>labels

	//string filename = string("path.txt");
	//ifstream file(filename);
	//if (!file) { printf("could not load file"); }
	//vector<Mat>images;
	//vector<int>labels;
	//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<BasicFaceRecognizer> 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;
	vector<Rect>faces;
	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;
}

猜你喜欢

转载自blog.csdn.net/qq_24946843/article/details/82898738