#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
init();
connect(ui->action_open_image, &QAction::triggered, [=]{this->open_image();});
connect(ui->action_open_video, &QAction::triggered, [=]{this->open_video();});
connect(ui->action_open_camera, &QAction::triggered, [=]{this->open_camera();});
connect(ui->action_close_camera, &QAction::triggered, [=]{this->close_camera();});
connect(ui->action_save_picture, &QAction::triggered, [=]{this->image_save();});
connect(ui->action_help_about, &QAction::triggered, [=]{this->help_about();});
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::closeEvent(QCloseEvent *event)
{
cap.release();
this->close();
delete ui;
}
void drawResult(cv::Mat& image, const std::vector<FaceResult>& faces)
{
for(auto& face : faces)
{
float score = face.info.at<float>(14);
cv::Rect faceRect(face.info.at<float>(0), face.info.at<float>(1), face.info.at<float>(2), face.info.at<float>(3));
cv::rectangle(image, faceRect, {0,0,255}, 2);
cv::putText(image, cv::format("%s: %.2f", face.name, score), cv::Point(faceRect.x, faceRect.y - 16), 1, 5, {0,0,255}, 2);
}
}
void MainWindow::init()
{
std::string detect_model_path = "yunet.onnx";
std::string recog_model_path = "face_recognizer_fast.onnx";
faceSolution->initFaceModels(detect_model_path, recog_model_path, "./face_db", true);
}
void MainWindow::call_yunet(cv::Mat& frame)
{
double start_time = (double)cv::getTickCount();
std::vector<FaceResult> faceResult;
faceSolution->detectFace(frame, faceResult); //人脸检测
faceSolution->matchFace(frame, faceResult); //人脸匹配
drawResult(frame, faceResult); //画出结果
double end_time = (double)cv::getTickCount();
double fps = cv::getTickFrequency() / (end_time - start_time);
double spend_time = (end_time - start_time) / cv::getTickFrequency();
std::string FPS = "FPS:" + cv::format("%.2f", fps) + " spend time:" + cv::format("%.2f", spend_time * 1000) + "ms";
statusBar()->showMessage(QString::fromStdString(FPS));
ui->label->setGeometry(80, 40, 640, 480);
int w = ui->label->width(), h = ui->label->height(), x = 0, y = 0;
if(frame.cols > ui->label->width())
{
w = ui->label->width();
h = frame.rows*ui->label->width()/frame.cols;
}
if(h > ui->label->height())
{
w = w * ui->label->height() / h;
h = ui->label->height();
}
x = (800 - w) / 2;
y = (600 - h) / 2 - 20;
ui->label->setGeometry(x, y, w, h);
ui->label->clear();
QImage qimage = QImage((const uchar*)frame.data, frame.cols, frame.rows, QImage::Format_RGB888).rgbSwapped();
ui->label->setPixmap(QPixmap::fromImage(qimage));
ui->label->show();
}
void MainWindow::open_image()
{
statusBar()->showMessage(u8"正在打开图像...");
QString qstr = QFileDialog::getOpenFileName(this,tr("Open File"),"home",tr("Images(*.png *.bmp *.jpg)"));
if(qstr.isEmpty()) return;
frame = cv::imread(qstr.toStdString());
if(frame.empty()) return;
call_yunet(frame);
}
void MainWindow::open_video()
{
statusBar()->showMessage(u8"正在打开视频...");
QString qstr = QFileDialog::getOpenFileName(this,tr("Open File"),"home",tr("Images(*.mp4 *.avi *.mkv)"));
if(qstr.isEmpty())
{
statusBar()->showMessage(u8"路径解析出错!");
return;
}
cap.open(qstr.toStdString());
while (cv::waitKey(30) < 0)
{
cap >> frame;
if(frame.empty()) break;
call_yunet(frame);
}
ui->label->clear();
}
void MainWindow::open_camera()
{
statusBar()->showMessage(u8"正在打开相机...");
cap.open(0);
while (cv::waitKey(30) < 0)
{
cap >> frame;
if(frame.empty()) break;
call_yunet(frame);
}
}
void MainWindow::close_camera()
{
cap.release();
ui->label->clear();
}
void MainWindow::image_save()
{
QString fileName = QFileDialog::getSaveFileName(this, "Save", QStandardPaths::writableLocation(QStandardPaths::PicturesLocation), "*.png");
if (fileName.isEmpty()) return;
QPixmap pixmap = ui->label->grab(ui->label->rect());
pixmap.save(fileName);
}
void MainWindow::help_about()
{
QMessageBox *box = new QMessageBox(QMessageBox::Information, QString::fromLocal8Bit("使用说明"),
QString::fromLocal8Bit(" 本软件提供了人脸识别的功能,\n 人脸截图需放在face_db文件夹下。\n\n"
" 由于开发周期短和本人能力有限,\n 其他功能还尚未完善,敬请谅解。"),
QMessageBox::Ok);
if(NULL!=box->button(QMessageBox::Ok))
{
box->button(QMessageBox::Ok)->setText(QString::fromLocal8Bit("确 定"));
}
box->setStyleSheet("QLabel{min-width: 240px;min-height: 180px;}");
box->exec();
}