前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于opencv人脸识别

基于opencv人脸识别

作者头像
全栈程序员站长
发布2022-09-05 09:45:20
5270
发布2022-09-05 09:45:20
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

一、准备

链接:代码+数据集 提取码:led1

环境:win10,vs2013,opencv3.2

注:每个代码都可以在vs中单独运行

该项目所有文件如下:

基于opencv人脸识别
基于opencv人脸识别

其中只需要使用的文件如下:

基于opencv人脸识别
基于opencv人脸识别

详细代码:

代码语言:javascript
复制
//这个是生成照片的代码
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

//cv库,哈尔检测人脸使用的配置文件
string haar_face_datapath = "E:/opencv/install/etc/haarcascades/haarcascade_frontalface_alt_tree.xml";


int main(int argc, char** argv) {
	//打开摄像头
	VideoCapture capture(0); 
	if (!capture.isOpened()) {
		printf("could not open camera...\n");
		return -1;
	}
	Size S = Size((int)capture.get(CV_CAP_PROP_FRAME_WIDTH), (int)capture.get(CV_CAP_PROP_FRAME_HEIGHT));
	int fps = capture.get(CV_CAP_PROP_FPS);

	//人脸检测库
	CascadeClassifier faceDetector;
	//人脸检测函数
	faceDetector.load(haar_face_datapath);


	Mat frame;
	namedWindow("camera-demo", CV_WINDOW_AUTOSIZE);
	vector<Rect> faces;
	int count = 0;
	while (capture.read(frame)) {
		flip(frame, frame, 1);
		faceDetector.detectMultiScale(frame, faces, 1.1, 1, 0, Size(100, 120), Size(380, 400));
		for (int i = 0; i < faces.size(); i++) {
			if (count % 10 == 0) {
				Mat dst;
				//重新把照片大小改成模板的大小
				resize(frame(faces[i]), dst, Size(112, 92));
				//保存照片
				imwrite(format("D:/else//led/face_%d.jpg", count), dst);
			}
			rectangle(frame, faces[i], Scalar(0, 0, 255), 2, 8, 0);
		}
		imshow("camera-demo", frame);
		char c = waitKey(10);
		//按键退出截图
		if (c == 27) {
			break;
		}
		count++;
	}

	capture.release();

	waitKey(0);
	return 0;
}
代码语言:javascript
复制
//这个是生成csv文件的教程,直接用shell命令,不需要写代码


1. 打开cmd


2. 输入 F: (因为我的文件在F盘)  注意一定要先进入F盘才可以后续操作,不然会显示找不到文件


3. 输入cd 文件路径,点回车


4. 输入dir /b/s/p/w *.jpg>at.csv 注意,我的文件格式为.jpg
代码语言:javascript
复制
#include <opencv2/opencv.hpp>
#include <opencv2/face.hpp>
#include <iostream>

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

int main(int argc, char** argv) {
	
	//加载自己的csv文件
	string filename = string("D:/else/wyz/at.csv");
	ifstream file(filename.c_str(), ifstream::in);
	if (!file) {
		printf("could not load file correctly...\n");
		return -1;
	}

	string line, path, classlabel;
	vector<Mat> images;
	vector<int> labels;
	char separator = ';';
	while (getline(file, line)) {
		stringstream liness(line);
		getline(liness, path, separator);
		getline(liness, classlabel);
		if (!path.empty() && !classlabel.empty()) {
			//printf("path : %s\n", path.c_str());
			images.push_back(imread(path, 0));
			labels.push_back(atoi(classlabel.c_str()));
		}
	}

	if (images.size() < 1 || labels.size() < 1) {
		printf("invalid image path...\n");
		return -1;
	}

	int height = images[0].rows;
	int width = images[0].cols;
	printf("height : %d, width : %d\n", height, width);

	Mat testSample = images[images.size() - 1];
	int testLabel = labels[labels.size() - 1];
	images.pop_back();
	labels.pop_back();

	// train it,训练自己的模型,到这里已经完成训练操作
	Ptr<BasicFaceRecognizer> model = createEigenFaceRecognizer();
	model->train(images, labels);
	model->save("D:/else/wyz/led_wyz.xml");


	/* 以下两个方法训练模型同样操作
	Ptr<FaceRecognizer> model1 = createFisherFaceRecognizer();
	model1->train(images, labels);
	model1->save("MyFaceFisherModel.xml");

	Ptr<FaceRecognizer> model2 = createLBPHFaceRecognizer();
	model2->train(images, labels);
	model2->save("MyFaceLBPHModel.xml");
	*/



	/* 以下内容用于检测验证自己重建的人脸模,可以直接跳过,本代码全部注释掉了
	// recognition face
	int predictedLabel = model->predict(testSample);
	printf("actual label : %d, predict label :  %d\n", testLabel, predictedLabel);

	Mat eigenvalues = model->getEigenValues();
	Mat W = model->getEigenVectors();
	Mat mean = model->getMean();
	Mat meanFace = mean.reshape(1, height);
	Mat dst;
	if (meanFace.channels() == 1) {
		normalize(meanFace, dst, 0, 255, NORM_MINMAX, CV_8UC1);
	}
	else if (meanFace.channels() == 3) {
		normalize(meanFace, dst, 0, 255, NORM_MINMAX, CV_8UC3);
	}
	imshow("Mean Face", dst);



	// show eigen faces
	for (int i = 0; i < min(25, W.cols); i++) {
		Mat ev = W.col(i).clone();
		Mat grayscale;
		Mat eigenFace = ev.reshape(1, height);
		if (eigenFace.channels() == 1) {
			normalize(eigenFace, grayscale, 0, 255, NORM_MINMAX, CV_8UC1);
		}
		else if (eigenFace.channels() == 3) {
			normalize(eigenFace, grayscale, 0, 255, NORM_MINMAX, CV_8UC3);
		}
		Mat colorface;
		applyColorMap(grayscale, colorface, COLORMAP_JET);
		char* winTitle = new char[128];
		sprintf(winTitle, "eigenface_%d", i);
		imshow(winTitle, colorface);
	}


	// 重建人脸
	for (int num = min(25, W.cols); num < min(W.cols, 300); num += 1) {
		Mat evs = Mat(W, Range::all(), Range(0, num));
		Mat projection = LDA::subspaceProject(evs, mean, images[0].reshape(1, 1));
		Mat reconstruction = LDA::subspaceReconstruct(evs, mean, projection);

		Mat result = reconstruction.reshape(1, height);
		if (result.channels() == 1) {
			normalize(result, reconstruction, 0, 255, NORM_MINMAX, CV_8UC1);
		}
		else if (result.channels() == 3) {
			normalize(result, reconstruction, 0, 255, NORM_MINMAX, CV_8UC3);
		}
		char* winTitle = new char[128];
		sprintf(winTitle, "recon_face_%d", num);
		imshow(winTitle, reconstruction);
	}
	*/

	waitKey(0);
	return 0;
}

二、原理

原理1.PCA(主成分分析)原理

通过对高维数据分析发现他们的相同与不同表达为 一个低维数据模式

主成分不变

细微损失

高维数据到低维数据

原理2.API调用

主要是使用其中的三个函数,来训练自己的数据,函数如下:

代码语言:javascript
复制
// train it
	Ptr<BasicFaceRecognizer> model = createEigenFaceRecognizer();
	model->train(images, labels);
	model->save("D:/else/wyz/led_wyz.xml");
代码语言:javascript
复制
	Ptr<FaceRecognizer> model1 = createFisherFaceRecognizer();
	model1->train(images, labels);
	model1->save("MyFaceFisherModel.xml");

	Ptr<FaceRecognizer> model2 = createLBPHFaceRecognizer();
	model2->train(images, labels);
	model2->save("MyFaceLBPHModel.xml");

三、步骤

1. 算法实现步骤

  1. 数据:ORL att_faces OpenCV的数据 10个人、每人10张照片
  2. 一个图像N宽*N高*N个 112*92*100个矩阵
  3. 平均脸 矩阵计算得到均值
  4. 特征脸 矩阵计算得到特征值
  5. 开始、读训练数据、计算平均脸、计算协方差矩阵、计算特征值、特征矩阵、 PAC降维、子空间模型、检测
  6. 生成CSV文件
  7. 生成自己的xml
  8. 训练
  9. 识别
  10. 识别率
  11. 结果分析

四、结果

结果1.方差均值作用

图像RGB矩阵

空白背景方差不为0,均值为0

基于opencv人脸识别
基于opencv人脸识别
基于opencv人脸识别
基于opencv人脸识别
基于opencv人脸识别
基于opencv人脸识别

结果2.PCA应用

  1. 灰度图像
  2. 描边,画出边缘
基于opencv人脸识别
基于opencv人脸识别
  1. XY表示所有轮廓,N*X*Y
  2. PCA处理,得到协方差矩阵,得到特征值特征向量

N行2列表示所有的点

得到轮廓中心位置

基于opencv人脸识别
基于opencv人脸识别

Eigen得到特征值

基于opencv人脸识别
基于opencv人脸识别

结果3..Eigenface算法

  1. 数据:ORL att_faces OpenCV的数据 10个人、每人10张照片
基于opencv人脸识别
基于opencv人脸识别

平均脸

基于opencv人脸识别
基于opencv人脸识别

2. 一个图像N宽*N高*N个 112*92*100个矩阵

3.平均脸 矩阵计算得到均值

4.特征脸 矩阵计算得到特征值

5.开始、读训练数据、计算平均脸、计算协方差矩阵、计算特征值、特征矩阵、 PAC降维、子空间模型、检测

6.生成CSV文件

7.生成自己的xml

基于opencv人脸识别
基于opencv人脸识别

8.训练

9.识别

基于opencv人脸识别
基于opencv人脸识别

10. 识别率:

基于opencv人脸识别
基于opencv人脸识别
基于opencv人脸识别
基于opencv人脸识别

11. 侧脸影响

基于opencv人脸识别
基于opencv人脸识别

12.暗光条件下,找不到人脸,识别率也降低

基于opencv人脸识别
基于opencv人脸识别

结果4.Fisher算法

  1. 由fisher发现,于是命名FisherFace
  2. 基于LDA降维,求两个对象之间的内差和外差,得到离散矩阵,求特征值特 征向量
  3. FishFace识别在光照上有所进步,光的明暗影响不是很大
基于opencv人脸识别
基于opencv人脸识别

4.识别率问题,因为这里光亮作为主要因素,光亮无法做到细微控制,这里不做详细比较

基于opencv人脸识别
基于opencv人脸识别

5.人脸上半部分处在黑暗环境,与EigenFace比较,差不多同一张图片,这张图能识别出来

基于opencv人脸识别
基于opencv人脸识别

结果5.LBPH算法

此算法和前两种的比较,主要是在光照和侧脸角度上有所加强,这里不再多做比较。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/135733.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年6月4,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
人脸识别
腾讯云神图·人脸识别(Face Recognition)基于腾讯优图强大的面部分析技术,提供包括人脸检测与分析、比对、搜索、验证、五官定位、活体检测等多种功能,为开发者和企业提供高性能高可用的人脸识别服务。 可应用于在线娱乐、在线身份认证等多种应用场景,充分满足各行业客户的人脸属性识别及用户身份确认等需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档