文章目录
- 制作数据集
- 训练并人脸识别
本文以
OpenCV + CPP 系列(圩七)人脸识别经典算法 为基础,实现简单的人脸识别系统。
若需要实现商业可行的算法,使用深度学习的人脸检测技术,人脸特征提取与存储技术,海量特征向量检索技术。
实现流程:
- 视频(摄像头)获取图像
- 人脸检测技术截取目标区域
- 使用PCA特征训练模型
- 使用摄像头获取人脸进行预测识别
头文件 FaceRecognize.h
:
#pragma once
#include <opencv2/opencv.hpp>
#include <opencv2/face.hpp>
#include <iostream>
#include <fstream>
using namespace cv;
using namespace std;
class FaceRecognize {
public:
void video2image(const char* face_path, const char* model_path);
void video_face_recognize(const char* csv_path, const char* model_path);
};
主函数main.cpp
#include "FaceRecognize.h"
int main(int argc, char**argv) {
const char* csv_path = "D:/opencv-c++/orl_faces/images_info.txt";
const char* face_path = "D:/opencv-c++/our_faces";
const char* face_xml_path = "D:/opencv_build/install/etc/haarcascades/haarcascade_frontalface_alt_tree.xml";
FaceRecognize face_recognize;
//face_recognize.video2image(face_path, face_xml_path);
face_recognize.video_face_recognize(csv_path, face_xml_path);
waitKey(0);
destroyAllWindows();
return 0;
}
制作数据集
void FaceRecognize::video2image(const char* face_path, const char* model_path) {
CascadeClassifier faceDetector;
VideoCapture capture(0);
if (!capture.isOpened()|| !faceDetector.load(model_path)) {
cout << "相机打开失败,或者人脸检测模型加载失败,退出!" << endl;
exit(-1);
}
int height = capture.get(cv::CAP_PROP_FRAME_HEIGHT);
int width = capture.get(cv::CAP_PROP_FRAME_WIDTH);
int FPS = capture.get(cv::CAP_PROP_FPS);
printf("height:%d \t width:%d \t FPS:%d\n", height, width, FPS);
vector<Rect> face_rects;
Mat frame, gray_img, dist_img;
int count = 0;
while (capture.read(frame))
{
cv::cvtColor(frame, gray_img, COLOR_BGR2GRAY);
cv::equalizeHist(gray_img, gray_img);
faceDetector.detectMultiScale(gray_img, face_rects, 1.1, 2, 0, Size(30, 30), Size(380, 400));
for (size_t i = 0; i < face_rects.size(); i++) {
if (count % 3 == 0) {
resize(frame(face_rects[i]), dist_img, Size(100, 100));
cv::imwrite(face_path + format("/face_%d.png", count), dist_img);
}
rectangle(frame, face_rects[i], Scalar(0, 0, 255), 2, 8, 0);
}
count++;
imshow("frame", frame);
if (waitKey(FPS) == 27) {
break;
}
}
capture.release();
}
训练并人脸识别
void load_image_sample(const char* csv_path, vector<Mat>& images, vector<int>& labels) {
ifstream file(csv_path, ifstream::in);
if (!file) {
cout << "could not read files." << endl;
exit(-1);
}
string line, imgPath, classLabel;
while (getline(file, line)) {
stringstream lines(line);
getline(lines, imgPath, '\t');
getline(lines, classLabel);
if (!imgPath.empty() && !classLabel.empty()) {
images.push_back(imread(imgPath, 0));
labels.push_back(atoi(classLabel.c_str()));
}
}
}
void FaceRecognize::video_face_recognize(const char* csv_path, const char* face_xml_path) {
vector<Mat> images;
vector<int> labels;
images.reserve(400);
labels.reserve(400);
load_image_sample(csv_path, images, labels);
if (images.size() < 1 || labels.size() < 1) {
printf("invalid image path...\n");
exit(-1);
}
int height = images[0].rows;
int width = images[0].cols;
printf("查看第一个样本信息:height : %d, width : %d\n", height, width);
// 弹出最后最后一个样本作为测试数据
Mat testImage = images[images.size() - 1];
int testLable = labels[labels.size() - 1];
images.pop_back();
labels.pop_back();
//训练 预测
Ptr<cv::face::BasicFaceRecognizer> model = cv::face::EigenFaceRecognizer::create();
model->train(images, labels);
int predictLabel = model->predict(testImage);
printf("actual label : %d, predict label : %d\n", testLable, predictLabel);
CascadeClassifier faceDetector;
VideoCapture capture(0);
if (!capture.isOpened() || !faceDetector.load(face_xml_path)) {
cout << "相机打开失败,或者人脸检测模型加载失败,退出!" << endl;
exit(-1);
}
int cap_height = capture.get(cv::CAP_PROP_FRAME_HEIGHT);
int cap_width = capture.get(cv::CAP_PROP_FRAME_WIDTH);
int FPS = capture.get(cv::CAP_PROP_FPS);
printf("cap_height:%d \t cap_width:%d \t FPS:%d\n", cap_height, cap_width, FPS);
vector<Rect> face_rects;
Mat frame, gray_img;
while (capture.read(frame))
{
cv::cvtColor(frame, gray_img, COLOR_BGR2GRAY);
cv::equalizeHist(gray_img, gray_img);
faceDetector.detectMultiScale(gray_img, face_rects, 1.1, 2, 0, Size(30, 30), Size(380, 400));
for (size_t i = 0; i < face_rects.size(); i++) {
Mat roi = frame(face_rects[i]);
cvtColor(roi, gray_img, COLOR_BGR2GRAY);
resize(gray_img, testImage, testImage.size());
int label = model->predict(testImage);
rectangle(frame, face_rects[i], Scalar(255, 0, 0), 2, 8, 0);
putText(frame, format("i'm %s", (label == 19 ? "me" : "Unknow")), face_rects[i].tl(), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 0, 255), 2, 8);
}
imshow("frame", frame);
if (waitKey(FPS) == 27) {
break;
}
}
capture.release();
}