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

2 篇文章 0 订阅

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

总的来说,当你走过一遍以后,会发现其实很简单,基本都是调用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,无所谓的,能找到自己就行。

      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,真是是拿智商在支配我,别说了,多看基础东西!

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

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

胆小勿看下滑。。。。。



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


我本人比较帅

把识别不出的仙女奉上:



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

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值