opencv c++人脸检测与识别
- 库依赖
opencv的人脸检测用到扩展库,需要自己源码编译。
- 流程
采集人脸图片 --> 训练数据集 --> 模型保存。
采集人脸图片 --> 检测人脸区域 --> 放入模型预测
- 代码
头文件:
#include "face/facerec.hpp" #include "opencv.hpp" #include <vector> using namespace cv; using namespace std;
分类器
cv::CascadeClassifier faceCascade; cv::Ptr<cv::face::LBPHFaceRecognizer> faceReco; QString str = "C:/msvc2017_64/opencv454/etc/haarcascades/haarcascade_frontalface_alt.xml"; if(!faceCascade.load(str.toStdString())){ qWarning() << "load failed:" << str; return ; } faceReco = cv::face::LBPHFaceRecognizer::create();
训练样本
vector<Mat> images; vector<int> labels; for(int i = 1; i < 7; i++){ QString strfile = QString("%2/3/%1.png").arg(i) .arg(qApp->applicationDirPath()); cv::Mat mat = imread(strfile.toStdString(), IMREAD_GRAYSCALE); if(mat.empty()){ continue; } vector<Rect> faceRect; faceCascade.detectMultiScale(mat, faceRect); if(faceRect.empty()){ continue; } Mat matface = mat(faceRect.front()); images.push_back(matface); labels.push_back(3); } for(int i = 1; i < 7; i++){ QString strfile = QString("%2/2/%1.png").arg(i) .arg(qApp->applicationDirPath()); cv::Mat mat = imread(strfile.toStdString(), IMREAD_GRAYSCALE); if(mat.empty()){ continue; } vector<Rect> faceRect; faceCascade.detectMultiScale(mat, faceRect); if(faceRect.empty()){ continue; } Mat matface = mat(faceRect.front()); images.push_back(matface); labels.push_back(2); } for(int i = 1; i < 9; i++){ QString strfile = QString("%2/1/%1.png").arg(i) .arg(qApp->applicationDirPath()); cv::Mat mat = imread(strfile.toStdString(), IMREAD_GRAYSCALE); if(mat.empty()){ continue; } vector<Rect> faceRect; faceCascade.detectMultiScale(mat, faceRect); if(faceRect.empty()){ continue; } Mat matface = mat(faceRect.front()); images.push_back(matface); labels.push_back(1); } if(!images.empty()){ faceReco->train(images, labels); faceReco->setLabelInfo(1, "A"); faceReco->setLabelInfo(2, "B"); faceReco->setLabelInfo(3, "C"); }
保存与加载
QString strresult = QString("%1/facedata.yml").arg(qApp->applicationDirPath()); faceReco->save(strresult.toStdString()); faceReco->read(strresult.toStdString());
识别与预测
cv::Mat matclr = listMats.takeLast().clone(); cv::Mat mat; cv::cvtColor(matclr, mat, cv::COLOR_BGR2GRAY); QTime timecost; timecost.restart(); vector<Rect> faceRect; faceCascade.detectMultiScale(mat, faceRect); for(int i = 0; i < faceRect.size(); i++){ rectangle(matclr, faceRect[i], CV_RGB(255, 0, 0)); } // qDebug() << "detect cost:" << timecost.elapsed(); if(faceRect.empty()){ emit sigMatResult(matclr); return; } timecost.restart(); int label = -1; double dvalue = 0; Mat matface = mat(faceRect.front()); faceReco->predict(matface, label, dvalue); string name = faceReco->getLabelInfo(label); if(dvalue < 60){ QString str = QString("%1(%2)").arg(QString::fromStdString(name)).arg((int)dvalue); putText(matclr, str.toStdString(), faceRect.front().tl(), FONT_HERSHEY_SIMPLEX, 1.0, CV_RGB(0,255,0)); }else{ qDebug() << "predict:" << QString::fromStdString(name) << dvalue; } emit sigMatResult(matclr);
运行效果