【opencv人脸识别5】通过建立模型(.xml文件)识别出你的脸

【opencv人脸识别5】通过建立模型(.xml文件)识别出你的脸

    通过前面4节的opencv人脸识别的内容,我们已经较完整的实现了人脸识别。本节主要在前4节的基础上,通过构建人脸识别的模型,来进行人脸的预测分类。前4节内容及链接如下:

    1.  【opencv人脸识别1】从图片中检测人脸

    2.  【opencv人脸识别2】从视频中检测人脸

    3.  【opencv人脸识别3】从视频中识别出你的脸

    4.   【opencv人脸识别4】训练人脸模型

    本节主要在前4节的基础上,通过构建人脸识别的模型,生成.xml文件,然后利用该模型进行人脸的预测分类。

大致流程  

    要想从视频中识别你的脸,大致流程如下:

        1.打开摄像头-> 获取视频帧-> 转化为对图片的操作 ->图片中检测人脸 ->截取检测到的人脸

        2.建立人脸数据库-> 训练人脸识别模型

        3.将截取的人脸与数据库进行对比 -> 利用模型进行预测-> 识别出人脸

所用人脸样本:

      本实验所采用的实验数据来自ORL人脸库,人脸图为灰度图,共40个人,每人10张,每张图片大小为92*112。并且在库中添加了自己的人脸样本,便于后续识别。

                

程序实现:

//face_recog_from_video.cpp 定义控制台应用程序的入口点。
#include "stdafx.h"
#include "opencv2/opencv.hpp"
#include "opencv2/face.hpp"
#include <stdio.h>
#include<iostream>

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

/** Function Headers */
void detectAndDisplay(Mat frame);
static  void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, int max, int min, char separator);

/** Global variables */
String face_cascade_name = "./xml/haarcascade_frontalface_alt2.xml";
CascadeClassifier face_cascade;
Ptr<EigenFaceRecognizer> modelPCA = EigenFaceRecognizer::create();// 创建特征脸模型  EigenFaceRecognizer

String window_name = "Capture - Face Recognition";

/** @function main */
int main(int argc, const char** argv)
{
	string csvFile = ".\\data\\at.txt";
	vector<Mat> images;
	vector<int> labels;
	int CountMax = 9, CountMin = 0;

	// 读取csv文件  
	try
	{
		read_csv(csvFile, images, labels, CountMax, CountMin, ';'); //读取csvFile中所有的img和label  
	}
	catch (cv::Exception& e) // 异常检查  
	{                 
		cerr << "Error opening file\" " << csvFile << "\".reason: " << e.msg << endl; 
		exit(-1);
	}


	// 若未读取到足够图片,也退出  
	if (images.size() <= 1)
	{
		string errMsg = "THis demo needs at least 2 images to work.please add images!";
		CV_Error(CV_StsError, errMsg);

	}
	cout << "train1.读取ok" << endl;

	// 训练模型,并将训练好的人脸模型保存到.xml中   
	modelPCA->train(images, labels); //训练  
	modelPCA->save("MyFacePcaModel.xml"); 
	cout << "train2.创建脸模型ok" << endl;
	
	// 视频采集
	VideoCapture capture;
	Mat frame;

	//-- 1. Load the cascades
	if (!face_cascade.load(face_cascade_name)) { printf("--(!)Error loading face cascade\n"); return -1; };

	//-- 2. Read the video stream
	capture.open(0); //打开摄像头
	if (!capture.isOpened()) { printf("--(!)Error opening video capture\n"); return -1; }

	while (capture.read(frame)) //读取帧
	{
		if (frame.empty())
		{
			printf(" --(!) No captured frame -- Break!");
			break;
		}

		//-- 3. Apply the classifier to the frame
		detectAndDisplay(frame);

		if (waitKey(10)  == 'k') { break; } // escape  
	}
	return 0;
}

/** @function detectAndDisplay */
void detectAndDisplay(Mat frame)
{
	std::vector<Rect> faces;
	Mat frame_gray;

	cvtColor(frame, frame_gray, COLOR_BGR2GRAY);  //BGR 转化为灰度图
	equalizeHist(frame_gray, frame_gray);   //直方图均衡化
	//-- Detect faces
	face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(60, 60));

	for (size_t i = 0; i < faces.size(); i++)
	{
		Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2); // 人脸中心坐标
		ellipse(frame, center, Size(faces[i].width / 2, faces[i].height / 2), 0, 0, 360, Scalar(255, 0, 255), 4, 8, 0); // 椭圆

		Mat faceROI = frame_gray(faces[i]);
		Mat face_test;
		 
		resize(faceROI, face_test, Size(92, 112)); // 调整大小为92*112 
		double confidence;
		int predictPCA;
		
		//modelPCA->load("MyFacePcaModel.xml");//加载模型
		modelPCA->predict(face_test, predictPCA, confidence);
		cout << "the predict result is " << predictPCA << endl << "confidence is " << confidence << endl;
		if (predictPCA == 40)
		{
			putText(frame, "Hello lisa", Point(faces[i].x, faces[i].y), FONT_HERSHEY_SIMPLEX, 1.5, Scalar(0, 0, 255), 2);
		}
	}
	//-- Show what you got
	imshow(window_name, frame);
}


static  void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, int max, int min, char separator)
{
	std::ifstream  file(filename.c_str(), ifstream::in); // 以in模式(读取文件模式)打开文件 ,实际是将filename文件关联给 流file 

	if (!file)
	{
		string error_message = "No valid input file was given,please check the given filename";
		CV_Error(CV_StsBadArg, error_message);

	}
	int ii = 0;

	/**********************读取文件.txt内容****************************/
	string line, path, label;
	// [1]读取file文件中的一行字符串给 line  
	while (getline(file, line, '\n'))  // 控制:直到读到file文件末尾(eof标识),才跳出while  
	{
		// [2]将line整行字符串读取到lines(流)中  
		stringstream lines(line); //区别->lines是流,读取字符时,指针会随流而动;而line是string,固定的,下文中的读取每次都是从line头开始  
								  // [3]读取文件中的路径和标签  
		getline(lines, path, separator); //此时光标已走到path之后的位置(即;分号处)  
		getline(lines, label);
		// [4]将图片和标签加入imgs 和 labels  
		if ((path.empty() == 0) && (label.empty() == 0))
		{
			if (ii % 10 <= max && ii % 10 >= min)  //默认每个类别共10张照片  
			{
				Mat img = imread(path, 0);  //第二个参数为0 !!!  
											//Mat img = imread(ImageFileAddress, CV_LOAD_IMAGE_GRAYSCALE),CV_LOAD_IMAGE_GRAYSCALE值为 0,指灰图(原本为“CV_LOAD_IMAGE_UNCHANGED”)  
				if (img.data != 0)
				{
					images.push_back(img); // 将图片 添加到images中  
					labels.push_back(atoi(label.c_str()));
				}
			}
			if (ii<9) ii++;
			else ii = 0;

		}
	}
}

运行结果:


OK! 现在此系统已经能从40多个人中认出小主啦!【opencv人脸识别1-5】系列,也暂告结束。

 -------------------------------------------         END      -------------------------------------


猜你喜欢

转载自blog.csdn.net/u012679707/article/details/80410094