(八)OpenCV人脸识别_07_实时人脸识别

本文介绍了一种基于EigenFace算法的人脸识别系统实现过程。系统首先通过VideoCapture类捕获视频流,使用HAAR级联检测器进行人脸检测,然后对检测到的人脸数据进行训练与测试。实时人脸识别部分,系统能检测并识别出特定人脸,同时在图像中标注识别结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 摄像头与人脸数据采集
    VideoCapture类使用
    使用HAAR 级联检测器实现人脸检测
    对检测的人脸数据写入文件保存
    删除错误数据与数据对齐
    采集数据注意点
  2. 数据训练与测试
    基于EigenFace算法实现数据训练与测试
  3. 实时人脸识别
    检测人脸
    识别人脸
    实时显示人脸识别结果
  4. 整体流程:
    人脸数据采集与处理->人脸数据训练与测试->实时人脸检测->人脸识别->显示结果/继续读取下一帧->选择终止->结束
  5. Tips:
    训练与检测的图像必须大小一致,类型为灰度
    VideoCatpture类使用
    HAAR人脸检测
    数据采集通过眼睛标定实现数据一致
#include <opencv2/opencv.hpp>
#include <opencv2/face.hpp>
#include <iostream>

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

String Face_fileName = "haarcascade_frontalface_alt.xml";//opencv自带训练好的人脸识别Haar级联器
//String Face_fileName = "lbpcascade_frontalface.xml";//opencv自带训练好的人脸识别LBP级联器

CascadeClassifier face_cascade;//Haar人脸检测级联分类器

int main(int argc, char** argv)
{
	String filename = string("face_image.txt");//标签Label_Text文件
	//从硬盘到内存
	ifstream file(filename.c_str(), ifstream::in);//c_str()函数可用可不用,无需返回一个标准C类型的字符串
	if (!file)//打开标签文件失败
	{
		cout << "could not load label_file" << endl;
		return -1;
	}

	string line, path, classlabel;
	vector<Mat> images;//存放图像数据
	vector<int> labels;//存放图像标签
	char separator = ';';//分号

	while (getline(file, line)) //getline(cin,inputLine)//cin 是正在读取的输入流,而 inputLine 是接收输入字符串的 string 变量的名称
	{
		stringstream liness(line);//这里采用stringstream主要作用是做字符串的分割
		getline(liness, path, separator);//遇到分号就结束
		getline(liness, classlabel);//继续从分号后面开始,遇到换行结束
		if (!path.empty() && !classlabel.empty())
		{
			images.push_back(imread(path,0));//imread(path,0)//0不能去
			labels.push_back(atoi(classlabel.c_str()));//atoi字符串转换成整型数
		}
	}

	if (images.size() <= 1 || labels.size() <= 1)//如果没有读到足够多的图片
	{
		cout << "读取图片数据失败..." << endl;
	}

	int height = images[0].rows; //得到第一张图片的高度,在下面对图像变形得到他们原始大小时需要
	int width = images[0].cols;
	cout << "读取的图片高度为:" << height << endl << "读取的图片宽度为:" << width << endl;

	//从数据集 中移除最后一张图片,用于做测试,需要根据自己的需要进行修改
	Mat testSample = images[images.size() - 1];//获取最后一张照片
	int testLabel = labels[labels.size() - 1];//获取最后一个标签
	images.pop_back();//移除最后一张图片
	labels.pop_back();//移除最后一个标签

	/*
	特征脸Eigenfaces
	图像表示的问题是他的高维问题。
	二维灰度图像p*q大小,是一个m=q*p维的向量空间,所以一个100*100像素大小的图像就是10,000维的图像空间。
	但是不是所有的维数空间对我们来说都有用?我们可以做一个决定,如果数据有任何差异,我们可以通过寻找主元来知道主要信息。
	主成分分析(Principal Component Analysis,PCA)是把一些可能相关的变量转换成一个更小的不相关的子集。
	一个高维数据集经常被相关变量表示,因此只有一些的维上数据才是有意义的,包含最多的信息。
	PCA方法寻找数据中拥有最大方差的方向,被称为主成分。
	*/
	//创建一个特征脸模型用于人脸识别
	//通过txt文件读取的图像和标签 训练它
	//这里是一个完整的PCA变换
	Ptr<BasicFaceRecognizer> model = EigenFaceRecognizer::create();
	model->train(images, labels);
	
	//人脸识别
	//判断是否成功读取级联器
	if (!face_cascade.load(Face_fileName))
	{
		cout << "face_cascade error" << endl;
		return -1;
	};
	//打开内置摄像头视频流
	VideoCapture capture(0);
	Mat frame;//用来接capture
	Mat frame_gray;
	vector<Rect> faces;//人脸区域
	while (capture.read(frame))
	{
		cvtColor(frame, frame_gray, COLOR_BGR2GRAY);//转换为灰度图
		equalizeHist(frame_gray, frame_gray);//直方图均衡化
		face_cascade.detectMultiScale(frame_gray, faces, 1.2, 3, 0, Size(30, 30));//利用detectMultiScale搜索图像
		for (size_t i = 0; i < faces.size(); i++)
		{
			//检索到人脸则画圆形
			Point center_face(faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5);
			//画椭圆
			ellipse(frame, center_face, Size(faces[i].width*0.5, faces[i].height*0.5)/*长轴短轴*/, 0, 0, 360, Scalar(0, 255, 255), 4, 8, 0);

			Mat ROI_face = frame(faces[i]);
			resize(frame_gray, testSample, testSample.size());
			//对测试图像进行预测,predictedLabel是预测标签结果
			int Face_label = model->predict(testSample);
			putText(frame, format(Face_label == 10 ? "Handsome boy" : "Who're you?"), faces[i].tl(), FONT_HERSHEY_SIMPLEX, 1.5, Scalar(0, 0, 255), 2, 8);
		}

		imshow("人脸识别", frame);
			char c = waitKey(30);
			if (c == 27)
			{
				break;
			}
	}
	waitKey(0);
	return 0;
}

输出结果:
成功检测人脸,并在人脸处绘制黄色圆;
当识别到标签10的人脸时,会出现红色字"Handsome boy";否则出现"Who’re you?"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值