1、下载人脸数据集,典型的有ORL,yale,我这里下载的是ORL人脸数据集,下载网址https://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html。
2、将所有图片的路径保存在一个txt文件中,方便后面读取所有图片。
//ifstream主要对文件读操作
//ofstream主要对文件进行读写
#include
ofstream file;
file.open("path.txt");//新建并打开文件
char str[50] = {};
for (int i = 1; i <= 40; i++) {
for (int j = 1; j <= 10; j++) {
sprintf_s(str, "orl_faces/s%d/%d.pgm;%d", i, j, i);//将数字转换成字符
file << str << endl;//写入
}
}
生成的路径文件如下,前面为人脸路径,后面为该人脸对应的标签:
2、采集自己的人脸:通过摄像头用haar人脸检测实时采集人脸图片,采集后的图片尺寸归一化,即与ORL数据集中图像的尺寸一致,然后保存成jpg格式,可以查看,尽量保持眼睛在一条直线上,表情尽量多样,然后把不好的数据删掉,留下10张放到下载的数据集一起。
//采集人脸数据
#include
using namespace cv;
using namespace std;
int main() {
namedWindow("input", CV_WINDOW_AUTOSIZE);
VideoCapture capture(0);
if (!capture.isOpened()) {
printf("could not open camera\n");
return -1;
}
string path = "haarcascade_frontalface_alt.xml";
CascadeClassifier faceDetector;
faceDetector.load(path);
Mat frame, gray, dst;
vectorfaces;
int count = 0;
while (capture.read(frame)) {
cvtColor(frame, gray, CV_BGR2GRAY);
faceDetector.detectMultiScale(gray, faces, 1.1, 3, 0, Size(50, 50));
for (int i = 0; i < faces.size(); i++) {
if (count % 5 == 0) {
resize(frame(faces[i]), dst, Size(112, 92));
imwrite(format("face capture/%d.jpg", count), dst);
}
rectangle(frame, faces[i], Scalar(0, 255, 0), 2);
}
imshow("face", frame);
char c = waitKey(10);
if (c == 27) {
break;
}
count++;
}
capture.release();
waitKey(0);
return 0;
}
3、将jpg格式转为ORL数据集中的格式pgm。
//将jpg图片转换为pgm格式
#include
using namespace cv;
int main() {
for (int i = 0; i < 10; i++) {
Mat src = imread(format("face capture/%d.jpg", i + 1));
cvtColor(src, src, CV_BGR2GRAY);
imwrite(format("face capture/%d.pgm", i + 1), src);
}
waitKey(0);
return 0;
}
4、新建putText.h头文件项和putText.cpp项,用于显示中文。
5、读取数据,将人脸图像全部读取出来放在一个vecto
6、创建、训练、保存、读取模型:有了以上两组数据,就可创建人脸识别模型,opencv中封装的也是最常见的三种人脸识别算法分别为EigenFace、FisherFace、LBPH,这三种算法的原理在我前面博客都有讲解, 随便选取其中一种即可。然后对人脸进行训练,将训练好的模型保存成xml(二进制)格式文件,这样不用每次运行时都训练,下次识别直接将该模型读取进来即可。这里有点需要注意的是,opencv3.3版本以前保存和读取是使用save和load,opencv3.3以后是通过write和read实现模型的保存和读取,所以你用save保存的模型,在opencv3.3以后的版本中不能使用,会出现如下错误:OpenCV Error: Unspecified error (This Eigenfaces model is not computed yet. Did you call Eigenfaces::train?)
7、实时识别
#include
#include
#include"putText.h"
using namespace cv;
using namespace cv::face;
using namespace std;
int main(int arc, char** argv) {
//【1】读入模型需要输入的数据,用来训练的图像vectorimages和标签vectorlabels
string filename = string("path.txt");
ifstream file(filename);
if (!file) { printf("could not load file"); }
vectorimages;
vectorlabels;
char separator = ';';
string line, path, classlabel;
while (getline(file, line)) {
stringstream lines(line);
getline(lines, path, separator);
getline(lines, classlabel);
printf("%d\n", atoi(classlabel.c_str()));
images.push_back(imread(path, 0));
labels.push_back(atoi(classlabel.c_str()));//atoi(ASCLL to int)将字符串转换为整数型
}
//【2】创建模型,训练模型
Ptr model = EigenFaceRecognizer::create();
model->train(images, labels);
model->write("EigenFaceModel.xml");
//【3】读入训练好的模型,不用每次运行时都训练了
// model->read("EigenFaceModel.xml");
//【4】打开摄像头
VideoCapture capture(0);
if (!capture.isOpened()) {
printf("could not open camera\n");
return -1;
}
//【5】haar人脸检测
string path2 = "haarcascade_frontalface_alt.xml";
CascadeClassifier faceDetector;
faceDetector.load(path2);
//【6】实时识别
Mat frame,gray,dst;
vectorfaces;
while (capture.read(frame)) {
cvtColor(frame, gray, CV_BGR2GRAY);
faceDetector.detectMultiScale(gray, faces, 1.1, 3, 0, Size(50, 50));
for (int i = 0; i < faces.size(); i++) {
resize(gray(faces[i]), dst, Size(112, 92));
int predictedLabel = model->predict(dst);
rectangle(frame, faces[i], Scalar(0, 0, 255), 2);
//putText(frame, format("%s", (predictedLabel == 41 ? "xiaobin" : "unknow")), faces[i].tl(), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 255, 0), 1);
putTextZH(frame, (predictedLabel == 41 ? "童小彬" : "识别错误"), faces[i].tl(), Scalar(0, 255, 0),18);
}
imshow("result", frame);
char c = waitKey(10);
if (c == 27) {
break;
}
}
waitKey(0);
return 0;
}
通过大量实验对比发现,LBPH的效果最佳,可能是由于它基本上不受光照的影响。