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

人脸检测与识别 (环境:opencv3.3.0 + vs2015)

程序员文章站 2022-03-20 08:23:29
...

首先,全部代码实现参考冰不语,感谢大佬提供代码(查看官网也可),帮助素人学习。

总的来说,当你走过一遍以后,会发现其实很简单,基本都是调用opencv库和opencv_contrib库,关于opencv_contrib的配置方法,CSDN上真正对你路子的方法很少,所以建议初学者安装版本时,选择你参考的安装方法的版本,调试起来会更方便,如果你是3.3.0版本,需要配置contrib的话,可以私信我,我可以分享编译好的install文件给你,免除配置烦恼。

至于为什么写这篇文章,是应为冰不语的版本时opencv2.*的版本,自己再写3.3版本时,遇到很多坑,然后一一填满,所以避免opencv3新手入坑吧,写了这篇总结。

重点开始

  • 数据准备                                                                                                                                                                          ORL人脸数据库,参考:人脸识别之一数据收集和预处理                                                                                                   本人数据准备:
#include <opencv2/opencv.hpp>;
#include <iostream>

using namespace cv;
using namespace std;

char ad[128] = { 0 };
int main()
{
	vector<Rect> faces;
	Mat image, image_gray;

	for (int i = 1; i < 11; i++)
	{
		sprintf_s(ad, "你的照片路径(注意分割符用\\或者/)\\%d.jpg", i);
		image = imread(ad);
		cvtColor(image, image_gray, COLOR_BGR2GRAY);
		equalizeHist(image_gray, image_gray);
		CascadeClassifier face_cascade; //载入分类器
		if (!face_cascade.load("分类器存放目录\\haarcascade_frontalface_alt.xml"))
		{
			cout << "Load haarcascade_frontalface_alt failed" << endl;
			return 0;
		}
		vector<Rect> faceRect;
		face_cascade.detectMultiScale(image_gray, faceRect, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
		for (size_t j = 0; j < faceRect.size(); j++)
		{
			Mat faceROI = image(faceRect[j]);
			Mat MyFace;
			if (faceROI.cols > 100)
			{
				resize(faceROI, MyFace, Size(92, 112));
				string str = format("保存路径\\s41\\%d.jpg", i);
				imwrite(str, MyFace);
			}

		}

	}


}

这部分没遇到什么问题,如有问题,欢迎提问

  • 模型训练                                                                                                                                                 
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <math.h>
    #include <opencv2/opencv.hpp>
    #include <opencv2/face/facerec.hpp>
    #include <opencv2/face.hpp>
    
    using namespace std;
    using namespace cv;
    using namespace cv::face;
    
    
    static Mat norm_0_255(InputArray _src) {
    	Mat src = _src.getMat();
    	// 创建和返回一个归一化后的图像矩阵:  
    	Mat dst;
    	switch (src.channels()) {
    	case1:
    		cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
    		break;
    	case3:
    		cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC3);
    		break;
    	default:
    		src.copyTo(dst);
    		break;
    	}
    	return dst;
    }
    	
    //使用CSV文件去读图像和标签,主要使用stringstream和getline方法  
    static void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator = ';') {
    	std::ifstream file(filename.c_str(), ifstream::in);
    	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)) {
    		stringstream liness(line);
    		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()
    {
    	system("color 3F");
    	//读取文件路径
    	string  fn_csv = "路径\\att_faces\\at.txt";
    
    	//定义容器存放图像数据和标签
    	vector<Mat> images;
    	vector<int> labels;
    
    	//读取数据
    	try
    	{
    		read_csv(fn_csv, images, labels);
    	}
    	catch (cv::Exception& e)
    	{
    		cerr << "Error opening file \"" << fn_csv << "\". Reason: " << e.msg << endl;
    		// 文件有问题,我们啥也做不了了,退出了  
    		exit(1);
    	}
    	// 如果没有读取到足够图片,也退出.  
    	if (images.size() <= 1) {
    		string error_message = "This demo needs at least 2 images to work. Please add more images to your data set!";
    		CV_Error(CV_StsError, error_message);
    	}
    
    	//训练集去除最后一张图片
    	Mat testSample = images[images.size() - 1];
    	int testLabel = labels[labels.size() - 1];
    	images.pop_back();
    	labels.pop_back();
    
    	Ptr<EigenFaceRecognizer> model = EigenFaceRecognizer::create();
    	model->train(images, labels);
    	model->write("MyFacePCAModel.xml");
    
    	Ptr<FisherFaceRecognizer> model1 = FisherFaceRecognizer::create();
    	model1->train(images, labels);
    	model1->write("MyFaceFisherModel.xml");
    
    	Ptr<LBPHFaceRecognizer> model2 = LBPHFaceRecognizer::create();
    	model2->train(images, labels);
    	model2->write("MyFaceLBPHModel.xml");
    
    	// 下面对测试图像进行预测,predictedLabel是预测标签结果  
    	int predictedLabel = model->predict(testSample);
    	int predictedLabel1 = model1->predict(testSample);
    	int predictedLabel2 = model2->predict(testSample);
    
    	string result_message = format("Predicted class = %d / Actual class = %d.", predictedLabel, testLabel);
    	string result_message1 = format("Predicted class = %d / Actual class = %d.", predictedLabel1, testLabel);
    	string result_message2 = format("Predicted class = %d / Actual class = %d.", predictedLabel2, testLabel);
    	cout << result_message << endl;
    	cout << result_message1 << endl;
    	cout << result_message2 << endl;
    
    	waitKey(0);
    	return 0;
    
    }
    问题汇总                                                                                                                                                   1.这里有难度的地方就是at.txt文件的制作,我是按照冰不语的方式做的,但是有一个问题就是,我做出来的,我本人的照片并不是对象41标签,而是35,无所谓的,能找到自己就行。人脸检测与识别 (环境:opencv3.3.0 + vs2015)

      2.特征模型的建立,继续我大哥,冰不语:opencv3.3 API变换,你以为这样就够了嘛,不是的,当我训练完成以后,在进行测试识别的时候, 出现了OpenCV Error: Unspecified error错误,不得不说,百度拯救了我,没错,在opencv3.3以前,save对应load, 3.3就要变成write对应read, 水平真的有限,你体会的到我被那哥错误支配半天的痛苦吗,我都要放弃的时候,找到了答案,题外话,遇到问题,百度百度再百度,人类那么多,总会有和你问题一样的“先行者”,加油,你行的!

  • 识别自己的脸

    冰不语是调用的摄像头,我选择读自己其他的照片,别说这个简单,没有参考的去做这个,你做你还真能行!

代码奉上:

#include <opencv2/opencv.hpp>
#include <opencv2/face.hpp>
#include <opencv2/face/facerec.hpp>
#include <iostream>

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

int main()
{
	system("color 3F");
	Mat image, image_gray;

	image = imread("huangbo.jpg");
	//namedWindow("苏宝宝本人");
	//imshow("苏宝宝本人", image);
	cvtColor(image, image_gray, CV_BGR2GRAY);
	equalizeHist(image_gray, image_gray);
	//imshow("苏宝宝", image_gray);

	CascadeClassifier cascade;
	cascade.load("haarcascade_frontalface_alt.xml");
	vector<Rect> faces(0);
	cascade.detectMultiScale(image_gray, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
	Mat face;
	Point text_lb;
	for (size_t i = 0; i < faces.size(); i++)
	{
		if (faces[i].height > 0 && faces[i].width > 0)
		{
			face = image_gray(faces[i]);
			text_lb = Point(faces[0].x, faces[0].y);
			rectangle(image, faces[0], Scalar(0, 255, 0), 1, 8, 0);
		}
			
	}
    Ptr<EigenFaceRecognizer> modelPCA = EigenFaceRecognizer::create();
	modelPCA -> read("MyFacePCAModel.xml");

	int predictPCA = 50;
	Mat face_test;
	if (face.rows >= 120)
	{
		resize(face, face_test, Size(92, 112));
	}

	if (!face_test.empty())
	{
		predictPCA = modelPCA->predict(face_test);
	}
	if (predictPCA == 50)
	{
		string name2 = "Not RanRansu";
		putText(image, name2, text_lb, FONT_HERSHEY_COMPLEX, 1, Scalar(255, 0, 0));
		cout << "未匹配到合适的人脸" << endl;
		namedWindow("人脸识别结果");
		imshow("人脸识别结果", image);
	}

	if (predictPCA == 35)
	{
		string name = "RanRanSu";
		putText(image, name, text_lb, FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255));
		cout << "我们可爱的苏宝宝本人" << endl;
		namedWindow("人脸识别结果");
		imshow("人脸识别结果", image);	
	}

	waitKey(0);
	return 0;
}

那个model ->read,真是是拿智商在支配我,别说了,多看基础东西!

没有结果的博客不是好博客。。。。。。

警告!!!!!!!!!!!

胆小勿看下滑。。。。。

人脸检测与识别 (环境:opencv3.3.0 + vs2015)


感谢我可爱的舍友RanRanSu出境,祝愿他生活幸福,少和媳妇闹矛盾,好好走下去!!!!


我本人比较帅

把识别不出的仙女奉上:

人脸检测与识别 (环境:opencv3.3.0 + vs2015)


最长的一篇博客,真心希望对你有用,生活快乐!

相关标签: 人脸识别