opencv学习之路(41)、人脸识别
一、人脸检测并采集个人图像
//take_photo.cpp
#include<opencv2/opencv.hpp> using namespace cv; using namespace std; void take_photo() { VideoCapture cap(0); //打开摄像头 if (!cap.isOpened()) return; //加载级联检测器 CascadeClassifier cascade; cascade.load("F:/opencv3.2/Release_x64/etc/haarcascades/haarcascade_frontalface_alt_tree.xml"); Mat frame; vector<Rect>faces; int count = 0; while (cap.read(frame)) //相当于cap >> frame { cascade.detectMultiScale(frame, faces, 1.1, 1, 0, Size(100, 100), Size(400, 400));//检测是否有人脸 for (int i = 0; i < faces.size(); i++) { if (count % 10 == 0) { //每10帧保存一次人脸图像 Mat dst; resize(frame(faces[i]), dst, Size(92, 112));//设置人脸图像大小 cvtColor(dst, dst, COLOR_BGR2GRAY);//转为灰度图节省计算 imwrite(format("att_faces/s41/pic%d.jpg", count / 10), dst); } rectangle(frame, faces[i], Scalar(0, 255, 0)); } imshow("video", frame); //按下任意键退出摄像头(waitkey在本系统环境下默认为255),或者是保存了20张人脸图片后,退出 if (waitKey(50) != 255 || count / 10>20) break; count++; } cap.release(); destroyAllWindows();//关闭所有窗口 }
运行程序,打开摄像头后会自动保存人脸图像,头不要晃动,表情变化即可,对于不合适的照片还需进行筛选。
二、基于特征脸算法的人脸识别
//face_recognition.cpp #include <opencv2/opencv.hpp> #include <opencv2/face.hpp> using namespace cv; using namespace cv::face; using namespace std; double face_recognition() { //读取文件,转换为数据流 string filename = string("at.txt"); ifstream file(filename.c_str(), ifstream::in); if (!file) cout << "error" << endl; string line, path, classlabel; vector<Mat>image; vector<int>labels; char separator = ';'; while (getline(file, line)) { stringstream liness(line); getline(liness, path, separator); getline(liness, classlabel); if (!path.empty() && !classlabel.empty()) { //cout << "path:" << path<< endl; image.push_back(imread(path, 0)); labels.push_back(atoi(classlabel.c_str())); } } if (image.size() < 1 || labels.size() < 1) cout << "invalid image path..." << endl; //最后一个人为测试样本 Mat testSample = image[image.size() - 1]; int testLabel = labels[labels.size() - 1]; image.pop_back(); labels.pop_back(); //EigenFace算法的模型训练 Ptr<BasicFaceRecognizer>model = createEigenFaceRecognizer(); model->train(image, labels); //对样本进行识别 int predictLabel = model->predict(testSample); cout << "actual label:" << testLabel << ",predict label:" << predictLabel << endl; //加载级联检测器 CascadeClassifier cascade; cascade.load("haarcascade_frontalface_alt_tree.xml");//识别时用alt_tree分类器,宁可漏检也不误检 //打开摄像头 VideoCapture cap(0); if (!cap.isOpened()) cout << "error..."; Mat frame; vector<Rect>faces; int correct = 0, total = 0; while (cap.read(frame)) //相当于cap >> frame,读取摄像头的每一帧 { cascade.detectMultiScale(frame, faces, 1.1, 1, 0, Size(80, 100), Size(380, 400));//检测是否有人脸 for (int i = 0; i < faces.size(); i++) { Mat roi = frame(faces[i]); cvtColor(roi, roi, COLOR_BGR2GRAY); resize(roi, testSample, testSample.size()); int label = model->predict(testSample); rectangle(frame, faces[i], Scalar(0, 255, 0)); if (label == 41) { putText(frame, "ZhangChunFu", faces[i].tl(), FONT_HERSHEY_COMPLEX, 1.0, Scalar(0, 0, 255)); correct++; } else putText(frame, format("%d", label), faces[i].tl(), CV_FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0, 0, 255)); } total++; imshow("人脸识别——MR.Zhang", frame); if (waitKey(50) == 27) break; } cap.release(); destroyAllWindows();//关闭所有窗口 waitKey(0); double rate = (1.0*correct) / total; return rate;//返回正确率 }
//main.cpp #include <opencv2/opencv.hpp> #include <opencv2/face.hpp> #include <iostream> using namespace cv; using namespace cv::face; using namespace std; void take_photo(); double face_recognition(); void main() { int flag; double rate; cout << "欢迎使用人脸识别系统(1代表录入人脸,2代表识别人脸),请输入您的选择:" << endl; cin >> flag; cout << "请稍等片刻……"<<endl; switch (flag) { case 1:take_photo(); return; case 2: rate=face_recognition(); break; default: break; } cout << "识别率:" << rate << endl; system("pause"); }