目录
一、人脸检测vs人脸识别
二、数据库
三、准备需要识别的人脸
四、人脸识别(OpenCV)
一、人脸检测vs人脸识别
人脸检测只是需要检测图像中是否有人脸,而人脸识别是一个程序能够识别出给定图像或者视频中的人脸。
二、数据库
人脸数据库,这个博客有网盘链接。
三、准备需要识别的人脸
准备一个人的10张左右数量的人脸,放到刚刚下载ORL的数据库中:
捕获人脸代码:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
using namespace std;
using namespace cv;
void detectFace(Mat frame, string path)
{
// 级联分类器加载文件
CascadeClassifier facefier;
facefier.load("/home/jason/file/opencv/haarcascade_frontalface_alt.xml");
VideoCapture capture(0);
vector<Rect> faces;
Mat gray_frame;
int number=0;
while (1)
{
capture >> frame;
imshow("detect face", frame);
cvtColor(frame,gray_frame,COLOR_BGR2GRAY);
equalizeHist(gray_frame,gray_frame);
// 检测人脸
facefier.detectMultiScale(gray_frame, faces);
// 保存人脸
for (size_t i=0; i < faces.size(); i++)
{
// 画框标出人脸
Mat temp = frame.clone();
rectangle(temp,faces[i], Scalar(255, 0,0), 1, 8);
imshow("detect face", temp);
// 扣出人脸
Mat faceROI = frame(faces[i]);
// 过滤
if (faceROI.cols * faceROI.rows > 100 * 100)
{
resize(faceROI, faceROI, Size(92, 112));
string newpath = path + "/" + to_string(number) + ".png";
imwrite(newpath,faceROI);
cout << "file save :" << newpath << endl;
imshow("ROI", faceROI);
number++;
}
}
if(waitKey() == 27)
break;
}
cout << "you save " << number << " face images" << endl;
}
void generator(string path)
{
// 输入文件夹名字
string name;
cout << "Please key the name:\n";
getline(cin, name);
// 新建文件夹
string newpath = path + "/" + name;
cout << "image will save the path:" << newpath.c_str() << endl;
if (!newpath.empty())
{
if(NULL != opendir(newpath.c_str()))
{
cout << "fin a dir same to your input! delete it now!" << endl;
rmdir(newpath.c_str());
}
if (NULL == opendir(newpath.c_str()))
{
mkdir(newpath.c_str(),0777);
}
}
// 检测人脸并扣出来保存到指定位置
Mat frame;
detectFace(frame, newpath);
}
int main()
{
string path = "/home/jason/file";
generator(path);
cout << "Hello World!" << endl;
return 0;
}
四、人脸识别(OpenCV)
实现代码:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <dirent.h>
#include <sys/stat.h>
#include <opencv2/opencv.hpp>
#include <opencv2/face/facerec.hpp>
using namespace cv;
using namespace std;
int label=0;
std::string nam;
vector<Mat> images;
vector<int> labels;
vector<string> names;
void Load_data(const std::string& path)
{
DIR* dir = opendir(path.c_str());
if (dir == nullptr)
{
std::cerr << "Cannot open directory: " << path << std::endl;
return;
}
struct dirent* entry;
while ((entry = readdir(dir)) != nullptr)
{
std::string name = entry->d_name;
if (name == "." || name == "..")
{
continue;
}
std::string fullPath = path + "/" + name;
struct stat stat_buf;
if (stat(fullPath.c_str(), &stat_buf) != 0)
{
std::cerr << "Cannot stat file: " << fullPath << std::endl;
return;
}
// Determine whether it is a folder
if (S_ISDIR(stat_buf.st_mode))
{
std::cout << "Directory: " << fullPath <<std::endl;
Load_data(fullPath);
// label name
label+=1;
nam=name;
}
else if (S_ISREG(stat_buf.st_mode))
{
std::cout << "File: " << fullPath
<< " name:" << nam
<< " label: "<<label<<std::endl;
// 添加到容器中
Mat img = imread(fullPath);
images.push_back(img);
labels.push_back(label);
names.push_back(nam);
}
}
closedir(dir);
}
void FaceRec(const string &path, string person_name="jack")
{
// 准备数据
Load_data(path);
// 训练
// Ptr<cv::face::FaceRecognizer> model = cv::face::FisherFaceRecognizer::create();
Ptr<cv::face::EigenFaceRecognizer> model = cv::face::EigenFaceRecognizer::create();
// Ptr<cv::face::LBPHFaceRecognizer> model = cv::face::LBPHFaceRecognizer(1, 8,8,8,);
model->train(images, labels);
// 创建一个级联分类器 加载一个 .xml 分类器文件. 它既可以是Haar特征也可以是LBP特征的分类器.
CascadeClassifier casc;
casc.load("/home/jason/file/opencv/haarcascade_frontalface_alt.xml");
int jack_label;
for (size_t i=0; i<names.size(); i++)
{
if (names[i] == person_name)
jack_label=labels[i];
}
VideoCapture capture(0);
Mat frame, gray;
vector<Rect> faces;
while (1)
{
// 获取图像
capture >> frame;
imshow("recognizer", frame);
// 预处理
cvtColor(frame,gray,COLOR_RGB2GRAY);
equalizeHist(gray, gray);
// 检测人脸
casc.detectMultiScale(gray, faces);
// 扣出人脸判断是否为目标人物
for(size_t i=0; i<faces.size(); i++)
{
Mat temp = frame.clone();
rectangle(temp, faces[i], Scalar(255, 0, 0), 1, 8);
Mat roi_gray = gray(faces[i]);
resize(roi_gray, roi_gray, Size(92, 112));
imshow("person",roi_gray);
int result;
double confidence=0.8;
// 预测
model->predict(roi_gray, result, confidence);
cout<< "result: " << result
<<"confidence: " << confidence<< endl;
if (result==jack_label)
{
putText(temp, person_name ,Point(faces[i].x, faces[i].y),FONT_ITALIC,
0.5, Scalar(255, 0, 0),1,8);
}
else
{
cout << "not find " << person_name << endl;
}
imshow("recognizer", temp);
}
if (waitKey(10)==27) break;
}
}
int main()
{
std::string path = "/home/jason/file/Face/ORL_Faces";
FaceRec(path,"jack");
return 1;
}
参考资料:
C++创建文件夹和写文件_林多的博客-CSDN博客
C++11标准中遍历文件夹方法_c++11 遍历目录_HotPot_Dumplings的博客-CSDN博客
OpenCV: cv::face::FaceRecognizer Class Reference
https://www.cnblogs.com/zyly/p/9498857.html