Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "MainWindow.h"
- int main(int argc, char *argv[])
- {
- QApplication app(argc, argv);
- QApplication::setApplicationName("face-demo");
- QApplication::setApplicationVersion("0.6.2");
- QApplication::setOrganizationName("stlab");
- QTranslator qtTranslator;
- qtTranslator.load("qt_" + QLocale::system().name(), QApplication::applicationDirPath()+"/translations");
- app.installTranslator(&qtTranslator);
- QThreadPool::globalInstance()->setMaxThreadCount(4);
- try {
- MainWindow window;
- window.show();
- return app.exec();
- } catch (e_default e) {
- QMessageBox::critical(0, QString::fromUtf8("Ошибка инициализации"), e.what());
- return -1;
- }
- }
- MainWindow::MainWindow()
- : QMainWindow(nullptr)
- {
- _ui.setupUi(this);
- // сцена
- _scene = new QGraphicsScene (0, 0, _ui.viewWidget->width(), _ui.viewWidget->height());
- _scene->setBackgroundBrush(QBrush(Qt::black));
- _ui.viewWidget->setScene(_scene);
- _rect = _scene->addRect(QRectF(0, 0, _ui.viewWidget->width(), _barHeight + 10), QPen(Qt::white), QBrush(Qt::white));
- _rect->setY(_ui.viewWidget->height()-_barHeight);
- _rect->setZValue (10);
- _text = _scene->addText("");
- _text->document()->setDocumentMargin(0);
- _text->setTextWidth(_ui.viewWidget->width());
- _text->setZValue (20);
- _text->setY(_ui.viewWidget->height()-_barHeight);
- // настройки по умолчанию
- _rtspParams << "--aout=dummy" << "--vout=dummy" << "--network-caching=500";
- if (!QSettings().contains("inputMode")) QSettings().setValue("inputMode", "webcam");
- if (!QSettings().contains("webcamIndex")) QSettings().setValue("webcamIndex", 0);
- if (!QSettings().contains("turnCheck")) QSettings().setValue("turnCheck", false);
- if (!QSettings().contains("showMarks")) QSettings().setValue("showMarks", false);
- // интерфейс
- _ui.webcamCheck->setChecked(QSettings().value("inputMode").toString() == "webcam");
- _ui.ipcamCheck->setChecked(QSettings().value("inputMode").toString() == "ipcam");
- _ui.webcamSpin->setValue(QSettings().value("webcamIndex").toInt());
- _ui.turnCheck->setChecked(QSettings().value("turnCheck").toBool());
- _ui.landmarksCheck->setChecked(QSettings().value("showMarks").toBool());
- QObject::connect (&_viewTimer, &QTimer::timeout, this, &MainWindow::on_view);
- QObject::connect (&_verifyTimer, &QTimer::timeout, this, &MainWindow::on_progressed);
- QObject::connect (this, &MainWindow::startView, this, &MainWindow::startView);
- QObject::connect (this, &MainWindow::stopView, this, &MainWindow::stopView);
- // сети
- QStringList protos;
- QFile resource;
- resource.setFileName("://det1.prototxt");
- if (!resource.open(QFile::ReadOnly)) throw e_failure("MainWindow: Can't load resource");
- protos.push_back(resource.readAll());
- resource.setFileName("://det2_input.prototxt");
- if (!resource.open(QFile::ReadOnly)) throw e_failure("MainWindow: Can't load resource");
- protos.push_back(resource.readAll());
- resource.setFileName("://det2.prototxt");
- if (!resource.open(QFile::ReadOnly)) throw e_failure("MainWindow: Can't load resource");
- protos.push_back(resource.readAll());
- resource.setFileName("://det3_input.prototxt");
- if (!resource.open(QFile::ReadOnly)) throw e_failure("MainWindow: Can't load resource");
- protos.push_back(resource.readAll());
- resource.setFileName("://det3.prototxt");
- if (!resource.open(QFile::ReadOnly)) throw e_failure("MainWindow: Can't load resource");
- protos.push_back(resource.readAll());
- resource.setFileName("://det4.prototxt");
- if (!resource.open(QFile::ReadOnly)) throw e_failure("MainWindow: Can't load resource");
- protos.push_back(resource.readAll());
- _detector = new FaceDetectorMtcnn(QApplication::applicationDirPath()+"/data/", protos, 80, 0.75);
- resource.setFileName("://cnn-deploy-x128.prototxt");
- if (!resource.open(QFile::ReadOnly)) throw e_failure("MainWindow: Can't load resource");
- protos.push_back(resource.readAll());
- _extractor = new FaceExtractorStlab(QApplication::applicationDirPath()+"/data/", protos[6]);
- _headDetector = new HeadMoveDetector;
- _etalon = new FaceTemplateL2(*_extractor);
- // начальное состояние
- setState(AppState::NotRegistered);
- setState(FaceState::None);
- reloadUsers();
- startView();
- startProcess();
- }
- MainWindow::~MainWindow ()
- {
- stopProcess();
- stopView();
- delete_s(_etalon);
- delete_s(_headDetector);
- delete_s(_extractor);
- delete_s(_detector);
- }
- void MainWindow::stopView()
- {
- _viewTimer.stop();
- for (auto i: _items) delete i;
- _items.clear();
- delete_s (_pixmap);
- delete_s (_input);
- _frame.setTo(cv::Scalar(0,0,0));
- }
- void MainWindow::startView()
- {
- try {
- #ifdef WITH_IPCAM
- _input = new VideoInputStream();
- if (QSettings().value("inputMode").toString() == "webcam") {
- _input->openDevice(QSettings().value("webcamIndex").toInt(), -1, _frameSize);
- setState(StreamState::Ok);
- } else if (QSettings().value("inputMode").toString() == "ipcam") {
- _input->openVideoStream(QSettings().value("rtspUrl").toString(), _frameSize, {}, {}, _rtspParams, VideoInputStream::Mode::KeepAspectRatio);
- setState(StreamState::Accessing);
- QTimer::singleShot(_streamTimeout, this, &MainWindow::on_streamTimeout);
- }
- #else
- _input = new VideoInput();
- if (QSettings().value("inputMode").toString() == "webcam") {
- _input->openDevice(QSettings().value("webcamIndex").toInt(), -1, _frameSize);
- }
- #endif
- _viewTimer.start (1000/_showFps);
- } catch (...) {
- setState(StreamState::Failed);
- }
- draw();
- }
- void MainWindow::stopProcess()
- {
- _running = false;
- if (_processingThread.isRunning()) _processingThread.waitForFinished();
- _mutex.lock();
- _mask.clear();
- _mutex.unlock();
- }
- void MainWindow::startProcess()
- {
- try {
- _running = true;
- _processingThread = QtConcurrent::run (this, &MainWindow::process);
- } catch (e_default e) {
- qDebug() << e.what();
- }
- }
- void MainWindow::on_view()
- {
- try {
- if (!_input->isFrameReady()) return;
- _mutex2.lock();
- _input->getFrame (_frame);
- _mutex2.unlock();
- if (!_frame.cols || !_frame.rows) throw e_failure("MainWindow: Empty frame");
- for (auto i: _items) delete(i);
- _items.clear();
- delete_s(_pixmap);
- _pixmap = _scene->addPixmap(QPixmap::fromImage(convert(_frame)));
- if (QSettings().value("showMarks").toBool() && _mask.size() == 7) {
- _mutex.lock();
- _items.push_back(_scene->addRect(_mask[0].x(), _mask[0].y(),
- _mask[1].x()-_mask[0].x(), _mask[1].y()-_mask[0].y(), QPen(Qt::yellow)));
- _items.push_back(_scene->addRect(_mask[2].x(), _mask[2].y(), 4, 4, QPen(Qt::yellow)));
- _items.push_back(_scene->addRect(_mask[3].x(), _mask[3].y(), 4, 4, QPen(Qt::yellow)));
- _items.push_back(_scene->addRect(_mask[4].x(), _mask[4].y(), 4, 4, QPen(Qt::yellow)));
- _items.push_back(_scene->addRect(_mask[5].x(), _mask[5].y(), 4, 4, QPen(Qt::yellow)));
- _items.push_back(_scene->addRect(_mask[6].x(), _mask[6].y(), 4, 4, QPen(Qt::yellow)));
- _mutex.unlock();
- }
- setState(StreamState::Ok);
- } catch (e_default e) {
- qDebug() << e.what();
- setState(StreamState::Skipping);
- } catch (...) {
- setState(StreamState::Skipping);
- }
- draw();
- if (_mutex2.tryLock()) _mutex2.unlock();
- }
- void MainWindow::on_progressed()
- {
- if (_appState != AppState::Testing) {
- _verifyTimer.stop();
- } else {
- _progress++;
- _rect->setRect(QRectF(0, 0, _ui.viewWidget->width() * MIN(100, _progress) / 100, _barHeight + 10));
- if (_progress >= 100) {
- setState(AppState::Ready);
- setState(FaceState::Rejected);
- }
- }
- }
- void MainWindow::on_streamTimeout()
- {
- if (_streamState == StreamState::Accessing) {
- setState(StreamState::Failed);
- draw();
- }
- }
- void MainWindow::draw ()
- {
- _ui.label_a->clear();
- _ui.label_b->clear();
- switch (_streamState)
- {
- case StreamState::Failed:
- _text->setHtml(tr("<body style=\"%0\"><br>Невозможно открыть видеопоток<br></body>").arg(_warningStyle));
- return;
- case StreamState::Skipping:
- _text->setHtml(tr("<body style=\"%0\"><br>Ошибка чтения кадра из видеопотока<br></body>").arg(_warningStyle));
- return;
- case StreamState::Accessing:
- _text->setHtml(tr("<body style=\"%0\"><br>Чтение видеопотока...<br></body>").arg(_warningStyle));
- return;
- case StreamState::Ok:
- break;
- }
- switch (_appState) {
- case AppState::NotRegistered:
- _rect->setRect(QRectF(0, 0, _ui.viewWidget->width(), _barHeight + 10));
- _text->setHtml(tr("<body style=\"%0\"><br>Пользователь не зарегистрирован<br></body>").arg(_grayStyle));
- break;
- case AppState::Training:
- if (_progress < 100) _text->setHtml(tr("<body style=\"%0\"><br>Регистрация лица... %1%<br></body>").arg(_grayStyle).arg(_progress));
- else _text->setHtml(tr("<body style=\"%0\"><br>Формирование шаблона...<br></body>").arg(_grayStyle));
- break;
- case AppState::Ready:
- _rect->setRect(QRectF(0, 0, _ui.viewWidget->width(), _barHeight + 10));
- _text->setHtml(tr("<body style=\"%0\"><br>Готово к работе<br></body>").arg(_grayStyle));
- break;
- case AppState::Testing:
- _text->setHtml(tr("<body style=\"%0\"><br>Верификация... %1%<br></body>").arg(_grayStyle).arg(_progress));
- _ui.label_a->setText(tr("Совпадение: %0%").arg(_similarity));
- if (QSettings().value("turnCheck").toBool()) _ui.label_b->setText(tr("Живое лицо: %0").arg(_moved?"да":"нет"));
- break;
- }
- switch (_faceState) {
- case FaceState::Accepted:
- _rect->setRect(QRectF(0, 0, _ui.viewWidget->width(), _barHeight + 10));
- _text->setHtml(tr("<body style=\"%0\"><br>Верификация успешна (%1 мс)<br></body>").arg(_greenStyle).arg(_verificationTime));
- break;
- case FaceState::Rejected:
- _rect->setRect(QRectF(0, 0, _ui.viewWidget->width(), _barHeight + 10));
- _text->setHtml(tr("<body style=\"%0\"><br>Верификация неудачна<br></body>").arg(_redStyle));
- break;
- case FaceState::Spoofing:
- _text->setHtml(tr("<body style=\"%0\"><br>Защита от фотографии: поверните голову<br></body>").arg(_yellowStyle));
- break;
- case FaceState::Noface:
- _text->setHtml(tr("<body style=\"%0\"><br>Лицо не обнаружено<br></body>").arg(_warningStyle));
- break;
- case FaceState::LowQuality:
- _text->setHtml(tr("<body style=\"%0\"><br>Недостаточное качество картинки<br></body>").arg(_warningStyle));
- break;
- case FaceState::None:
- break;
- }
- _ui.label_c->setText(tr("%0 мс / кадр").arg(_frameTime));
- }
- void MainWindow::reloadUsers()
- {
- _ui.usersList->clear();
- QDir dir(_path);
- for (auto file: dir.entryList({"*.face"})) {
- _ui.usersList->addItem(file.left(file.size()-5));
- }
- }
- QString MainWindow::getInput(QString header, QString label, QString text)
- {
- QInputDialog dialog(this);
- dialog.setWindowTitle(header);
- dialog.setLabelText(label);
- dialog.setTextValue(text);
- dialog.resize(geometry().width()-64, -1);
- return dialog.exec() ? dialog.textValue() : "";
- }
- void MainWindow::process()
- {
- while (_running) {
- QDateTime timestamp = QDateTime::currentDateTime();
- try {
- if (!_frame.cols || !_frame.rows) throw e_failure ("MainWindow: Empty frame");
- _mutex2.lock();
- _temp = _frame.clone();
- _mutex2.unlock();
- _detector->processDownScale(_temp, 2);
- _mutex.lock();
- _mask.clear();
- _mutex.unlock();
- if (_detector->facesFound()) {
- _mask.push_back(QPointF(_detector->rect().x,
- _detector->rect().y));
- _mask.push_back(QPointF(_detector->rect().x+_detector->rect().width,
- _detector->rect().y+_detector->rect().height));
- _mask.push_back(QPointF(_detector->landmarks()[0].x+_detector->rect().x,
- _detector->landmarks()[0].y+_detector->rect().y));
- _mask.push_back(QPointF(_detector->landmarks()[1].x+_detector->rect().x,
- _detector->landmarks()[1].y+_detector->rect().y));
- _mask.push_back(QPointF(_detector->landmarks()[4].x+_detector->rect().x,
- _detector->landmarks()[4].y+_detector->rect().y));
- _mask.push_back(QPointF(_detector->landmarks()[3].x+_detector->rect().x,
- _detector->landmarks()[3].y+_detector->rect().y));
- _mask.push_back(QPointF(_detector->landmarks()[2].x+_detector->rect().x,
- _detector->landmarks()[2].y+_detector->rect().y));
- }
- switch (_appState) {
- case AppState::Testing:
- if (!_detector->facesFound()) {
- setState(FaceState::Noface);
- throw e_runtime ("MainWindow: No face detected");
- }
- _aligned = _extractor->alignMtcnn(_temp, *_detector);
- if (!_verified) {
- _pattern = _extractor->extract(_aligned);
- _etalon->verifySample(_pattern, &_similarity);
- _verified = _similarity >= 100;
- }
- else if (!_moved) {
- cv::Rect actual = _extractor->usedFaceRect();
- if (_faceRect.area() != 0) {
- cv::Rect is = actual & _faceRect;
- float isf = (float)is.area() / (float)actual.area();
- qDebug() << "intersection" << isf;
- if (isf < 0.75f)
- _headDetector->reset();
- }
- float qual = _extractor->quality();
- qDebug() << "quality" << qual;
- if (qual >= _qualThreshold) {
- if (_progress != 100)
- setState(FaceState::Spoofing);
- _moved = _headDetector->addFrame(_extractor->alignedCenter(), _extractor->alignedNose());
- }
- else {
- if (_progress != 100)
- setState(FaceState::LowQuality);
- _moved = _headDetector->addEmptyFrame();
- }
- }
- if (_verified) {
- if (_moved) {
- _progress = 100;
- setState(AppState::Ready);
- setState(FaceState::Accepted);
- _verificationTime = _timestamp.msecsTo(QDateTime::currentDateTime());
- }
- }
- _faceRect = _extractor->usedFaceRect();
- break;
- case AppState::Training:
- if (!_detector->facesFound()) {
- setState(FaceState::Noface);
- throw e_failure ("MainWindow: No face detected");
- }
- setState(FaceState::None);
- _pattern = _extractor->extractMtcnnAlign(_temp, *_detector);
- if (_etalon->addSample(_pattern)) {
- _progress += 100/_trainFrames;
- }
- if (_progress >= 100) {
- saveEtalon();
- }
- break;
- default:;
- }
- } catch (e_default e) {
- qDebug() << e.what();
- _similarity = 0;
- } catch (...) {
- _similarity = 0;
- }
- _frameTime = timestamp.msecsTo(QDateTime::currentDateTime());
- }
- }
- void MainWindow::setState(AppState state)
- {
- _appState = state;
- switch (state) {
- case AppState::NotRegistered:
- _ui.addOnlineButton->setEnabled(_streamState == StreamState::Ok);
- _ui.addOnlineButton->setText(tr("Регистрировать с камеры"));
- _ui.addPhotoButton->setEnabled(true);
- _ui.removeButton->setEnabled(false);
- _ui.testButton->setEnabled(false);
- _ui.testButton->setText(tr("Верифицировать"));
- _ui.settingsBox->setEnabled(true);
- _ui.usersList->setEnabled(true);
- break;
- case AppState::Training:
- _ui.addOnlineButton->setEnabled(true);
- _ui.addOnlineButton->setText(tr("Остановить"));
- _ui.addPhotoButton->setEnabled(false);
- _ui.removeButton->setEnabled(false);
- _ui.testButton->setEnabled(false);
- _ui.testButton->setText(tr("Верифицировать"));
- _ui.settingsBox->setEnabled(false);
- _ui.usersList->setEnabled(false);
- break;
- case AppState::Ready:
- _ui.addOnlineButton->setEnabled(_streamState == StreamState::Ok);
- _ui.addOnlineButton->setText(tr("Регистрировать с камеры"));
- _ui.addPhotoButton->setEnabled(true);
- _ui.removeButton->setEnabled(true);
- _ui.testButton->setEnabled(_streamState == StreamState::Ok);
- _ui.testButton->setText(tr("Верифицировать"));
- _ui.settingsBox->setEnabled(true);
- _ui.usersList->setEnabled(true);
- break;
- case AppState::Testing:
- _ui.addOnlineButton->setEnabled(false);
- _ui.addOnlineButton->setText(tr("Регистрировать с камеры"));
- _ui.addPhotoButton->setEnabled(false);
- _ui.removeButton->setEnabled(false);
- _ui.testButton->setEnabled(true);
- _ui.testButton->setText(tr("Остановить"));
- _ui.settingsBox->setEnabled(false);
- _ui.usersList->setEnabled(false);
- break;
- }
- }
- void MainWindow::setState(MainWindow::FaceState status)
- {
- _faceState = status;
- }
- void MainWindow::setState(MainWindow::StreamState error)
- {
- _streamState = error;
- setState(_appState);
- }
- void MainWindow::on_testButton_clicked()
- {
- stopProcess();
- try {
- _ui.testButton->setEnabled(false);
- if (_appState == AppState::Testing) {
- setState(AppState::Ready);
- setState(FaceState::None);
- _verifyTimer.stop();
- } else {
- _progress = 0;
- _verifyTimer.start(_verifyTimeout/100);
- _verified = false;
- _moved = !QSettings().value("turnCheck").toBool();
- _headDetector->reset();
- setState(AppState::Testing);
- setState(FaceState::None);
- _timestamp = QDateTime::currentDateTime();
- }
- } catch (e_default e) {
- qDebug() << e.what();
- }
- startProcess();
- }
- void MainWindow::on_ipcamButton_clicked()
- {
- try {
- QString text = getInput(tr("Изменение настроек"), tr("Укажите адрес RTSP потока камеры:"), QSettings().value("rtspUrl").toString());
- if (!text.isEmpty()) {
- QSettings().setValue("rtspUrl", text);
- _ui.ipcamCheck->setChecked(true);
- on_ipcamCheck_toggled(true);
- }
- } catch (e_default e) {
- qDebug() << e.what();
- }
- }
- void MainWindow::on_webcamSpin_valueChanged(int arg)
- {
- try {
- QSettings().setValue("webcamIndex", arg);
- _ui.webcamCheck->setChecked(true);
- on_webcamCheck_toggled(true);
- } catch (e_default e) {
- qDebug() << e.what();
- }
- }
- void MainWindow::on_webcamCheck_toggled(bool checked)
- {
- try {
- if (checked) {
- QSettings().setValue("inputMode", "webcam");
- stopView();
- startView();
- on_usersList_currentIndexChanged(_ui.usersList->currentIndex());
- }
- } catch (e_default e) {
- qDebug() << e.what();
- }
- }
- void MainWindow::on_ipcamCheck_toggled(bool checked)
- {
- try {
- if (checked) {
- QSettings().setValue("inputMode", "ipcam");
- stopView();
- startView();
- on_usersList_currentIndexChanged(_ui.usersList->currentIndex());
- }
- } catch (e_default e) {
- qDebug() << e.what();
- }
- }
- void MainWindow::on_turnCheck_toggled(bool checked)
- {
- try {
- QSettings().setValue("turnCheck", checked);
- } catch (e_default e) {
- qDebug() << e.what();
- }
- }
- void MainWindow::on_addOnlineButton_clicked()
- {
- stopProcess();
- try {
- _ui.addOnlineButton->setEnabled(false);
- if (_appState == AppState::Training) {
- setState(AppState::NotRegistered);
- setState(FaceState::None);
- } else {
- _username = getInput(tr("Добавление пользователя"), tr("Введите имя пользователя:"), QUuid::createUuid().toString());
- if (_username.isEmpty()) return;
- _progress = 0;
- if (_etalon) _etalon->clear();
- setState(AppState::Training);
- setState(FaceState::None);
- }
- } catch (e_default e) {
- qDebug() << e.what();
- }
- startProcess();
- }
- void MainWindow::on_addPhotoButton_clicked()
- {
- stopProcess();
- try {
- _username = getInput(tr("Добавление пользователя"), tr("Введите имя пользователя:"), QUuid::createUuid().toString());
- if (_username.isEmpty()) return;
- QString path = QFileDialog::getOpenFileName(this, tr("Выберите фотографию пользователя"));
- _temp = cv::imread(std::string(path.toLocal8Bit()));
- qDebug() << "photo:" << _temp.rows << _temp.cols;
- if (!_detector->process(_temp)) {
- setState(FaceState::Noface);
- return;
- }
- _pattern = _extractor->extractMtcnnAlign(_temp, *_detector);
- _etalon->clear();
- if (_etalon->addSample(_pattern)) {
- saveEtalon();
- } else {
- setState(AppState::NotRegistered);
- }
- } catch (e_default e) {
- qDebug() << e.what();
- }
- startProcess();
- }
- void MainWindow::on_removeButton_clicked()
- {
- stopProcess();
- try {
- QString path = QString("%0/%1.face").arg(_path).arg(_ui.usersList->currentText());
- QFile::remove(path);
- reloadUsers();
- } catch (e_default e) {
- qDebug() << e.what();
- }
- startProcess();
- }
- void MainWindow::on_landmarksCheck_toggled(bool checked)
- {
- try {
- QSettings().setValue("showMarks", checked);
- } catch (e_default e) {
- qDebug() << e.what();
- }
- }
- void MainWindow::on_usersList_currentIndexChanged(int index)
- {
- try {
- if (index >= 0) {
- _username = _ui.usersList->currentText();
- _etalon->clear();
- _etalon->load(QString("%0/%1.face").arg(_path).arg(_username));
- setState(AppState::Ready);
- setState(FaceState::None);
- } else {
- setState(AppState::NotRegistered);
- setState(FaceState::None);
- }
- } catch (e_default e) {
- qDebug() << e.what();
- }
- }
- void MainWindow::saveEtalon()
- {
- _progress = 100;
- setState(AppState::Ready);
- QDir().mkpath(_path);
- _etalon->save(QString("%0/%1.face").arg(_path).arg(_username));
- reloadUsers();
- _ui.usersList->setCurrentIndex(_ui.usersList->findText(_username, Qt::MatchExactly));
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement