人脸识别之三识别视频流(摄像头)中的人脸
程序员文章站
2022-07-12 20:51:09
...
前面两篇讲了人脸库的建立及模型训练,为本篇识别人脸做好准备。
本篇将在前两篇所做的工作的基础上展开。
首先,将上篇得到的三个训练模型文件(MyFaceFisherModel.xml、MyFaceLBPHModel.xml、MyFacePCAModel.xml)复制至当前目录,因为人脸识别时以这三个文件作为依据。
本篇亦以三种方法进行识别。
大概流程如下:
1、打开摄像头;
2、加载人脸检测器、人脸模型;
3、对图像缩放处理(提高效率),检测人脸并框出;
4、识别人脸(以人脸模型中的作对比)。
代码【opencv-3.2.0版本】:
#include <opencv2/opencv.hpp>
#include "opencv2/core.hpp"
#include "opencv2/face.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
using namespace cv;
using namespace cv::face;
using namespace std;
#define ROW_MIN 45
int exitFlag = 0;
int DetectAndDraw(Mat& img, CascadeClassifier& cascade,
double scale, Mat& facesImg);
int main()
{
int ret = 0;
double scale = 4;
VideoCapture cap(0); //打开摄像头
if (!cap.isOpened())
{
printf("open camera failed.\n");
return -1;
}
// 加载级联分类器
CascadeClassifier cascade;
ret = cascade.load("/root/library/opencv/opencv-3.2.0/data/haarcascades/haarcascade_frontalface_alt.xml");
if( !ret )
{
printf("load xml failed[ret=%d].\n", ret);
return -1;
}
cout << "load xml succeed. " << endl;
// 加载训练好的人脸模型
Ptr<BasicFaceRecognizer> modelPCA = createEigenFaceRecognizer();
modelPCA->load("MyFacePCAModel.xml");
Ptr<BasicFaceRecognizer> modelFisher = createFisherFaceRecognizer();
modelFisher->load("MyFaceFisherModel.xml");
Ptr<LBPHFaceRecognizer> modelLBPH = createLBPHFaceRecognizer();
modelLBPH->load("MyFaceLBPHModel.xml");
Mat frame;
while (!exitFlag)
{
cap >> frame;
if(frame.empty())
{
continue;
}
//建立用于存放人脸的向量容器
Mat faces;
ret = DetectAndDraw(frame, cascade, scale, faces);
if(ret <= 0) // 没有人脸
{
cout << "faces.size <= 0" << endl;
continue;
}
Mat face_resize;
int predictPCA = 0;
int predictFisher = 0;
int predictLBPH = 0;
if (faces.rows >= ROW_MIN) // 控制人脸不能太小(远)
{
resize(faces, face_resize, Size(92, 112));
}
else
{
printf("face.rows[%d] < %d\n", faces.rows, ROW_MIN);
continue;
}
if (!face_resize.empty())
{
//测试图像应该是灰度图
predictPCA = modelPCA->predict(face_resize);
predictFisher = modelFisher->predict(face_resize);
predictLBPH = modelLBPH->predict(face_resize);
}
cout << "predictPCA : " << predictPCA << endl;
cout << "predictFisher: " << predictFisher << endl;
cout << "predictLBPH : " << predictLBPH << endl;
if (waitKey(1) == 27) // Esc
{
exitFlag = 1;
cout << "Esc..." << endl;
break;
}
}
return 0;
}
/* 参数 : 输入图像、级联分类器、缩放倍数、输出人脸 */
int DetectAndDraw(Mat& img, CascadeClassifier& cascade, double scale,
Mat& facesImg)
{
double t = 0;
Mat gray;
Mat GrayImg;
vector<Rect> faces;
double fx = 1 / scale;
cvtColor( img, gray, COLOR_BGR2GRAY ); // 将源图像转为灰度图
/* 缩放图像 */
resize( gray, GrayImg, Size(), fx, fx, INTER_LINEAR);
equalizeHist( GrayImg, GrayImg ); // 直方图均衡化,提高图像质量
/* 检测目标 */
t = (double)getTickCount();
cascade.detectMultiScale( GrayImg, faces,
1.1, 2, 0
//|CASCADE_FIND_BIGGEST_OBJECT
//|CASCADE_DO_ROUGH_SEARCH
|CASCADE_SCALE_IMAGE,
Size(30, 30) );
t = (double)getTickCount() - t;
printf( "detection time = %g ms faces.size = %ld\n", t*1000/getTickFrequency(), faces.size());
/* 画矩形框出目标 */
for ( size_t i = 0; i < faces.size(); i++ ) // faces.size():检测到的目标数量
{
Rect rectFace = faces[i];
facesImg = GrayImg(faces[i]);
rectangle(img, faces[i], Scalar(255, 0, 0), 1, 8, 0); // 缩放后的人脸
rectangle( img, Point(rectFace.x, rectFace.y) * scale,
Point(rectFace.x + rectFace.width, rectFace.y + rectFace.height) * scale,
Scalar(0, 255, 0), 2, 8); // 还原后的人脸
}
imshow( "FaceDetect", img ); // 显示
if(waitKey(1) == 27) // 显示后要添加延时
{
exitFlag = 1;
}
return faces.size();
}
编译、运行结果:
detection time = 23.5059 ms faces.size = 1
predictPCA : 1
predictFisher: 1
predictLBPH : 1
Esc...
注:蓝色框为缩放后的人脸位置,绿色框为还原后的人脸位置。