mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <opencv2/opencv.hpp>
#include "opencv2/objdetect.hpp"
#include "opencv2/face.hpp"
#include <qimage.h>
#include <QTimer>
#include "opencv2/face/facerec.hpp"
using namespace cv;
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void Delay_MSec(unsigned int msec);
void OpenCamera();
QImage Mat2QImage(Mat cvImg);
bool Train();
private slots:
void on_pushButton_2_clicked();//open
void on_pushButton_4_clicked();//capture
void on_pushButton_clicked();//quit
private:
bool bLoad;
Mat imageMat;
VideoCapture _videoCapture;
CascadeClassifier cascade;
std::vector<Rect> rect;
Ptr<cv::face::EigenFaceRecognizer> modelEigenFace = nullptr;
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTime>
#include <QDebug>
#include <QDir>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
//级联分类器对象
//读取级联分类器
bLoad = cascade.load("../untitled/etc/haarcascades/haarcascade_frontalface_alt.xml");
modelEigenFace = cv::face::EigenFaceRecognizer::create();
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
//Mat转化为QImage
QImage MainWindow::Mat2QImage(Mat cvImg)
{
QImage qImg;
if(cvImg.channels()==3) //3 channels color image
{
//Converts an image from one color space to another
cv::cvtColor(cvImg,cvImg,COLOR_BGR2RGB);
qImg =QImage((const unsigned char*)(cvImg.data),
cvImg.cols, cvImg.rows,
cvImg.cols*cvImg.channels(),
QImage::Format_RGB888);
}
else if(cvImg.channels()==1) //grayscale image
{
qImg =QImage((const unsigned char*)(cvImg.data),
cvImg.cols,cvImg.rows,
cvImg.cols*cvImg.channels(),
QImage::Format_Indexed8);
}
else
{
qImg =QImage((const unsigned char*)(cvImg.data),
cvImg.cols,cvImg.rows,
cvImg.cols*cvImg.channels(),
QImage::Format_RGB888);
}
return qImg;
}
void MainWindow::OpenCamera()
{
if (_videoCapture.isOpened())
return;
_videoCapture.open(0);
if(_videoCapture.isOpened())
{
bool bTrain = this->Train();
while(1)
{
_videoCapture >> imageMat;
//画面翻转 参数3为1 代表Y轴翻转
flip(imageMat, imageMat, 1);
if (!imageMat.empty())
{
Mat imageMat_gray;
Mat predictImage;
Mat temp_gray;
cvtColor(imageMat, imageMat_gray, COLOR_BGR2GRAY);//转为灰度图
equalizeHist(imageMat_gray, imageMat_gray);//均衡化
cascade.detectMultiScale(imageMat_gray, rect, 1.1, 3, 0);//人脸检测
for (int i = 0; i < rect.size(); i++)
{
//取灰色人脸图像
Mat temp = imageMat(rect[i]);
cvtColor(temp, temp_gray, COLOR_BGR2GRAY);
cv::resize(temp_gray, predictImage, Size(100, 120));
//predict返回人脸 label
int predicted_label = -1;
if(bTrain)
predicted_label = modelEigenFace->predict(predictImage);
//框出人脸
rectangle(imageMat, rect[i], Scalar(0, 0, 255));
putText(imageMat, format("%s", (predicted_label == 12345 ? "PASS" : "FAIL")),
rect[i].tl(), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 0, 255));
}
//显示
QImage image = Mat2QImage(imageMat);
ui->label->setPixmap(QPixmap::fromImage(image));
}
Delay_MSec(10);
}
}
}
void MainWindow::on_pushButton_2_clicked()
{
if(bLoad && modelEigenFace != nullptr)
OpenCamera();
}
bool MainWindow::Train()
{
std::vector<int> labels;
std::vector<Mat> images;
QString path = "../untitled/myFace.jpg";
QFileInfo info(path);
if(!info.exists())
return false;
Mat temp = imread(path.toStdString(),0);
labels.push_back(12345);
images.push_back(temp);
modelEigenFace->train(images,labels);
modelEigenFace->save("../untitled/my_eigen_face_modelEigenFace.xml");
return true;
}
void MainWindow::on_pushButton_4_clicked()
{
Mat cap;
bool bWrite = false;
for (int i = 0; i < rect.size(); i++)
{
cv::resize(imageMat(rect[i]), cap, Size(100, 120));
cvtColor(cap,cap,COLOR_BGR2RGB);
bWrite = imwrite("../untitled/myFace.jpg", cap);
}
if(bWrite)
{
qDebug("videoCapture imwrite success,start train!");
this->Train();
}
}
void MainWindow::on_pushButton_clicked()
{
_videoCapture.release();
}
void MainWindow::Delay_MSec(unsigned int msec)
{
QEventLoop loop;//定义一个新的事件循环
QTimer::singleShot(msec, &loop, SLOT(quit()));//创建单次定时器,槽函数为事件循环的退出函数
loop.exec();//事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出
}
编译OpenCV+OpenCV_contrib见
QT + OPENCV + OpenCV_contrib + MINGW编译_weixin_44270564的博客-CSDN博客